Exerciseur niveau lycée réalisé avec GeoGebra

Tout ce qui concerne par exemple les outils de calcul numérique, de calcul formel ou de géométrie.
[participation réservée aux membres inscrits]
Règles du forum
Merci de soigner la rédaction de vos messages et de consulter ce sujet avant de poster. Pensez également à utiliser la fonction recherche du forum.
joelGa

Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par joelGa »

Bonjour
J'ai réalisé une série d'exercices interactifs en ligne à l'aide d'Applets GeoGebra.
Exercices de mathématiques au lycée Valin

http://maths.valin-sciences.fr/maths/ex ... index.html

Ces exercices peuvent certainement être utiles aux lycéens.
Bonne visite!
Joël
Arnaud
Modérateur général
Modérateur général
Messages : 7095
Inscription : lundi 28 août 2006, 13:18
Localisation : Allemagne

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par Arnaud »

Merci pour ce partage de documents ;) ( je connaissais déjà la page )
Arnaud
Un peu d'info - Pyromaths - Pas d'aide en MP (non plus)
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par projetmbc »

Au premier coup d'oeil, les exercices proposés semblent très bien vus et aussi très bien conçus.

Il reste à tester la gestion des réponses, ce que je ferais dès que je pourrais.

Question technique : comment sont faits les exos ? Te sers-tu de programmes pour t'aider ou fais-tu tout "à la main" ?
joelGa

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par joelGa »

Question technique : comment sont faits les exos ? Te sers-tu de programmes pour t'aider ou fais-tu tout "à la main" ?
Non je programme tout (HTML et Javascript) à la main sur le bloc-note de Window.

Merci pour les compliments

Joël
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par projetmbc »

Sacrée motivation.

Je vais me faire d'ici la rentrée scolaire prochaine, enfin je l'espère, des outils Python pour fabriquer "facilement" ce type d'exercices. L'idée étant de taper une sorte de script dans un fichier de type TXT, et ensuite de faire faire au programme Python la traduction GeoGebra, CarMetal, ..., HTML, JS. J'utiliserais aussi sûrement un peu de PhP pour autoriser l'utilisateur à taper des formules comme avec une calculatrice (même si une solution tout en JS me conviendrait plus).

Pour l'affichage des formules, je passerais par MathJax, pour l'interface graphique par jQuery, et côté applets, il y aura GeoGebra, CarMetal et peut-être aussi JavaView et/ou JMath 3D.

Il me reste un problème de taille : avoir un outil de calcul formel en ligne... Peut-être que GeoGebraCAS permettra cela.
Arnaud
Modérateur général
Modérateur général
Messages : 7095
Inscription : lundi 28 août 2006, 13:18
Localisation : Allemagne

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par Arnaud »

@projetmbc : je suppose que tu n'as pas de serveur dédié, non ?
Arnaud
Un peu d'info - Pyromaths - Pas d'aide en MP (non plus)
kojak
Modérateur général
Modérateur général
Messages : 10414
Inscription : samedi 18 novembre 2006, 19:50

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par kojak »

projetmbc a écrit : Il me reste un problème de taille : avoir un outil de calcul formel en ligne...
Xcas en ligne existe.
Pas d'aide par MP.
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par projetmbc »

Merci.

Du PhP semble être utilisé. Donc cela me semble accessible. Par contre, est-ce "appelable" depuis un site perso. ? "J'va" aller "d'mander" cela sur le forum de giac.
joelGa

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par joelGa »

projetmbc a écrit :Sacrée motivation.

Je vais me faire d'ici la rentrée scolaire prochaine, enfin je l'espère, des outils Python pour fabriquer "facilement" ce type d'exercices. L'idée étant de taper une sorte de script dans un fichier de type TXT, et ensuite de faire faire au programme Python la traduction GeoGebra, CarMetal, ..., HTML, JS. J'utiliserais aussi sûrement un peu de PhP pour autoriser l'utilisateur à taper des formules comme avec une calculatrice (même si une solution tout en JS me conviendrait plus).

Pour l'affichage des formules, je passerais par MathJax, pour l'interface graphique par jQuery, et côté applets, il y aura GeoGebra, CarMetal et peut-être aussi JavaView et/ou JMath 3D.

Il me reste un problème de taille : avoir un outil de calcul formel en ligne... Peut-être que GeoGebraCAS permettra cela.
Bonsoir projettmbc

