Exemplo n.º 1
0
class ServeurHtml():
    def __init__(self, local, rejpertoire, scriptsDir):
        self.rejpertoire = rejpertoire
        self.scriptsDir = scriptsDir
        self.ejnoncej = ''
        # init la socket
        c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        c.bind((HOST, PORT))
        print('attend sur le port {}'.format(PORT))
        # 1 seul client a la fois, ca permet d'utiliser la socket de connexion pour la reponse
        c.listen(1)
        # si local, lance le client firefox
        if local:
            if name == 'nt':
                commande = '"C:\Program Files\Mozilla Firefox\firefox.exe"'
            else:
                commande = 'firefox'
            subprocess.run([commande, 'http://localhost:{}'.format(PORT)])
        # attend l'utilisateur et ce, indefiniment
        while True:
            try:
                csock, caddr = c.accept()
                #print('----------------------\nServeurHtml travaille')
                donnejesRecues = urllib.parse.unquote_plus(
                    csock.recv(4096).decode('utf-8'))
                #repond au client que tout va bien
                csock.send(b'HTTP/1.0 200 OK\n\n')
                #print(donnejesRecues)
                # GET / HTTP/1.1 = 1ehre fois
                if 'GET / HTTP/1.1' in donnejesRecues:
                    print('Première fois')
                    self.afficheSaisieGrille(csock)
                # POST /saisie-cc HTTP/1.1
                elif 'POST /saisie-cc HTTP/1.1' in donnejesRecues:
                    print('saisie-cc')
                    self.traiteCopierColler(csock, donnejesRecues)
                # POST /saisie-grille HTTP/1.1
                elif 'POST /saisie-grille HTTP/1.1' in donnejesRecues:
                    print('saisie-grille')
                    self.traiteSaisieGrille(csock, donnejesRecues)
                elif 'POST /calcul-sudoku HTTP/1.1' in donnejesRecues:
                    print('calcul-sudoku')
                    self.traiteCalculSudoku(csock)
                else:
                    print("PUTAIN C'EST QUOI ?")
                csock.close()
                #print('----------------------')
            except Exception as exc:
                if not exc.args == (32, 'Broken pipe'): raise
                print(exc.args)

    ###################################
    def traiteCopierColler(self, csock, donnejesRecues):
        self.ejnoncej = ''
        # copiercoller=003104800,000000000,400508001,790060048,080473090,530010027,800302004,000000000,002701500
        match = re.search('copiercoller=(.*)', donnejesRecues)
        if match:
            for caractehre in match.group(1):
                if caractehre in ('1', '2', '3', '4', '5', '6', '7', '8', '9'):
                    self.ejnoncej += caractehre
                elif caractehre in ('0', ' ', '.'):
                    self.ejnoncej += '.'
                # max 81 + 8 virgules
                if len(self.ejnoncej) == 89: break
                # insertion barre sejparation
                if len(self.ejnoncej) % 10 == 9: self.ejnoncej += '|'
        else: print('saisie-cc INCONNU')
        self.afficheSaisieGrille(csock)

    ###################################
    def traiteSaisieGrille(self, csock, donnejesRecues):
        self.ejnoncej = ''
        # 11=3&12=1&13=&...&98=&99=&raz=raz
        if 'raz=raz' in donnejesRecues:
            self.afficheSaisieGrille(csock)
            return
        # 11=3&12=1&13=&...&98=&99=&soumettre=soumettre
        match = re.search('(11=.*)&soumettre=soumettre', donnejesRecues)
        if not match:
            print('saisie-grille INCONNU')
            self.afficheSaisieGrille(csock)
            return
        for affectation in match.group(1).split('&'):
            # 12=1 ou 13=
            valeur = affectation.split('=')[1]
            if valeur == '': self.ejnoncej += '.'
            else: self.ejnoncej += valeur
            # max 81 + 8 virgules
            if len(self.ejnoncej) == 89: break
            # insertion barre sejparation
            if len(self.ejnoncej) % 10 == 9: self.ejnoncej += '|'
        if len(self.ejnoncej) != 89:
            print('saisie-grille ERRONNÉE ({})'.format(len(self.ejnoncej)))
            self.afficheSaisieGrille(csock)
            return
        # avec le programme de calcul maintenant
        lignes = self.ejnoncej.replace('|', ',')
        lignes = lignes.replace('.', '0')
        self.sudoku = Sudoku(lignes)
        # affiche
        self.afficheEnTeste(csock)
        self.afficheTitreEtSaisie(csock)
        self.afficheCalculPartiel(csock)
        self.afficheValeursPossibles(csock)
        self.afficheQueue(csock)

    ###################################
    def traiteCalculSudoku(self, csock):
        # affiche
        self.afficheEnTeste(csock)
        self.afficheTitreEtSaisie(csock)
        self.afficheRejsultatVide(csock)
        self.afficheCalculPdf(csock)
        self.afficheQueue(csock)

    ###################################
    def afficheSaisieGrille(self, csock):
        self.afficheEnTeste(csock)
        self.afficheTitreEtSaisie(csock)
        self.afficheRejsultatVide(csock)
        self.afficheQueue(csock)

    ###################################
    def afficheTitreEtSaisie(self, csock):
        imageHtml = self.imageBase64("{}/echiquierLatejcon4-200T.png".format(
            self.scriptsDir))
        csock.sendall(("""        
        <table><tr><td><h1>Le sudoku anthropomorphique de</h1></td><td>{}</td></tr>
        </table>
        <table class="saisiecc"><tr><td height="50px">
        <form name="saisie-cc" method="post" action="saisie-cc">
            <input type="text" id="copiercoller" name="copiercoller" maxlength="90" size="89" value="{}"/>
            <input type="submit" value="V">
        </form>
        </td></tr></table>
        <br/>
        """.format(imageHtml, self.ejnoncej)).encode('utf-8'))

        csock.sendall("""
        <table><tr><td  class="zone-saisie">
            <form name="saisie-grille" method="post" action="saisie-grille">
            """.encode('utf-8'))

        inputId = 0
        ejnoncej = self.ejnoncej.replace('|', '')
        for ligne in range(1, 10):
            csock.sendall(
                ('<div id="ligne{}" class="ligne-saisie">\n'.format(ligne)
                 ).encode('utf-8'))
            for colonne in range(1, 10):
                if inputId < len(ejnoncej): valeur = ejnoncej[inputId]
                else: valeur = ''
                if valeur == '.': valeur = ''
                inputId += 1
                html = '<input type="text" id="{}" name="{}{}" maxlength="1" value="{}" class="chiffre'.format(
                    inputId, ligne, colonne, valeur)
                if colonne in (3, 6): html += ' sep'
                if ligne in (4, 7): html += ' sep2'
                if inputId == 1: html += '" autofocus/>\n'
                else: html += '"/>\n'
                csock.sendall(html.encode('utf-8'))
            csock.sendall('</div>\n'.encode('utf-8'))

        csock.sendall("""
                    <br/>
                </div>
                <p>&nbsp;</p><br/>
                <div>
                <input type="submit" name="raz" value="raz" formmethod="post">
                <input type="submit" name="soumettre" value="soumettre" formmethod="post">
                </div>
            </form>
            """.encode('utf-8'))

    ###################################
    def afficheRejsultatVide(self, csock):
        csock.sendall("""
            </td>
            <td class="zone-blanche"/>
            <td class="zone-rejsultat">
            </td></tr></table>
            """.encode('utf-8'))

    ###################################
    def afficheCalculPartiel(self, csock):
        # affiche les informations de validitej
        lesInvalides = self.sudoku.cellulesInvalides()
        if len(lesInvalides) != 0:
            csock.sendall(
                '<p>La grille présente des incompatibilités sur les cellules marquées en rouge</p>\n'
                .encode('utf-8'))
        else:
            # le diagnostic par la mejthode bourrin
            tropDeSolutions, rejsultat = self.sudoku.nombreSolutions()
            if rejsultat == 0:
                csock.sendall(
                    "<p>La grille n'a aucune solution</p>\n".encode('utf-8'))
            elif rejsultat == 1:
                csock.sendall(
                    "<p>La grille a une solution et une seule</p>\n".encode(
                        'utf-8'))
            elif tropDeSolutions:
                csock.sendall(
                    "<p>La grille a plus de 100 solutions</p>\n".encode(
                        'utf-8'))
            else:
                csock.sendall(
                    ("<p>La grille a {} solutions</p>\n".format(rejsultat)
                     ).encode('utf-8'))
            # le calcul par le sudoku anthropomorphique
            csock.sendall("""
            <form name="calcul" method="post" action="calcul-sudoku">
                <input type="submit" value="Tentative de résolution par le Sudoku anthropomorphique">
            </form>
                """.encode('utf-8'))
        csock.sendall("""
            </td>
            <td class="zone-blanche"/>
            <td class="zone-rejsultat">
            """.encode('utf-8'))

    ###################################
    def afficheValeursPossibles(self, csock):
        lesInvalides = self.sudoku.cellulesInvalides()
        lesValeurs, lesPossibles = self.sudoku.valeurs()
        correspondance = [
            11, 12, 13, 21, 22, 23, 31, 32, 33, 14, 15, 16, 24, 25, 26, 34, 35,
            36, 17, 18, 19, 27, 28, 29, 37, 38, 39, 41, 42, 43, 51, 52, 53, 61,
            62, 63, 44, 45, 46, 54, 55, 56, 64, 65, 66, 47, 48, 49, 57, 58, 59,
            67, 68, 69, 71, 72, 73, 81, 82, 83, 91, 92, 93, 74, 75, 76, 84, 85,
            86, 94, 95, 96, 77, 78, 79, 87, 88, 89, 97, 98, 99
        ]
        csock.sendall('<table class="tableRejultat">'.encode('utf-8'))
        nbCase = 0
        for lig in range(1, 4):
            csock.sendall('<tr>'.encode('utf-8'))
            for col in range(1, 4):
                csock.sendall(
                    '<td><table class="tableCarrej">'.encode('utf-8'))
                for lig2 in range(1, 4):
                    csock.sendall('<tr>'.encode('utf-8'))
                    for col2 in range(1, 4):
                        cellule = correspondance[nbCase]
                        nbCase += 1
                        csock.sendall('<td class="tdRej'.encode('utf-8'))
                        if cellule in lesValeurs:
                            if cellule in lesInvalides:
                                csock.sendall(' tdErr">'.encode('utf-8'))
                            else:
                                csock.sendall(' tdSim">'.encode('utf-8'))
                            csock.sendall(('{}</td>'.format(
                                lesValeurs[cellule])).encode('utf-8'))
                        else:
                            valeurs = [
                                str(elem) for elem in lesPossibles[cellule]
                            ]
                            valeurs.sort()
                            if len(valeurs) > 7:
                                csock.sendall(' tdMu2">'.encode('utf-8'))
                            else:
                                csock.sendall(' tdMul">'.encode('utf-8'))
                            if len(valeurs) > 6:
                                texte = ''.join(
                                    valeurs[:4]) + '<br/>' + ''.join(
                                        valeurs[4:])
                            elif len(valeurs) > 4:
                                texte = ' '.join(
                                    valeurs[:3]) + '<br/>' + ' '.join(
                                        valeurs[3:])
                            elif len(valeurs) > 2:
                                texte = ' '.join(
                                    valeurs[:2]) + '<br/>' + ' '.join(
                                        valeurs[2:])
                            else:
                                texte = ' '.join(valeurs)
                            csock.sendall(
                                ('{}</td>'.format(texte)).encode('utf-8'))
                    csock.sendall('</tr>\n'.encode('utf-8'))
                csock.sendall('</table></td>\n'.encode('utf-8'))
            csock.sendall('</tr>\n'.encode('utf-8'))
        csock.sendall('</table>\n'.encode('utf-8'))
        csock.sendall('</td></tr></table>'.encode('utf-8'))

    ###################################
    def afficheCalculPdf(self, csock):
        succehs, nbAffectations, tour, nomFichierSortie = self.sudoku.resoudSudoku(
            self.rejpertoire)
        if succehs:
            csock.sendall("<p>SUCCÈS !".encode('utf-8'))
        else:
            csock.sendall("<p>ÉCHEC !".encode('utf-8'))
        csock.sendall((
            """ Le sudoku anthropomorphique a affecté {} valeurs en {} tours</br>
            Le résultat est consultable sur {}<p>
            """.format(nbAffectations, tour,
                       nomFichierSortie)).encode('utf-8'))
        fichier = path.basename(nomFichierSortie)
        csock.sendall(('<a href="{}" target="_blank"></a>'.format(fichier)
                       ).encode('utf-8'))

    ###################################
    def imageBase64(self, nom):
        try:
            with open(nom, 'rb') as img:
                extension = nom.split('.')[-1]
                imgStr = base64.b64encode(img.read()).decode()
                return '<img src="data:image/{};base64,{}"/>\n'.format(
                    extension, imgStr)
        except Exception:
            traceback.print_exc()
            return '<blink>Image pas trouveje !</blink>'

    ###################################
    def afficheEnTeste(self, csock):
        csock.sendall("""
<!DOCTYPE html>
<html  lang="fr">
    <head>
        <meta charset="utf-8">
        <title>Sudoku anthropomorphique de l'Atejcon</title>
        <style type="text/css">
            .ligne-saisie input[type='text'].chiffre {width: 25px; }
            .ligne-saisie input[type='text'].sep {margin-right: 2px; }
            .ligne-saisie input[type='text'].sep2 {margin-top: 1px; }
            .ligne-saisie input[type='text'] {
                background: #fff;
                border: 1px solid #d6d6d6;
                border-radius: 2px;
                padding: 0 5px;
                line-height: 2.81em;
                font-family: "Open Sans";
                font-size: 25px;
                float: left;
                margin-left: -1px;
                text-align: center; }
            .ligne-saisie input[type='text'] {height: 32px !important; } 
            .ligne-saisie {
                position:relative;
                min-height:1px;
                padding-right:15px; 
                padding-left:30px}
            .ligne-saisie {float:left}
            .ligne-saisie {width:100%}
            .zone-saisie {
                width:390px; height:500px; 
                text-align:center; vertical-align:center; 
                background-color: #E5E5E4;}
            .zone-blanche {
                width:50px; height:500px; 
                background-color: white;}
            .zone-rejsultat {
                width:500px; height:500px; 
                text-align:center; vertical-align:center; 
                background-color: #f4f4f4;}
            .tableRejultat {
                border: 1px solid #d6d6d6; border-collapse: collapse; 
                background-color: #d6d6d6;}
            .tableCarrej {border: 1px solid black; border-collapse: collapse; }
            .tdRej {
                font-family: "Open Sans";
                width: 50px; height: 50px;
                border: 1px solid #d6d6d6; border-collapse: collapse; 
                empty-cells: show;}
            .tdSim {
                background-color: #f4f4f4;
                font-size: 35px; }
            .tdErr {
                background-color: red;
                font-size: 35px; }
            .tdMul {
                background-color: white;
                font-size: 18px; }
            .tdMu2 {
                background-color: white;
                font-size: 16px; }
            .saisiecc {
                background-color: #E5E5E4;}   
            #copiercoller {
                font-family:courier, courier new, sans-serif;
                font-size: 16px; }
        </style>
    </head>
    <body>
            """.encode('utf-8'))

    ###################################
    def afficheQueue(self, csock):
        csock.sendall("""
        <script>
            var inputs = document.getElementsByClassName('chiffre');
            for (var i=0; i < inputs.length; i++) 
                inputs[i].addEventListener('input', prochain);
            function prochain() {
                //il faut un signe "-" pour que ca calcule, "+" fait de la concatejnation
                var valeur = this.value;
                if (valeur != '') {
                    valeur = valeur.replace(/[^1-9]/g, '');
                    this.value = valeur
                    document.getElementById(this.id-1+2).focus();
                }
            }
        </script>
    </body>
</html>
            """.encode('utf-8'))