---
# System prepended metadata

title: '**Evaluation Ascii Art**'

---

# **Evaluation Ascii Art**

*Matthias Flament*
*Léo SERY*

## **Procédure d'installation :**
```
Téléchargement des différents fichiers de test : Standart.txt
                                                 Shadow.txt
                                                 Thinkertoy.txt
depuis ce lien https://github.com/01-edu/public/tree/master/subjects/ascii-art
```

## 

## **Exemple d'utilisation :**
```
Pour utiliser notre programme, nous devons lancer un terminal bash pour que celui-si fonctionne.
Voici quelques exemples d'utilisation.
```
![](https://i.imgur.com/T38G25g.png)

## 

## **Code Source :**
```
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strconv"
	"strings"
)

func main() {

	//fs (permet de choisir la typographie en passant le nom de cette dernière en argument)
	style := "standart.txt"

	if len(os.Args) >= 3 {
		if os.Args[2] == "shadow" {
			style = "shadow.txt"
		} else if os.Args[2] == "thinkertoy" {
			style = "thinkertoy.txt"
		}
	}

	arg1 := os.Args[1]
	nbrspace := 0

	for u := 0; u < len(arg1); u++ { //permet de compter le nombre d'espaces dans la string qui est en argument (sert pour le cas "justifie")
		if rune(arg1[u]) == ' ' {
			nbrspace++
		}
	}

	alignparam := ""
	justbool := false
	filename := ""
	printcheck := 0
	outputcheck := false
	var colorizedchar Color
	colorizedchar = ColorReset

	for p := 0; p < len(os.Args); p++ { //naviguer dans les arguments (boucle sur chaque argument)
		arg := os.Args[p]

		// permet de séparaer les flags "--output" et "--aling" de leurs paramètres
		for p := 0; p < len(os.Args); p++ { //boucle sur chaque lettres
			arg := os.Args[p]                    //arg = argument actuelle
			separated := strings.Split(arg, "=") // des que "=" split l'argument en 2
			if separated[0] == "--output" {
				filename = separated[1] //rajoute le nom du fichier juste apres le "="
			} else if separated[0] == "--align" {
				alignparam = separated[1] //rajoute le type d'alignement apres le "="
			}
		}

		switch os.Args[p] { //permet de détecter les flags
		case "--align=" + alignparam: //flag permettant de choisir la disposition du texte
			justbool = true
		case "--output=" + filename: //flag permetant de créer un fichier dans lequel ce trouvera la sortie
			outputcheck = true
		case "--color=red": // le flag "color" permet de choisir la couleur de la sortie
			colorizedchar = red
		case "--color=blue":
			colorizedchar = blue
		case "--color=green":
			colorizedchar = green
		case "--color=pink":
			colorizedchar = pink
		case "--color=yellow":
			colorizedchar = yellow
		case "--color=cyan":
			colorizedchar = cyan
		case "--color=orange":
			colorizedchar = orange
		}
		if rune(arg[0]) == '-' && rune(arg[1]) == '-' { //permet de savoir si il faut print avec le flag "output" | permet de detecter les "--"
			printcheck++ //eviter que il print quand "--output est le seul flag"
		}
	}

	var lenghtstrarr []string
	totalcharlen := 0
	widthrest := 0

	//calcul largeur terminal
	if justbool {
		for j := 0; j < len(arg1); j++ { //boucle sur chaque lettre de l'arg 1
			//prend la largeur de lettre
			lenghtstrarr = append(lenghtstrarr, ReadLine(arg1[j], 6, style, widthrest, alignparam, nbrspace)) //"lenght" - "str" - "arr" | withdrest = longeur du reste
		}
		for y := 0; y < len(lenghtstrarr); y++ { // addition longueur de chaque case " 1 case = 1 lettre"
			totalcharlen += len(lenghtstrarr[y]) //longueur de la chaine de caractère en sortie dans le terminal
		}
		//longeur terminal - longueur total du mot
		widthrest = int(Width()) - totalcharlen //permet de savoir la longueur restante du terminal
	}

	//printer + permet de faire des "/n" dans le mot.
	if (len(os.Args) >= 2 && printcheck > 1) || (len(os.Args) >= 2 && outputcheck == false) { //print par defaut | 2 args = nom fichier + text en ""
		sep := string(rune(92)) + "n"
		stringarr := strings.Split(arg1, sep)
		for i := 0; i < len(stringarr); i++ {
			Printer(stringarr[i], colorizedchar, style, widthrest, alignparam, nbrspace) //print avec tout les arguments
		}
	}

	if outputcheck == true {
		//permet de créer un fichier dans lequel ce trouvera la sortie
		sep := string(rune(92)) + "n"
		stringarr := strings.Split(arg1, sep)
		jump := 0
		file, _ := os.Create(filename)

		for i := 0; i < len(stringarr); i++ {
			for h := 1; h <= 8; h++ {
				for j := 0; j < len(stringarr[i]); j++ {
					word := stringarr[i]
					letter := ReadLine(word[j], h, style, widthrest, alignparam, nbrspace)
					jump++
					filewriter, _ := file.WriteString(letter)
					if jump == len(word) && filewriter == filewriter {
						jump = 0
						filewriter, _ = file.WriteString("\n")
					}
				}
			}
		}
		file.Sync()
	}
}

func Printer(s string, couleur Color, style string, width int, param string, nbrspace int) {

	compteur := 0 // sert a compter le nombre de lettre ou se trouve , pour passer a la ligne suivante dans le standart.txt

	for i := 1; i <= 8; i++ { //boucle sur chaque etage "hauteur"
		for j := 0; j < len(s); j++ { //boule sur la "longueur" du mot

			//lier au flag "align", permet de choisir les différentes options de positionnement du texte
			switch param {
			case "center":
				if compteur == 0 && width != 0 {
					for d := 1; d <= width/2-2; d++ {
						fmt.Print(" ")
					}
				}
			case "right":
				if compteur == 0 && width != 0 {
					for d := 1; d <= width-2; d++ {
						fmt.Print(" ")
					}
				}
			}
			if param == "justify" && nbrspace == 0 {
				if compteur == 0 && width != 0 {
					for d := 1; d <= width/2-2; d++ {
						fmt.Print(" ")
					}
				}
			}
			compteur++
			if compteur == len(s) { //passe a la ligne suivante quand
				compteur = 0
				Colorizeln(couleur, ReadLine(s[j], i, style, width, param, nbrspace))
			} else {
				Colorize(couleur, ReadLine(s[j], i, style, width, param, nbrspace))

			}
		}
	}
}

//permet de lire les fichiers txt ligne par ligne afin de les imprimer
func ReadLine(letter byte, n int, style string, width int, param string, nbrspace int) string {

	//Permet de trouver la ligne à laquelle se trouve notre caractère
	line := int((rune(letter)-31)+(8*(rune(letter)-32))) + n // "rune lettre - 31" = pour commencer a regarder la bonne ligne | une lettre = 8 de hauteur , rune letter = lettre actuellement dans le mot ,// 32 = "espace en ASCII et ligne 0 du txt" | +n = pour savoir l'etage.
	file, _ := os.Open(style)                                //pour aller dans le fichier style
	stringline, _, _ := ReadChar(file, line)                 // lire le charactère

	if param == "justify" { // savoir quand on est sur un espace | si le charactère es tun espace on met un espace
		if rune(letter) == ' ' {
			for i := 0; i < (width/nbrspace)-6-2; i++ { // width = taille qui reste dans le terminale divisé par le nombre d'espace - 6 = largeur en ASCII et -2 = "/n
				stringline = stringline + " "
			}
		}
	}
	return stringline
}

//permet de transformer une ligne du txt en string - lire les charactères 1 par 1
func ReadChar(r io.Reader, lineNum int) (line string, lastLine int, err error) {
	sc := bufio.NewScanner(r)

	for sc.Scan() {
		lastLine++
		if lastLine == lineNum {
			return sc.Text(), lastLine, sc.Err()
		}
	}
	return line, lastLine, io.EOF
}

//Color (permet d'assigner une couleur à une constante)
type Color string

const (
	black      Color = "\u001b[30m"
	red              = "\u001b[31m"
	green            = "\u001b[32m"
	yellow           = "\u001b[33m"
	blue             = "\u001b[34m"
	pink             = "\u001b[35m"
	cyan             = "\u001b[36m"
	orange           = "\u001b[38;5;208m"
	ColorReset       = "\u001b[0m"
)

//permet de print une couleur sans saut de ligne
func Colorize(color Color, message string) {
	fmt.Print(string(color), message, ColorReset)
}

//permet de print une couleur avec saut de ligne
func Colorizeln(color Color, message string) {
	fmt.Println(string(color), message, ColorReset)
}

//retoune une string avec la largeur et la hauteur du terminal séparées pas un espace
func size() (string, error) {
	cmd := exec.Command("stty", "size")
	cmd.Stdin = os.Stdin
	out, err := cmd.Output()
	return string(out), err
}

//permet split la largeur et hauteur
func parse(input string) (uint, error) {
	parts := strings.Split(input, " ")
	y, err := strconv.Atoi(strings.Replace(parts[1], "\n", "", 1))
	if err != nil {
		return 0, err
	}
	return uint(y), nil
}

//retourne la largeur du terminal
func Width() uint {
	output, err := size()
	if err != nil {
		return 0
	}
	width, _ := parse(output)
	return width
}

```