Vaste projet :!:
Pour ma part, je pense que la prochaine version de GeoGebra me permettra de faire des choses plus intéressantes.
Connaitrais tu par hasard une fonction javascript qui aurait comme but de traduire une expression (comme on peut l'entrer sur une calculette) en code LaTex:
Par exemple: si la fonction recevait la chaîne "((x²+3)^3)/ (3x^3+2/x) " elle renverrait la chaîne " \frac{(x^2+3)^3^}{3x^3+\frac{2}{x}}" etc..
Ce ne doit pas être trop compliqué à programmer mais je n'ai pas encore eu le temps de le faire, alors si cela existe déjà ....

Joël
Francky
Utilisateur éprouvé
Utilisateur éprouvé
Messages : 681
Inscription : dimanche 11 avril 2010, 14:01

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par Francky »

joelGa a écrit :
projetmbc a écrit :Sacrée motivation.

Je vais me faire d'ici la rentrée scolaire prochaine, enfin je l'espère, des outils Python pour fabriquer "facilement" ce type d'exercices. L'idée étant de taper une sorte de script dans un fichier de type TXT, et ensuite de faire faire au programme Python la traduction GeoGebra, CarMetal, ..., HTML, JS. J'utiliserais aussi sûrement un peu de PhP pour autoriser l'utilisateur à taper des formules comme avec une calculatrice (même si une solution tout en JS me conviendrait plus).

Pour l'affichage des formules, je passerais par MathJax, pour l'interface graphique par jQuery, et côté applets, il y aura GeoGebra, CarMetal et peut-être aussi JavaView et/ou JMath 3D.

Il me reste un problème de taille : avoir un outil de calcul formel en ligne... Peut-être que GeoGebraCAS permettra cela.
Bonsoir projettmbc

Vaste projet :!:
Pour ma part, je pense que la prochaine version de GeoGebra me permettra de faire des choses plus intéressantes.
Connaitrais tu par hasard une fonction javascript qui aurait comme but de traduire une expression (comme on peut l'entrer sur une calculette) en code LaTex:
Par exemple: si la fonction recevait la chaîne "((x²+3)^3)/ (3x^3+2/x) " elle renverrait la chaîne " \frac{(x^2+3)^3^}{3x^3+\frac{2}{x}}" etc..
Ce ne doit pas être trop compliqué à programmer mais je n'ai pas encore eu le temps de le faire, alors si cela existe déjà ....

Joël
Personnellement, j'utiliserais xcas ou sagemath pour ce genre de requête, mais on revient au serveur dédié pour tout ça.
Autre avantage, au lieu de la sortie latex, on peut avoir du mathML, meilleur pour l'affichage web, et la possibilité de faire du copier-coller.
Linux Mint | TeXLive - TexMaker - asymptote | Python3 & C - Geany - Project Euler - SPOJ
Entia non sunt multiplicanda praeter necessitatem
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par projetmbc »

Bonsoir.
joelGa a écrit :Vaste projet :!:
Le plus pénible a été fait, à savoir l'analyseur de formules mathématiques et celui de documents.
joelGa a écrit :Pour ma part, je pense que la prochaine version de GeoGebra me permettra de faire des choses plus intéressantes.
Pourquoi ?
joelGa a écrit :Connaitrais tu par hasard une fonction javascript qui aurait comme but de traduire une expression (comme on peut l'entrer sur une calculette) en code LaTex
Non mais il serait étonnant que quelqu'un n'est pas fait quelque chose. Est-ce visible sur la toile ? Pas sûr étant donné le fonctionnement de Google et à mon avis l'aspect un peu confidentiel de ce genre de script.

Dans le cadre de mon projet je vais en faire un mais ce ne sera pas pour tout suite car j'ai prévu de fabriquer un programme qui traduira tous mes codes Python gérant les formules en code JavaScript.
joelGa a écrit :Ce ne doit pas être trop compliqué à programmer mais je n'ai pas encore eu le temps de le faire, alors si cela existe déjà ...
Tout dépend comment tu t'y prends. Est-ce pour permettre la saisie de formules aux élèves ?
Francky a écrit :Personnellement, j'utiliserais xcas ou sagemath pour ce genre de requête
En local, je passerais par SymPy normalement. Par contre, l'auteur de xcas en ligne semble prêt à proposer des fonctions javascripts pour appeler xcas directement sur le serveur de xcas en ligne. Ceci permettrait d'utiliser xcas depuis un site. Affaire à suivre...
Francky a écrit :Autre avantage, au lieu de la sortie latex, on peut avoir du mathML, meilleur pour l'affichage web, et la possibilité de faire du copier-coller.
Pour les sorties des formules, il y a MathJax qui est très, très bien.
Francky
Utilisateur éprouvé
Utilisateur éprouvé
Messages : 681
Inscription : dimanche 11 avril 2010, 14:01

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par Francky »

Pour MathJax, je sais, il me semble que c'est moi qui est lâché l'info sur la sortie 2.0.
MathJax utilise le MathML, mais tu dois mieux le savoir que moi, tout cela me dépasse beaucoup.

Pour XCas, c'est cool, cela devrait lui redonner un coup de pub important.
Powered by XCas.
Linux Mint | TeXLive - TexMaker - asymptote | Python3 & C - Geany - Project Euler - SPOJ
Entia non sunt multiplicanda praeter necessitatem
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par projetmbc »

J'avais oublié ma source... :oops:
projetmbc a écrit :
joelGa a écrit :Connaitrais tu par hasard une fonction javascript qui aurait comme but de traduire une expression (comme on peut l'entrer sur une calculette) en code LaTex
Non mais il serait étonnant que quelqu'un n'est pas fait quelque chose. Est-ce visible sur la toile ? Pas sûr étant donné le fonctionnement de Google et à mon avis l'aspect un peu confidentiel de ce genre de script.
J'ai encore perdu une occasion de me taire. Il faudrait tester ceci : JavaScript Expression Evaluator (je n'ai pas le temps de le faire en ce moment). La documentation parle de substitution, donc l'analyse de la formule est formelle.

Côté programmation, il va falloir voir si le code est modifiable rapidement. Avec un peu de chance, le programme est orienté objet, et un simple "sous-classage" sera possible (des infos ici).
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par projetmbc »

Curiosité quand tu nous tiens...

J'ai "zieuté" le code, et il semble modifiable et améliorable très facilement. Par exemple, la méthode toString, ligne 210, doit permettre de fabriquer "facilement" une méthode toLaTeX.

Ligne de codes correspondant à toString :

Code : Tout sélectionner

        toString: function (toJS) {
            var nstack = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(escapeValue(item.number_));
                }
                else if (type_ === TOP2) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = item.index_;
                    if (toJS && f == "^") {
                        nstack.push("Math.pow(" + n1 + "," + n2 + ")");
                    }
                    else {
                        nstack.push("(" + n1 + f + n2 + ")");
                    }
                }
                else if (type_ === TVAR) {
                    nstack.push(item.index_);
                }
                else if (type_ === TOP1) {
                    n1 = nstack.pop();
                    f = item.index_;
                    if (f === "-") {
                        nstack.push("(" + f + n1 + ")");
                    }
                    else {
                        nstack.push(f + "(" + n1 + ")");
                    }
                }
                else if (type_ === TFUNCALL) {
                    n1 = nstack.pop();
                    f = nstack.pop();
                    nstack.push(f + "(" + n1 + ")");
                }
                else {
                    throw new Error("invalid Expression");
                }
            }
            if (nstack.length > 1) {
                throw new Error("invalid Expression (parity)");
            }
            return nstack[0];
        }
Si quelqu'un le fait, ce serait sympa de poster ici la modification.
joelGa

Re: Exerciseur niveau lycée ralisé avec GeoGebra

Message non lu par joelGa »

projetmbc a écrit :Bonsoir.


joelGa a écrit :Pour ma part, je pense que la prochaine version de GeoGebra me permettra de faire des choses plus intéressantes.
Pourquoi ?
Je me suis mal exprimé : je pense faire des choses plus intéressantes que celles que j'ai faites .
La nouvelle version de GeoGebra intègrera entre autre du calcul formel .
Mais je suis très intéressé par ton projet.
Tiens nous au courant de son avancement.
Joël
joelGa

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par joelGa »

projetmbc a écrit :Curiosité quand tu nous tiens...

J'ai "zieuté" le code, et il semble modifiable et améliorable très facilement. Par exemple, la méthode toString, ligne 210, doit permettre de fabriquer "facilement" une méthode toLaTeX.

Si quelqu'un le fait, ce serait sympa de poster ici la modification.
Je vais regarder cela quand j'aurais un instant.
Mais si quelqu'un s'y attèle avant je suis preneur.
Joël
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par projetmbc »

Bonjour,
j'essaierais de regarder cela en fin de semaine.
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par projetmbc »

Bonjour,
j'ai fait très rapidement, mais c'est INCOMPLET, le code ci-dessous suivi d'un exemple d'utilisation. Ce qui a été modifié est entre les lignes
/////////////////////////////////////////.

parser.js

Code : Tout sélectionner

/*
 Based on ndef.parser, by Raphael Graf(r@undefined.ch)
 http://www.undefined.ch/mparser/index.html

 Source for this file :
    http://silentmatt.com/math/evaluator.php
*/
var Parser = function () {
    function object(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }

    var TNUMBER = 0;
    var TOP1 = 1;
    var TOP2 = 2;
    var TVAR = 3;
    var TFUNCALL = 4;

    function Token(type_, index_, prio_, number_) {
        this.type_ = type_;
        this.index_ = index_ || 0;
        this.prio_ = prio_ || 0;
        this.number_ = (number_ !== undefined && number_ !== null) ? number_ : 0;
        this.toString = function () {
            switch (this.type_) {
            case TNUMBER:
                return this.number_;
            case TOP1:
            case TOP2:
            case TVAR:
                return this.index_;
            case TFUNCALL:
                return "CALL";
            default:
                return "Invalid Token";
            }
        };
    }

    function Expression(tokens, ops1, ops2, functions) {
        this.tokens = tokens;
        this.ops1 = ops1;
        this.ops2 = ops2;
        this.functions = functions;
    }

    // Based on http://www.json.org/json2.js
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\'\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            "'" : "\\'",
            '\\': '\\\\'
        };

    function escapeValue(v) {
        if (typeof v === "string") {
            escapable.lastIndex = 0;
            return escapable.test(v) ?
                "'" + v.replace(escapable, function (a) {
                    var c = meta[a];
                    return typeof c === 'string' ? c :
                        '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                }) + "'" :
                "'" + v + "'";
        }
        return v;
    }

    Expression.prototype = {
        simplify: function (values) {
            values = values || {};
            var nstack = [];
            var newexpression = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(item);
                }
                else if (type_ === TVAR && (item.index_ in values)) {
                    item = new Token(TNUMBER, 0, 0, values[item.index_]);
                    nstack.push(item);
                }
                else if (type_ === TOP2 && nstack.length > 1) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = this.ops2[item.index_];
                    item = new Token(TNUMBER, 0, 0, f(n1.number_, n2.number_));
                    nstack.push(item);
                }
                else if (type_ === TOP1 && nstack.length > 0) {
                    n1 = nstack.pop();
                    f = this.ops1[item.index_];
                    item = new Token(TNUMBER, 0, 0, f(n1.number_));
                    nstack.push(item);
                }
                else {
                    while (nstack.length > 0) {
                        newexpression.push(nstack.shift());
                    }
                    newexpression.push(item);
                }
            }
            while (nstack.length > 0) {
                newexpression.push(nstack.shift());
            }

            return new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions));
        },

        substitute: function (variable, expr) {
            if (!(expr instanceof Expression)) {
                expr = new Parser().parse(String(expr));
            }
            var newexpression = [];
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TVAR && item.index_ === variable) {
                    for (var j = 0; j < expr.tokens.length; j++) {
                        var expritem = expr.tokens[j];
                        var replitem = new Token(expritem.type_, expritem.index_, expritem.prio_, expritem.number_);
                        newexpression.push(replitem);
                    }
                }
                else {
                    newexpression.push(item);
                }
            }

            var ret = new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions));
            return ret;
        },

        evaluate: function (values) {
            values = values || {};
            var nstack = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(item.number_);
                }
                else if (type_ === TOP2) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = this.ops2[item.index_];
                    nstack.push(f(n1, n2));
                }
                else if (type_ === TVAR) {
                    if (item.index_ in values) {
                        nstack.push(values[item.index_]);
                    }
                    else if (item.index_ in this.functions) {
                        nstack.push(this.functions[item.index_]);
                    }
                    else {
                        throw new Error("undefined variable: " + item.index_);
                    }
                }
                else if (type_ === TOP1) {
                    n1 = nstack.pop();
                    f = this.ops1[item.index_];
                    nstack.push(f(n1));
                }
                else if (type_ === TFUNCALL) {
                    n1 = nstack.pop();
                    f = nstack.pop();
                    if (f.apply && f.call) {
                        if (Object.prototype.toString.call(n1) == "[object Array]") {
                            nstack.push(f.apply(undefined, n1));
                        }
                        else {
                            nstack.push(f.call(undefined, n1));
                        }
                    }
                    else {
                        throw new Error(f + " is not a function");
                    }
                }
                else {
                    throw new Error("invalid Expression");
                }
            }
            if (nstack.length > 1) {
                throw new Error("invalid Expression (parity)");
            }
            return nstack[0];
        },

        toString: function (toJS) {
            var nstack = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(escapeValue(item.number_));
                }
                else if (type_ === TOP2) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = item.index_;
                    if (toJS && f == "^") {
                        nstack.push("Math.pow(" + n1 + "," + n2 + ")");
                    }
                    else {
                        nstack.push("(" + n1 + f + n2 + ")");
                    }
                }
                else if (type_ === TVAR) {
                    nstack.push(item.index_);
                }
                else if (type_ === TOP1) {
                    n1 = nstack.pop();
                    f = item.index_;
                    if (f === "-") {
                        nstack.push("(" + f + n1 + ")");
                    }
                    else {
                        nstack.push(f + "(" + n1 + ")");
                    }
                }
                else if (type_ === TFUNCALL) {
                    n1 = nstack.pop();
                    f = nstack.pop();
                    nstack.push(f + "(" + n1 + ")");
                }
                else {
                    throw new Error("invalid Expression");
                }
            }
            if (nstack.length > 1) {
                throw new Error("invalid Expression (parity)");
            }
            return nstack[0];
        },



/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////

        toLatex: function () {
            var nstack = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(escapeValue(item.number_));
                }
                else if (type_ === TOP2) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = item.index_;
                    if (f == "^") {
                        nstack.push("{" + n1 + "}^{" + n2 + "}");
                    }
                    else if (f == "*") {
                        nstack.push('(' + n1 + ')' + " \\times " + '(' + n2 + ')');
                    }
                    else if (f == "/") {
                        nstack.push("\\frac{" + n1 + "}{" + n2 + "}");
                    }
                    else {
                        nstack.push(n1 + " " + f + " " + n2);
                    }
                }
                else if (type_ === TVAR) {
                    nstack.push(item.index_);
                }
                else if (type_ === TOP1) {
                    n1 = nstack.pop();
                    f = item.index_;
                    if (f === "-") {
                        nstack.push("(" + f + n1 + ")");
                    }
                    else {
                        nstack.push(f + "(" + n1 + ")");
                    }
                }
                else if (type_ === TFUNCALL) {
                    n1 = nstack.pop();
                    f = nstack.pop();
                    nstack.push(f + "(" + n1 + ")");
                }
                else {
                    throw new Error("invalid Expression");
                }
            }
            if (nstack.length > 1) {
                throw new Error("invalid Expression (parity)");
            }
            return nstack[0];
        },


/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////


        variables: function () {
            var L = this.tokens.length;
            var vars = [];
            for (var i = 0; i < L; i++) {
                var item = this.tokens[i];
                if (item.type_ === TVAR && (vars.indexOf(item.index_) == -1)) {
                    vars.push(item.index_);
                }
            }

            return vars;
        },

        toJSFunction: function (param, variables) {
            var f = new Function(param, "with(Parser.values) { return " + this.simplify(variables).toString(true) + "; }");
            return f;
        }
    };

    function add(a, b) {
        return Number(a) + Number(b);
    }
    function sub(a, b) {
        return a - b;
    }
    function mul(a, b) {
        return a * b;
    }
    function div(a, b) {
        return a / b;
    }
    function mod(a, b) {
        return a % b;
    }
    function concat(a, b) {
        return "" + a + b;
    }

    function neg(a) {
        return -a;
    }

    function random(a) {
        return Math.random() * (a || 1);
    }
    function fac(a) { //a!
        a = Math.floor(a);
        var b = a;
        while (a > 1) {
            b = b * (--a);
        }
        return b;
    }

    // TODO: use hypot that doesn't overflow
    function pyt(a, b) {
        return Math.sqrt(a * a + b * b);
    }

    function append(a, b) {
        if (Object.prototype.toString.call(a) != "[object Array]") {
            return [a, b];
        }
        a = a.slice();
        a.push(b);
        return a;
    }

    function Parser() {
        this.success = false;
        this.errormsg = "";
        this.expression = "";

        this.pos = 0;

        this.tokennumber = 0;
        this.tokenprio = 0;
        this.tokenindex = 0;
        this.tmpprio = 0;

        this.ops1 = {
            "sin": Math.sin,
            "cos": Math.cos,
            "tan": Math.tan,
            "asin": Math.asin,
            "acos": Math.acos,
            "atan": Math.atan,
            "sqrt": Math.sqrt,
            "log": Math.log,
            "abs": Math.abs,
            "ceil": Math.ceil,
            "floor": Math.floor,
            "round": Math.round,
            "-": neg,
            "exp": Math.exp
        };

        this.ops2 = {
            "+": add,
            "-": sub,
            "*": mul,
            "/": div,
            "%": mod,
            "^": Math.pow,
            ",": append,
            "||": concat
        };

        this.functions = {
            "random": random,
            "fac": fac,
            "min": Math.min,
            "max": Math.max,
            "pyt": pyt,
            "pow": Math.pow,
            "atan2": Math.atan2
        };

        this.consts = {
            "E": Math.E,
            "PI": Math.PI
        };
    }

    Parser.parse = function (expr) {
        return new Parser().parse(expr);
    };

    Parser.evaluate = function (expr, variables) {
        return Parser.parse(expr).evaluate(variables);
    };

    Parser.Expression = Expression;

    Parser.values = {
        sin: Math.sin,
        cos: Math.cos,
        tan: Math.tan,
        asin: Math.asin,
        acos: Math.acos,
        atan: Math.atan,
        sqrt: Math.sqrt,
        log: Math.log,
        abs: Math.abs,
        ceil: Math.ceil,
        floor: Math.floor,
        round: Math.round,
        random: random,
        fac: fac,
        exp: Math.exp,
        min: Math.min,
        max: Math.max,
        pyt: pyt,
        pow: Math.pow,
        atan2: Math.atan2,
        E: Math.E,
        PI: Math.PI
    };

    var PRIMARY  = 1 << 0;
    var OPERATOR = 1 << 1;
    var FUNCTION = 1 << 2;
    var LPAREN   = 1 << 3;
    var RPAREN   = 1 << 4;
    var COMMA    = 1 << 5;
    var SIGN     = 1 << 6;
    var CALL     = 1 << 7;

    Parser.prototype = {
        parse: function (expr) {
            this.errormsg = "";
            this.success = true;
            var operstack = [];
            var tokenstack = [];
            this.tmpprio = 0;
            var expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
            var noperators = 0;
            this.expression = expr;
            this.pos = 0;

            while (this.pos < this.expression.length) {
                if (this.isOperator()) {
                    if (this.isSign() && (expected & SIGN)) {
                        if (this.isNegativeSign()) {
                            this.tokenprio = 2;
                            this.tokenindex = "-";
                            noperators++;
                            this.addfunc(tokenstack, operstack, TOP1);
                        }
                        expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                    }
                    else if (this.isComment()) {

                    }
                    else {
                        if ((expected & OPERATOR) === 0) {
                            this.error_parsing(this.pos, "unexpected operator");
                        }
                        noperators += 2;
                        this.addfunc(tokenstack, operstack, TOP2);
                        expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                    }
                }
                else if (this.isNumber()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected number");
                    }
                    var token = new Token(TNUMBER, 0, 0, this.tokennumber);
                    tokenstack.push(token);

                    expected = (OPERATOR | RPAREN | COMMA);
                }
                else if (this.isString()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected string");
                    }
                    var token = new Token(TNUMBER, 0, 0, this.tokennumber);
                    tokenstack.push(token);

                    expected = (OPERATOR | RPAREN | COMMA);
                }
                else if (this.isLeftParenth()) {
                    if ((expected & LPAREN) === 0) {
                        this.error_parsing(this.pos, "unexpected \"(\"");
                    }

                    if (expected & CALL) {
                        noperators += 2;
                        this.tokenprio = -2;
                        this.tokenindex = -1;
                        this.addfunc(tokenstack, operstack, TFUNCALL);
                    }

                    expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                }
                else if (this.isRightParenth()) {
                    if ((expected & RPAREN) === 0) {
                        this.error_parsing(this.pos, "unexpected \")\"");
                    }

                    expected = (OPERATOR | RPAREN | COMMA | LPAREN | CALL);
                }
                else if (this.isComma()) {
                    if ((expected & COMMA) === 0) {
                        this.error_parsing(this.pos, "unexpected \",\"");
                    }
                    this.addfunc(tokenstack, operstack, TOP2);
                    noperators += 2;
                    expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                }
                else if (this.isConst()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected constant");
                    }
                    var consttoken = new Token(TNUMBER, 0, 0, this.tokennumber);
                    tokenstack.push(consttoken);
                    expected = (OPERATOR | RPAREN | COMMA);
                }
                else if (this.isOp2()) {
                    if ((expected & FUNCTION) === 0) {
                        this.error_parsing(this.pos, "unexpected function");
                    }
                    this.addfunc(tokenstack, operstack, TOP2);
                    noperators += 2;
                    expected = (LPAREN);
                }
                else if (this.isOp1()) {
                    if ((expected & FUNCTION) === 0) {
                        this.error_parsing(this.pos, "unexpected function");
                    }
                    this.addfunc(tokenstack, operstack, TOP1);
                    noperators++;
                    expected = (LPAREN);
                }
                else if (this.isVar()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected variable");
                    }
                    var vartoken = new Token(TVAR, this.tokenindex, 0, 0);
                    tokenstack.push(vartoken);

                    expected = (OPERATOR | RPAREN | COMMA | LPAREN | CALL);
                }
                else if (this.isWhite()) {
                }
                else {
                    if (this.errormsg === "") {
                        this.error_parsing(this.pos, "unknown character");
                    }
                    else {
                        this.error_parsing(this.pos, this.errormsg);
                    }
                }
            }
            if (this.tmpprio < 0 || this.tmpprio >= 10) {
                this.error_parsing(this.pos, "unmatched \"()\"");
            }
            while (operstack.length > 0) {
                var tmp = operstack.pop();
                tokenstack.push(tmp);
            }
            if (noperators + 1 !== tokenstack.length) {
                //print(noperators + 1);
                //print(tokenstack);
                this.error_parsing(this.pos, "parity");
            }

            return new Expression(tokenstack, object(this.ops1), object(this.ops2), object(this.functions));
        },

        evaluate: function (expr, variables) {
            return this.parse(expr).evaluate(variables);
        },

        error_parsing: function (column, msg) {
            this.success = false;
            this.errormsg = "parse error [column " + (column) + "]: " + msg;
            throw new Error(this.errormsg);
        },

//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

        addfunc: function (tokenstack, operstack, type_) {
            var operator = new Token(type_, this.tokenindex, this.tokenprio + this.tmpprio, 0);
            while (operstack.length > 0) {
                if (operator.prio_ <= operstack[operstack.length - 1].prio_) {
                    tokenstack.push(operstack.pop());
                }
                else {
                    break;
                }
            }
            operstack.push(operator);
        },

        isNumber: function () {
            var r = false;
            var str = "";
            while (this.pos < this.expression.length) {
                var code = this.expression.charCodeAt(this.pos);
                if ((code >= 48 && code <= 57) || code === 46) {
                    str += this.expression.charAt(this.pos);
                    this.pos++;
                    this.tokennumber = parseFloat(str);
                    r = true;
                }
                else {
                    break;
                }
            }
            return r;
        },

        // Ported from the yajjl JSON parser at http://code.google.com/p/yajjl/
        unescape: function(v, pos) {
            var buffer = [];
            var escaping = false;

            for (var i = 0; i < v.length; i++) {
                var c = v.charAt(i);

                if (escaping) {
                    switch (c) {
                    case "'":
                        buffer.push("'");
                        break;
                    case '\\':
                        buffer.push('\\');
                        break;
                    case '/':
                        buffer.push('/');
                        break;
                    case 'b':
                        buffer.push('\b');
                        break;
                    case 'f':
                        buffer.push('\f');
                        break;
                    case 'n':
                        buffer.push('\n');
                        break;
                    case 'r':
                        buffer.push('\r');
                        break;
                    case 't':
                        buffer.push('\t');
                        break;
                    case 'u':
                        // interpret the following 4 characters as the hex of the unicode code point
                        var codePoint = parseInt(v.substring(i + 1, i + 5), 16);
                        buffer.push(String.fromCharCode(codePoint));
                        i += 4;
                        break;
                    default:
                        throw this.error_parsing(pos + i, "Illegal escape sequence: '\\" + c + "'");
                    }
                    escaping = false;
                } else {
                    if (c == '\\') {
                        escaping = true;
                    } else {
                        buffer.push(c);
                    }
                }
            }

            return buffer.join('');
        },

        isString: function () {
            var r = false;
            var str = "";
            var startpos = this.pos;
            if (this.pos < this.expression.length && this.expression.charAt(this.pos) == "'") {
                this.pos++;
                while (this.pos < this.expression.length) {
                    var code = this.expression.charAt(this.pos);
                    if (code != "'" || str.slice(-1) == "\\") {
                        str += this.expression.charAt(this.pos);
                        this.pos++;
                    }
                    else {
                        this.pos++;
                        this.tokennumber = this.unescape(str, startpos);
                        r = true;
                        break;
                    }
                }
            }
            return r;
        },

        isConst: function () {
            var str;
            for (var i in this.consts) {
                if (true) {
                    var L = i.length;
                    str = this.expression.substr(this.pos, L);
                    if (i === str) {
                        this.tokennumber = this.consts[i];
                        this.pos += L;
                        return true;
                    }
                }
            }
            return false;
        },

        isOperator: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 43) { // +
                this.tokenprio = 0;
                this.tokenindex = "+";
            }
            else if (code === 45) { // -
                this.tokenprio = 0;
                this.tokenindex = "-";
            }
            else if (code === 124) { // |
                if (this.expression.charCodeAt(this.pos + 1) === 124) {
                    this.pos++;
                    this.tokenprio = 0;
                    this.tokenindex = "||";
                }
                else {
                    return false;
                }
            }
            else if (code === 42) { // *
                this.tokenprio = 1;
                this.tokenindex = "*";
            }
            else if (code === 47) { // /
                this.tokenprio = 2;
                this.tokenindex = "/";
            }
            else if (code === 37) { // %
                this.tokenprio = 2;
                this.tokenindex = "%";
            }
            else if (code === 94) { // ^
                this.tokenprio = 3;
                this.tokenindex = "^";
            }
            else {
                return false;
            }
            this.pos++;
            return true;
        },

        isSign: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 45 || code === 43) { // -
                return true;
            }
            return false;
        },

        isPositiveSign: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 43) { // -
                return true;
            }
            return false;
        },

        isNegativeSign: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 45) { // -
                return true;
            }
            return false;
        },

        isLeftParenth: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 40) { // (
                this.pos++;
                this.tmpprio += 10;
                return true;
            }
            return false;
        },

        isRightParenth: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 41) { // )
                this.pos++;
                this.tmpprio -= 10;
                return true;
            }
            return false;
        },

        isComma: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 44) { // ,
                this.pos++;
                this.tokenprio = -1;
                this.tokenindex = ",";
                return true;
            }
            return false;
        },

        isWhite: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 32 || code === 9 || code === 10 || code === 13) {
                this.pos++;
                return true;
            }
            return false;
        },

        isOp1: function () {
            var str = "";
            for (var i = this.pos; i < this.expression.length; i++) {
                var c = this.expression.charAt(i);
                if (c.toUpperCase() === c.toLowerCase()) {
                    if (i === this.pos || c < '0' || c > '9') {
                        break;
                    }
                }
                str += c;
            }
            if (str.length > 0 && (str in this.ops1)) {
                this.tokenindex = str;
                this.tokenprio = 5;
                this.pos += str.length;
                return true;
            }
            return false;
        },

        isOp2: function () {
            var str = "";
            for (var i = this.pos; i < this.expression.length; i++) {
                var c = this.expression.charAt(i);
                if (c.toUpperCase() === c.toLowerCase()) {
                    if (i === this.pos || c < '0' || c > '9') {
                        break;
                    }
                }
                str += c;
            }
            if (str.length > 0 && (str in this.ops2)) {
                this.tokenindex = str;
                this.tokenprio = 5;
                this.pos += str.length;
                return true;
            }
            return false;
        },

        isVar: function () {
            var str = "";
            for (var i = this.pos; i < this.expression.length; i++) {
                var c = this.expression.charAt(i);
                if (c.toUpperCase() === c.toLowerCase()) {
                    if (i === this.pos || c < '0' || c > '9') {
                        break;
                    }
                }
                str += c;
            }
            if (str.length > 0) {
                this.tokenindex = str;
                this.tokenprio = 4;
                this.pos += str.length;
                return true;
            }
            return false;
        },

        isComment: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 47 && this.expression.charCodeAt(this.pos) === 42) {
                this.pos = this.expression.indexOf("*/", this.pos) + 2;
                if (this.pos === 1) {
                    this.pos = this.expression.length;
                }
                return true;
            }
            return false;
        }
    };

    return Parser;
}();
test.html

Code : Tout sélectionner

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
    <head>
        <script src="parser.js" type="text/javascript"/>
        <script type="text/javascript">
            oneFomurlaParsed = Parser.parse('2^5*(1+4/5)');
            document.write( oneFomurlaParsed.toLatex() );
        </script>
    </head>

    <body>
    </body>
</html>
Sur ce, mes copies m'appellent...
projetmbc
Utilisateur chevronné
Utilisateur chevronné
Messages : 1982
Inscription : samedi 29 décembre 2007, 00:58

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par projetmbc »

Voici un fichier test adapté d'un exemple de MathJax. Ceci permet de tester visuellement le fichier JavaScript modifié qui pourra être utile dans un premier temps même si cela est loin d'être parfait.

Code : Tout sélectionner

<!--
Sources :
    http://www.mathjax.org/resources/docs/?typeset.html
-->

<html>
    <head>
        <script src="parser.js" type="text/javascript"/>

        <script src="http://www.mathjax.org/mathjax/MathJax.js">
MathJax.Hub.Config({
    extensions: ["tex2jax.js"],
    jax: ["input/TeX","output/HTML-CSS"],
    tex2jax: {inlineMath: [["$","$"],["\\(","\\)"]]}
});
        </script>

        <script>
//
//  Use a closure to hide the local variables from the
//  global namespace
//
(function () {
    var QUEUE = MathJax.Hub.queue;  // shorthand for the queue
    var math = null;                // the element jax for the math output.

//
//  Get the element jax when MathJax has produced it.
//
    QUEUE.Push(function () {
        math = MathJax.Hub.getAllJax("MathOutput")[0];
    });

//
//  The onchange event handler that typesets the
//  math entered by the user
//
    window.UpdateMath = function (text) {
        TeX = Parser.parse(text).toLatex();
        QUEUE.Push(["Text",math,"\\displaystyle{"+TeX+"}"]);
    }
})();
        </script>
    </head>


    <body>
        Type some TeX code:
        <input id="MathInput" size="50" onchange="UpdateMath(this.value)" />

        <div id="MathOutput">
You typed: ${}$
        </div>
    </body>
</html>
Code parser.js à nettoyer (retirer les lignes inutiles)

Code : Tout sélectionner

/*
 Based on ndef.parser, by Raphael Graf(r@undefined.ch)
 http://www.undefined.ch/mparser/index.html

 Source for this file :
    http://silentmatt.com/math/evaluator.php
*/
var Parser = function () {
    function object(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }

    var TNUMBER = 0;
    var TOP1 = 1;
    var TOP2 = 2;
    var TVAR = 3;
    var TFUNCALL = 4;

    function Token(type_, index_, prio_, number_) {
        this.type_ = type_;
        this.index_ = index_ || 0;
        this.prio_ = prio_ || 0;
        this.number_ = (number_ !== undefined && number_ !== null) ? number_ : 0;
        this.toString = function () {
            switch (this.type_) {
            case TNUMBER:
                return this.number_;
            case TOP1:
            case TOP2:
            case TVAR:
                return this.index_;
            case TFUNCALL:
                return "CALL";
            default:
                return "Invalid Token";
            }
        };
    }

    function Expression(tokens, ops1, ops2, functions) {
        this.tokens = tokens;
        this.ops1 = ops1;
        this.ops2 = ops2;
        this.functions = functions;
    }

    // Based on http://www.json.org/json2.js
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\'\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            "'" : "\\'",
            '\\': '\\\\'
        };

    function escapeValue(v) {
        if (typeof v === "string") {
            escapable.lastIndex = 0;
            return escapable.test(v) ?
                "'" + v.replace(escapable, function (a) {
                    var c = meta[a];
                    return typeof c === 'string' ? c :
                        '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                }) + "'" :
                "'" + v + "'";
        }
        return v;
    }

    Expression.prototype = {
        simplify: function (values) {
            values = values || {};
            var nstack = [];
            var newexpression = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(item);
                }
                else if (type_ === TVAR && (item.index_ in values)) {
                    item = new Token(TNUMBER, 0, 0, values[item.index_]);
                    nstack.push(item);
                }
                else if (type_ === TOP2 && nstack.length > 1) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = this.ops2[item.index_];
                    item = new Token(TNUMBER, 0, 0, f(n1.number_, n2.number_));
                    nstack.push(item);
                }
                else if (type_ === TOP1 && nstack.length > 0) {
                    n1 = nstack.pop();
                    f = this.ops1[item.index_];
                    item = new Token(TNUMBER, 0, 0, f(n1.number_));
                    nstack.push(item);
                }
                else {
                    while (nstack.length > 0) {
                        newexpression.push(nstack.shift());
                    }
                    newexpression.push(item);
                }
            }
            while (nstack.length > 0) {
                newexpression.push(nstack.shift());
            }

            return new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions));
        },

        substitute: function (variable, expr) {
            if (!(expr instanceof Expression)) {
                expr = new Parser().parse(String(expr));
            }
            var newexpression = [];
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TVAR && item.index_ === variable) {
                    for (var j = 0; j < expr.tokens.length; j++) {
                        var expritem = expr.tokens[j];
                        var replitem = new Token(expritem.type_, expritem.index_, expritem.prio_, expritem.number_);
                        newexpression.push(replitem);
                    }
                }
                else {
                    newexpression.push(item);
                }
            }

            var ret = new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions));
            return ret;
        },

        evaluate: function (values) {
            values = values || {};
            var nstack = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(item.number_);
                }
                else if (type_ === TOP2) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = this.ops2[item.index_];
                    nstack.push(f(n1, n2));
                }
                else if (type_ === TVAR) {
                    if (item.index_ in values) {
                        nstack.push(values[item.index_]);
                    }
                    else if (item.index_ in this.functions) {
                        nstack.push(this.functions[item.index_]);
                    }
                    else {
                        throw new Error("undefined variable: " + item.index_);
                    }
                }
                else if (type_ === TOP1) {
                    n1 = nstack.pop();
                    f = this.ops1[item.index_];
                    nstack.push(f(n1));
                }
                else if (type_ === TFUNCALL) {
                    n1 = nstack.pop();
                    f = nstack.pop();
                    if (f.apply && f.call) {
                        if (Object.prototype.toString.call(n1) == "[object Array]") {
                            nstack.push(f.apply(undefined, n1));
                        }
                        else {
                            nstack.push(f.call(undefined, n1));
                        }
                    }
                    else {
                        throw new Error(f + " is not a function");
                    }
                }
                else {
                    throw new Error("invalid Expression");
                }
            }
            if (nstack.length > 1) {
                throw new Error("invalid Expression (parity)");
            }
            return nstack[0];
        },

        toString: function (toJS) {
            var nstack = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(escapeValue(item.number_));
                }
                else if (type_ === TOP2) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = item.index_;
                    if (toJS && f == "^") {
                        nstack.push("Math.pow(" + n1 + "," + n2 + ")");
                    }
                    else {
                        nstack.push("(" + n1 + f + n2 + ")");
                    }
                }
                else if (type_ === TVAR) {
                    nstack.push(item.index_);
                }
                else if (type_ === TOP1) {
                    n1 = nstack.pop();
                    f = item.index_;
                    if (f === "-") {
                        nstack.push("(" + f + n1 + ")");
                    }
                    else {
                        nstack.push(f + "(" + n1 + ")");
                    }
                }
                else if (type_ === TFUNCALL) {
                    n1 = nstack.pop();
                    f = nstack.pop();
                    nstack.push(f + "(" + n1 + ")");
                }
                else {
                    throw new Error("invalid Expression");
                }
            }
            if (nstack.length > 1) {
                throw new Error("invalid Expression (parity)");
            }
            return nstack[0];
        },



/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////

        toLatex: function () {
            var nstack = [];
            var n1;
            var n2;
            var f;
            var L = this.tokens.length;
            var item;
            var i = 0;
            for (i = 0; i < L; i++) {
                item = this.tokens[i];
                var type_ = item.type_;
                if (type_ === TNUMBER) {
                    nstack.push(escapeValue(item.number_));
                }
                else if (type_ === TOP2) {
                    n2 = nstack.pop();
                    n1 = nstack.pop();
                    f = item.index_;
                    if (f == "^") {
                        nstack.push("{(" + n1 + ")}^{(" + n2 + ")}");
                    }
                    else if (f == "*") {
                        nstack.push(n1 + " \\times " + n2);
                    }
                    else if (f == "/") {
                        nstack.push("\\frac{" + n1 + "}{" + n2 + "}");
                    }
                    else {
                        nstack.push(n1 + " " + f + " " + n2);
                    }
                }
                else if (type_ === TVAR) {
                    nstack.push(item.index_);
                }
                else if (type_ === TOP1) {
                    n1 = nstack.pop();
                    f = item.index_;
                    if (f === "-") {
                        nstack.push("(" + f + n1 + ")");
                    }
                    else {
                        nstack.push(f + "(" + n1 + ")");
                    }
                }
                else if (type_ === TFUNCALL) {
                    n1 = nstack.pop();
                    f = nstack.pop();
                    nstack.push(f + "(" + n1 + ")");
                }
                else {
                    throw new Error("invalid Expression");
                }
            }
            if (nstack.length > 1) {
                throw new Error("invalid Expression (parity)");
            }
            return nstack[0];
        },


/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////


        variables: function () {
            var L = this.tokens.length;
            var vars = [];
            for (var i = 0; i < L; i++) {
                var item = this.tokens[i];
                if (item.type_ === TVAR && (vars.indexOf(item.index_) == -1)) {
                    vars.push(item.index_);
                }
            }

            return vars;
        },

        toJSFunction: function (param, variables) {
            var f = new Function(param, "with(Parser.values) { return " + this.simplify(variables).toString(true) + "; }");
            return f;
        }
    };

    function add(a, b) {
        return Number(a) + Number(b);
    }
    function sub(a, b) {
        return a - b;
    }
    function mul(a, b) {
        return a * b;
    }
    function div(a, b) {
        return a / b;
    }
    function mod(a, b) {
        return a % b;
    }
    function concat(a, b) {
        return "" + a + b;
    }

    function neg(a) {
        return -a;
    }

    function random(a) {
        return Math.random() * (a || 1);
    }
    function fac(a) { //a!
        a = Math.floor(a);
        var b = a;
        while (a > 1) {
            b = b * (--a);
        }
        return b;
    }

    // TODO: use hypot that doesn't overflow
    function pyt(a, b) {
        return Math.sqrt(a * a + b * b);
    }

    function append(a, b) {
        if (Object.prototype.toString.call(a) != "[object Array]") {
            return [a, b];
        }
        a = a.slice();
        a.push(b);
        return a;
    }

    function Parser() {
        this.success = false;
        this.errormsg = "";
        this.expression = "";

        this.pos = 0;

        this.tokennumber = 0;
        this.tokenprio = 0;
        this.tokenindex = 0;
        this.tmpprio = 0;

        this.ops1 = {
            "sin": Math.sin,
            "cos": Math.cos,
            "tan": Math.tan,
            "asin": Math.asin,
            "acos": Math.acos,
            "atan": Math.atan,
            "sqrt": Math.sqrt,
            "log": Math.log,
            "abs": Math.abs,
            "ceil": Math.ceil,
            "floor": Math.floor,
            "round": Math.round,
            "-": neg,
            "exp": Math.exp
        };

        this.ops2 = {
            "+": add,
            "-": sub,
            "*": mul,
            "/": div,
            "%": mod,
            "^": Math.pow,
            ",": append,
            "||": concat
        };

        this.functions = {
            "random": random,
            "fac": fac,
            "min": Math.min,
            "max": Math.max,
            "pyt": pyt,
            "pow": Math.pow,
            "atan2": Math.atan2
        };

        this.consts = {
            "E": Math.E,
            "PI": Math.PI
        };
    }

    Parser.parse = function (expr) {
        return new Parser().parse(expr);
    };

    Parser.evaluate = function (expr, variables) {
        return Parser.parse(expr).evaluate(variables);
    };

    Parser.Expression = Expression;

    Parser.values = {
        sin: Math.sin,
        cos: Math.cos,
        tan: Math.tan,
        asin: Math.asin,
        acos: Math.acos,
        atan: Math.atan,
        sqrt: Math.sqrt,
        log: Math.log,
        abs: Math.abs,
        ceil: Math.ceil,
        floor: Math.floor,
        round: Math.round,
        random: random,
        fac: fac,
        exp: Math.exp,
        min: Math.min,
        max: Math.max,
        pyt: pyt,
        pow: Math.pow,
        atan2: Math.atan2,
        E: Math.E,
        PI: Math.PI
    };

    var PRIMARY  = 1 << 0;
    var OPERATOR = 1 << 1;
    var FUNCTION = 1 << 2;
    var LPAREN   = 1 << 3;
    var RPAREN   = 1 << 4;
    var COMMA    = 1 << 5;
    var SIGN     = 1 << 6;
    var CALL     = 1 << 7;

    Parser.prototype = {
        parse: function (expr) {
            this.errormsg = "";
            this.success = true;
            var operstack = [];
            var tokenstack = [];
            this.tmpprio = 0;
            var expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
            var noperators = 0;
            this.expression = expr;
            this.pos = 0;

            while (this.pos < this.expression.length) {
                if (this.isOperator()) {
                    if (this.isSign() && (expected & SIGN)) {
                        if (this.isNegativeSign()) {
                            this.tokenprio = 2;
                            this.tokenindex = "-";
                            noperators++;
                            this.addfunc(tokenstack, operstack, TOP1);
                        }
                        expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                    }
                    else if (this.isComment()) {

                    }
                    else {
                        if ((expected & OPERATOR) === 0) {
                            this.error_parsing(this.pos, "unexpected operator");
                        }
                        noperators += 2;
                        this.addfunc(tokenstack, operstack, TOP2);
                        expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                    }
                }
                else if (this.isNumber()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected number");
                    }
                    var token = new Token(TNUMBER, 0, 0, this.tokennumber);
                    tokenstack.push(token);

                    expected = (OPERATOR | RPAREN | COMMA);
                }
                else if (this.isString()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected string");
                    }
                    var token = new Token(TNUMBER, 0, 0, this.tokennumber);
                    tokenstack.push(token);

                    expected = (OPERATOR | RPAREN | COMMA);
                }
                else if (this.isLeftParenth()) {
                    if ((expected & LPAREN) === 0) {
                        this.error_parsing(this.pos, "unexpected \"(\"");
                    }

                    if (expected & CALL) {
                        noperators += 2;
                        this.tokenprio = -2;
                        this.tokenindex = -1;
                        this.addfunc(tokenstack, operstack, TFUNCALL);
                    }

                    expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                }
                else if (this.isRightParenth()) {
                    if ((expected & RPAREN) === 0) {
                        this.error_parsing(this.pos, "unexpected \")\"");
                    }

                    expected = (OPERATOR | RPAREN | COMMA | LPAREN | CALL);
                }
                else if (this.isComma()) {
                    if ((expected & COMMA) === 0) {
                        this.error_parsing(this.pos, "unexpected \",\"");
                    }
                    this.addfunc(tokenstack, operstack, TOP2);
                    noperators += 2;
                    expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
                }
                else if (this.isConst()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected constant");
                    }
                    var consttoken = new Token(TNUMBER, 0, 0, this.tokennumber);
                    tokenstack.push(consttoken);
                    expected = (OPERATOR | RPAREN | COMMA);
                }
                else if (this.isOp2()) {
                    if ((expected & FUNCTION) === 0) {
                        this.error_parsing(this.pos, "unexpected function");
                    }
                    this.addfunc(tokenstack, operstack, TOP2);
                    noperators += 2;
                    expected = (LPAREN);
                }
                else if (this.isOp1()) {
                    if ((expected & FUNCTION) === 0) {
                        this.error_parsing(this.pos, "unexpected function");
                    }
                    this.addfunc(tokenstack, operstack, TOP1);
                    noperators++;
                    expected = (LPAREN);
                }
                else if (this.isVar()) {
                    if ((expected & PRIMARY) === 0) {
                        this.error_parsing(this.pos, "unexpected variable");
                    }
                    var vartoken = new Token(TVAR, this.tokenindex, 0, 0);
                    tokenstack.push(vartoken);

                    expected = (OPERATOR | RPAREN | COMMA | LPAREN | CALL);
                }
                else if (this.isWhite()) {
                }
                else {
                    if (this.errormsg === "") {
                        this.error_parsing(this.pos, "unknown character");
                    }
                    else {
                        this.error_parsing(this.pos, this.errormsg);
                    }
                }
            }
            if (this.tmpprio < 0 || this.tmpprio >= 10) {
                this.error_parsing(this.pos, "unmatched \"()\"");
            }
            while (operstack.length > 0) {
                var tmp = operstack.pop();
                tokenstack.push(tmp);
            }
            if (noperators + 1 !== tokenstack.length) {
                //print(noperators + 1);
                //print(tokenstack);
                this.error_parsing(this.pos, "parity");
            }

            return new Expression(tokenstack, object(this.ops1), object(this.ops2), object(this.functions));
        },

        evaluate: function (expr, variables) {
            return this.parse(expr).evaluate(variables);
        },

        error_parsing: function (column, msg) {
            this.success = false;
            this.errormsg = "parse error [column " + (column) + "]: " + msg;
            throw new Error(this.errormsg);
        },

//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

        addfunc: function (tokenstack, operstack, type_) {
            var operator = new Token(type_, this.tokenindex, this.tokenprio + this.tmpprio, 0);
            while (operstack.length > 0) {
                if (operator.prio_ <= operstack[operstack.length - 1].prio_) {
                    tokenstack.push(operstack.pop());
                }
                else {
                    break;
                }
            }
            operstack.push(operator);
        },

        isNumber: function () {
            var r = false;
            var str = "";
            while (this.pos < this.expression.length) {
                var code = this.expression.charCodeAt(this.pos);
                if ((code >= 48 && code <= 57) || code === 46) {
                    str += this.expression.charAt(this.pos);
                    this.pos++;
                    this.tokennumber = parseFloat(str);
                    r = true;
                }
                else {
                    break;
                }
            }
            return r;
        },

        // Ported from the yajjl JSON parser at http://code.google.com/p/yajjl/
        unescape: function(v, pos) {
            var buffer = [];
            var escaping = false;

            for (var i = 0; i < v.length; i++) {
                var c = v.charAt(i);

                if (escaping) {
                    switch (c) {
                    case "'":
                        buffer.push("'");
                        break;
                    case '\\':
                        buffer.push('\\');
                        break;
                    case '/':
                        buffer.push('/');
                        break;
                    case 'b':
                        buffer.push('\b');
                        break;
                    case 'f':
                        buffer.push('\f');
                        break;
                    case 'n':
                        buffer.push('\n');
                        break;
                    case 'r':
                        buffer.push('\r');
                        break;
                    case 't':
                        buffer.push('\t');
                        break;
                    case 'u':
                        // interpret the following 4 characters as the hex of the unicode code point
                        var codePoint = parseInt(v.substring(i + 1, i + 5), 16);
                        buffer.push(String.fromCharCode(codePoint));
                        i += 4;
                        break;
                    default:
                        throw this.error_parsing(pos + i, "Illegal escape sequence: '\\" + c + "'");
                    }
                    escaping = false;
                } else {
                    if (c == '\\') {
                        escaping = true;
                    } else {
                        buffer.push(c);
                    }
                }
            }

            return buffer.join('');
        },

        isString: function () {
            var r = false;
            var str = "";
            var startpos = this.pos;
            if (this.pos < this.expression.length && this.expression.charAt(this.pos) == "'") {
                this.pos++;
                while (this.pos < this.expression.length) {
                    var code = this.expression.charAt(this.pos);
                    if (code != "'" || str.slice(-1) == "\\") {
                        str += this.expression.charAt(this.pos);
                        this.pos++;
                    }
                    else {
                        this.pos++;
                        this.tokennumber = this.unescape(str, startpos);
                        r = true;
                        break;
                    }
                }
            }
            return r;
        },

        isConst: function () {
            var str;
            for (var i in this.consts) {
                if (true) {
                    var L = i.length;
                    str = this.expression.substr(this.pos, L);
                    if (i === str) {
                        this.tokennumber = this.consts[i];
                        this.pos += L;
                        return true;
                    }
                }
            }
            return false;
        },

        isOperator: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 43) { // +
                this.tokenprio = 0;
                this.tokenindex = "+";
            }
            else if (code === 45) { // -
                this.tokenprio = 0;
                this.tokenindex = "-";
            }
            else if (code === 124) { // |
                if (this.expression.charCodeAt(this.pos + 1) === 124) {
                    this.pos++;
                    this.tokenprio = 0;
                    this.tokenindex = "||";
                }
                else {
                    return false;
                }
            }
            else if (code === 42) { // *
                this.tokenprio = 1;
                this.tokenindex = "*";
            }
            else if (code === 47) { // /
                this.tokenprio = 2;
                this.tokenindex = "/";
            }
            else if (code === 37) { // %
                this.tokenprio = 2;
                this.tokenindex = "%";
            }
            else if (code === 94) { // ^
                this.tokenprio = 3;
                this.tokenindex = "^";
            }
            else {
                return false;
            }
            this.pos++;
            return true;
        },

        isSign: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 45 || code === 43) { // -
                return true;
            }
            return false;
        },

        isPositiveSign: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 43) { // -
                return true;
            }
            return false;
        },

        isNegativeSign: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 45) { // -
                return true;
            }
            return false;
        },

        isLeftParenth: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 40) { // (
                this.pos++;
                this.tmpprio += 10;
                return true;
            }
            return false;
        },

        isRightParenth: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 41) { // )
                this.pos++;
                this.tmpprio -= 10;
                return true;
            }
            return false;
        },

        isComma: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 44) { // ,
                this.pos++;
                this.tokenprio = -1;
                this.tokenindex = ",";
                return true;
            }
            return false;
        },

        isWhite: function () {
            var code = this.expression.charCodeAt(this.pos);
            if (code === 32 || code === 9 || code === 10 || code === 13) {
                this.pos++;
                return true;
            }
            return false;
        },

        isOp1: function () {
            var str = "";
            for (var i = this.pos; i < this.expression.length; i++) {
                var c = this.expression.charAt(i);
                if (c.toUpperCase() === c.toLowerCase()) {
                    if (i === this.pos || c < '0' || c > '9') {
                        break;
                    }
                }
                str += c;
            }
            if (str.length > 0 && (str in this.ops1)) {
                this.tokenindex = str;
                this.tokenprio = 5;
                this.pos += str.length;
                return true;
            }
            return false;
        },

        isOp2: function () {
            var str = "";
            for (var i = this.pos; i < this.expression.length; i++) {
                var c = this.expression.charAt(i);
                if (c.toUpperCase() === c.toLowerCase()) {
                    if (i === this.pos || c < '0' || c > '9') {
                        break;
                    }
                }
                str += c;
            }
            if (str.length > 0 && (str in this.ops2)) {
                this.tokenindex = str;
                this.tokenprio = 5;
                this.pos += str.length;
                return true;
            }
            return false;
        },

        isVar: function () {
            var str = "";
            for (var i = this.pos; i < this.expression.length; i++) {
                var c = this.expression.charAt(i);
                if (c.toUpperCase() === c.toLowerCase()) {
                    if (i === this.pos || c < '0' || c > '9') {
                        break;
                    }
                }
                str += c;
            }
            if (str.length > 0) {
                this.tokenindex = str;
                this.tokenprio = 4;
                this.pos += str.length;
                return true;
            }
            return false;
        },

        isComment: function () {
            var code = this.expression.charCodeAt(this.pos - 1);
            if (code === 47 && this.expression.charCodeAt(this.pos) === 42) {
                this.pos = this.expression.indexOf("*/", this.pos) + 2;
                if (this.pos === 1) {
                    this.pos = this.expression.length;
                }
                return true;
            }
            return false;
        }
    };

    return Parser;
}();
joelGa

Re: Exerciseur niveau lycée réalisé avec GeoGebra

Message non lu par joelGa »

Merci beaucoup pour ce travail
J'ai un problème:
J'ai testé les fichiers, au lancement du fichier HTML j'obtiens le code d'erreur
Erreur : MathJax is not defined
Fichier Source : .................... Mon fichier .........html
Ligne : 24
La connexion au fichier http://www.mathjax.org/mathjax/MathJax.js se fait pourtant correctement.
Faut-il installer un pluging à Firefox ?

Merci d'avance pour ta réponse
Joël