venerdì 25 febbraio 2022

Quadtree in Go

metto questo abbozzo di codice perche', nonostante non funzionante, puo' essere interessante

Ai tempi di Fractint su Dos c'e un algoritmo che divideva il piano di quadrati, se i punti estremi del quadrato avevano lo stesso valore allora tutto il quadrato assumeva lo stesso colore dell'insieme di Mandelbrot, in caso contrario il quadrato veniva a sua volta diviso in 4 quadrati e si reiterava

In questo caso ho cercato di fare lo stesso usando le goroutine  ed la ricorsione


package main

import (
    "fmt"
    "math"
    "math/cmplx"
    "reflect"
    "strconv"
    "sync"

    "github.com/fogleman/gg"
)

var wg sync.WaitGroup

// ATTENZION    E il nome delle variabili deve essere in uppercase
// per poter esportare la variabile e
type punto struct {
    Min_x float64
    Max_x float64
    Min_y float64
    Max_y float64
    Itera int64
}

var punti []punto // slice di struct
var transi punto
var mu sync.Mutex

func calcola(a float64, b float64) int {
    var k int
    c := complex(a, b)
    k = 0

    x := complex(0.0, 0.0)
    for k = 0; k < 25; k++ {
        x_a := (x * x)
        x_a = x_a + c
        x = x_a
        if cmplx.Abs(x) > 2 {
            return k
        }
    }
    return k
}

func dividi(min_x float64, max_x float64, min_y float64, max_y float64) {
    defer wg.Done()

    x1 := calcola(min_x, min_y)
    x2 := calcola(max_x, max_y)

    if (x1 != x2) && (max_x-min_x > 0.005) {

        mezzo_x := (max_x - min_x) / 2
        mezzo_y := (max_y - min_y) / 2
        wg.Add(4)
        go dividi(min_x, min_x+mezzo_x, min_y, min_y+mezzo_y)
        go dividi(min_x+mezzo_x, max_x, min_y, min_y+mezzo_y)
        go dividi(min_x, min_x+mezzo_x, min_y+mezzo_y, max_y)
        go dividi(min_x+mezzo_x, max_x, min_y+mezzo_y, max_y)

    } else {
        fmt.Println(strconv.FormatFloat(min_x, 'f', 6, 32) + ";" + strconv.FormatFloat(min_y, 'f', 6, 32) + ";" + strconv.Itoa(x1))

        s := reflect.ValueOf(&transi).Elem()
        s.Field(0).SetFloat(min_x)
        s.Field(1).SetFloat(max_x)
        s.Field(2).SetFloat(min_y)
        s.Field(3).SetFloat(max_y)
        s.Field(4).SetInt(int64(x1))

        mu.Lock()
        punti = append(punti, transi)
        mu.Unlock()
    }

}

func grafica() {
    dc := gg.NewContext(400, 400)

    dx := 3.0 / 400
    dy := 2.0 / 400

    for _, value := range punti {
        fmt.Printf("%d\n", value)
        min_x := math.Round(value.Min_x*dx) + 200
        max_x := math.Round(value.Max_x*dx) + 200
        min_y := math.Round((value.Min_y * dy)) + 200
        max_y := math.Round((value.Max_y * dy)) + 200
        dc.DrawRectangle(min_x, max_x, min_y, max_y)
        dc.SetRGB255(value.Itera, 0, 0)
        dc.Fill()

    }

    dc.SavePNG("mandelbrot.png")
}

func main() {
    wg.Add(1)
    go dividi(-2.0, 1.0, -1.0, 1.0)
    wg.Wait()
    grafica()
}

Grafica base in Go

 package main


import "github.com/fogleman/gg"

func main() {
    dc := gg.NewContext(1000, 1000)
    //dc.Push()
    dc.DrawCircle(500, 500, 400)
    dc.SetRGB255(0, 0, 0)
    dc.Fill()
   
    dc.SetHexColor("#008080")
    dc.DrawRectangle(10,10,40,30)
    dc.SetRGB255(255, 0, 0)

    dc.Fill()
   
    dc.SavePNG("out.png")
}

martedì 22 febbraio 2022

Webassembly Golang Mandelbrot

Era da tempo che volevo provare WebAssembly (abbreviato wasm).. ho scoperto che sia GoLang che Qt permettono di compilare in Wasm e cosi' ho fatto una prova

Per eseguire applicazioni WAsm si deve configurare il webserver a riconoscere il Mime Type wasm . In Apache e' sufficiente aggiungere la linea in /etc/mime.types mentre in NGinx /etc/nginx/mime.types con application/wasm  wasm;

Il file compilato deve avere l'estensione .wasm

Per compilare il file go.wasm si usa la linea di comando

GOOS=js GOARCH=wasm go build -o wasm.wasm

ATTENZIONE: i file wasm rimangono in cache del browser. In fase di sviluppo e' quindi necessario sincerarsi di pulire la cache con CTRL+SHIFT+R (od usare una sessione anonima)

Per creare il file wasm_exec.js e' sufficiente (attenzione al punto finale)

cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .

Il programma genera una immagine dell'insieme di Mandelbrot che viene codificata in PNG e successivamente in Base64 per divenire la src del tag img della pagina web

https://github.com/c1p81/gowasm_mand


wasm.go

package main

// cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .

import (
"bytes"
"encoding/base64"
"fmt"
"image"
"image/color"
"image/png"
"io/ioutil"
"syscall/js"
)

func funzione() js.Func {
jsonFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {

//////////////////////////////////////////////////////////////////////////////
var SCREEN_WIDTH int = 400
var SCREEN_HEIGHT int = 400

var re_min float32 = -2.0
var im_min float32 = -1.2
var re_max float32 = 1.0
var im_max float32 = 1.2

var iterazioni int = 1024

var a, b float32
var x, y, x_new, y_new, somma float32
var k, i, j int

var re_factor float32 = (re_max - re_min)
var im_factor float32 = (im_max - im_min)

m := image.NewRGBA(image.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT))

for i = 0; i < SCREEN_HEIGHT; i++ {
for j = 0; j < SCREEN_WIDTH; j++ {
a = re_min + (float32(j) * re_factor / float32(SCREEN_WIDTH))
b = im_min + (float32(i) * im_factor / float32(SCREEN_HEIGHT))
x = 0
y = 0

for k = 0; k < iterazioni; k++ {
x_new = (float32(x) * float32(x)) - (float32(y) * float32(y)) + float32(a)
y_new = (float32(2) * float32(x) * float32(y)) + float32(b)
somma = (x_new * x_new) + (y_new * y_new)
if somma > 4 {
if k%2 == 0 {
m.Set(j, i, color.RGBA{0, 0, 0, 255})
} else {
m.Set(j, i, color.RGBA{255, 255, 255, 255})
}
break
}
x = x_new
y = y_new
}
}
}

buf := new(bytes.Buffer)
if err := png.Encode(buf, m); err != nil {
return ("unable to encode png")
}
readBuf, _ := ioutil.ReadAll(buf)

enc := base64.StdEncoding.EncodeToString([]byte(readBuf))

return "data:image/png;base64," + enc
})
return jsonFunc
}

func main() {
fmt.Println("Inizio")
js.Global().Set("go_function", funzione())
fmt.Println(funzione())
<-make(chan bool)
}

 

Index.html

<html>
<head>
<meta charset="utf-8"/>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("wasm.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body>
<center> 2
<img id="immagine" name="immagine" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" /><br><br>
<input id="button" type="submit" name="button" onclick="ff()"/> <br>
<textarea id="imgbase64" name="imgbase64" cols="80" rows="200"></textarea>

</center>



<script>
var ff = function() {
immagine.src = go_function(ff)
imgbase64.value = go_function(ff)
}
</script>
</body>
</html>




venerdì 11 febbraio 2022

Ser2Net Go

 Premesso che questo non e' il sistema corretto di usare una goroutine in quanto non termina mai ho provato a fare questo programma che in una goroutine legge i valori da una porta seriale e tramite un channel manda i dati ad un'altra goroutine che invia sulla rete

non e' un codice da copiare

package main
import (
    "bufio"
    "fmt"
    "io"
    "log"
    "net"
    "time"

    "github.com/tarm/serial"
)

/*
per fare i test si puo' creare una porta seriale virtuale con
socat -d -d pty,raw,echo=0 pty,raw,echo=0
il sistema risponde con messaggi del tipo
socat -d -d pty,raw,echo=0 pty,raw,echo=0

2022/01/02 14:53:04 socat[18636] N PTY is /dev/pts/3
2022/01/02 14:53:04 socat[18636] N PTY is /dev/pts/4
2022/01/02 14:53:04 socat[18636] N starting data transfer loop with FDs [5,5] and [7,7]

si apre un altro terminale e si inviano i messaggi sulla seconda porta
echo "messaggio" > /dev/pts/4
il programma in Go deve andare in ascolto sull /dev/pts/3
*/

func main() {
    canale := make(chan []byte, 1024)

    usbRead := &serial.Config{Name: "/dev/pts/3", Baud: 9600}
    //s, err := serial.OpenPort(c)
    port, err := serial.OpenPort(usbRead)
    if err != nil {
        log.Fatal(err)
    }
    scanner := bufio.NewScanner(port)
    go scrivi_channel(canale, scanner)

    listener, err := net.Listen("tcp", "localhost:8000")
    if err != nil {
        log.Fatal(err)
    }
    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Print(err) // e.g., connection aborted
            continue
        }
        handleConn(conn, canale) // handle one connection at a time
    }
}

func handleConn(c net.Conn, canale chan []byte) {
    defer c.Close()
    for {
        _, err := io.WriteString(c, string(<-canale)+" "+time.Now().Format("15:04:05\n"))
        if err != nil {
            return // e.g., client disconnected
        }
        time.Sleep(1 * time.Second)
    }
}

func scrivi_channel(canale chan []byte, scanner *bufio.Scanner) {
    buf := make([]byte, 128)
    scanner.Buffer(buf, 128)
    for {

        //scanner.Buffer(buf, 128)
        scanner.Scan()
        input := scanner.Text()
        fmt.Println(input)
        canale <- []byte(input)
        time.Sleep(1 * time.Second)
    }

    //time.Sleep(1 * time.Second)
    //canale <- []byte("test")
}

Rest Client in Python

Dopo la versione in Go la medesima funzione in Python 


import requests
from requests.structures import CaseInsensitiveDict
import json

url = "http://xxxxxxxxxxxxx/api/v1/authentication/"

headers = CaseInsensitiveDict()


headers["api-key"] = "apikey"
headers["Accept"] = "application/json"
headers["api-version"] = "v1"
headers["device-language"] = "it"
headers["id-user-session"] = "guest"
headers["Authorization"] = "Basic Z2xxxxxxxxxxxxxxxxxxxxxxxxxxx=="



resp = requests.get(url, headers=headers)

print(resp.content)
if(resp.ok):
    jData = json.loads(resp.content)

    print("The response contains {0} properties".format(len(jData)))
    print("\n")
    for key in jData:
        print(str(key) + " : " + str(jData[key]))
else:
    resp.raise_for_status()

TicTacToe Go

 Volevo provare a creare una macchina di apprendimento per il gioco TicTacToe (Tris) 

Il passo e' stato quello di creare il gioco per umani...la cosa che mi ha dato piu' soddisfazione e' stata la funzione per determinare la condizione di vittoria dei giocatori

In pratica ogni casella del gioco e' associata ad una potenza di 2...si sommano i valori delle caselle e si fa un AND con la maschera di bit delle condizioni di vittoria

il prossimo passo e' salvare le varie partite con una Trie 

---------------------------

Il nome delle caselle e' cosi' ordinato

0 | 1 | 2
______
3 | 4 | 5
______
6 | 7 | 8



package main

import (
    "fmt"
    "math"
    "os"
    "strconv"
)

var display [9]int // array per mostrare il gioco
var step int       // numero di mossa
var giocatore int
var mossa_valida bool

func reset() {
    for k := 0; k < 9; k++ {
        display[k] = 0
    }
    step = 1
    giocatore = 3
    mossa_valida = false
}

func controlla_vittoria() int {
    totale_1 := 0
    totale_2 := 0

    // per il calcolo della scacchiera ad ogni casella corrispondente un valore di potenza di 2
    // si sommano tutti le caselle occupate da un giocatore
    // poi si effettua un AND logic con le 8 posizioni vincenti

    // giocatore 1
    for k := 0; k < 9; k++ {
        if display[k] == 3 {
            totale_1 = totale_1 + int(math.Pow(float64(2), float64(k)))
        }
    }

    if (totale_1 & 448) == 448 {
        return 1
    }
    if (totale_1 & 56) == 56 {
        return 1
    }
    if (totale_1 & 7) == 7 {
        return 1
    }
    if (totale_1 & 292) == 292 {
        return 1
    }
    if (totale_1 & 146) == 146 {
        return 1
    }
    if (totale_1 & 73) == 73 {
        return 1
    }
    if (totale_1 & 273) == 273 {
        return 1
    }
    if (totale_1 & 84) == 84 {
        return 1
    }

    // giocatore 2
    for k := 0; k < 9; k++ {
        if display[k] == 2 {
            totale_2 = totale_2 + int(math.Pow(float64(2), float64(k)))
        }
    }

    if (totale_2 & 448) == 448 {
        return 2
    }
    if (totale_2 & 56) == 56 {
        return 2
    }
    if (totale_2 & 7) == 7 {
        return 2
    }
    if (totale_2 & 292) == 292 {
        return 2
    }
    if (totale_2 & 146) == 146 {
        return 2
    }
    if (totale_2 & 73) == 73 {
        return 2
    }
    if (totale_2 & 273) == 273 {
        return 2
    }
    if (totale_2 & 84) == 84 {
        return 2
    }

    return 0 // se ritorna 0 nessuno ha vinto
}

func casella(c int) string {
    switch c {
    case 0:
        return (" ")
    case 3:
        return ("X")
    case 2:
        return ("O")
    }
    return " "
}

func mostra_gioco() {
    fmt.Print(casella(display[0]))
    fmt.Print("|")
    fmt.Print(casella(display[1]))
    fmt.Print("|")
    fmt.Println(casella(display[2]))
    fmt.Println("-----")
    fmt.Print(casella(display[3]))
    fmt.Print("|")
    fmt.Print(casella(display[4]))
    fmt.Print("|")
    fmt.Println(casella(display[5]))
    fmt.Println("-----")
    fmt.Print(casella(display[6]))
    fmt.Print("|")
    fmt.Print(casella(display[7]))
    fmt.Print("|")
    fmt.Println(casella(display[8]))
}

func main() {

    var tasto int

    step = 1
    giocatore = 3
    mossa_valida = false
    mostra_gioco()
    fmt.Println("Turno al Giocatore " + strconv.Itoa(giocatore-2))

    for {
        for { // controlla se e' una mossa valida

            if !mossa_valida {
                fmt.Print("Enter move: ")
                fmt.Scanln(&tasto)
                // controlla se e' un tasto valido

                if display[tasto] == 0 { // controlla se la casella e' valida
                    mossa_valida = true
                    display[tasto] = giocatore
                    giocatore = ((giocatore + 1) % 2) + 2
                    fmt.Println("Turno al Giocatore " + string(giocatore+2))
                    break
                } else {
                    fmt.Println("Mossa non valida")
                }

            }
        }

        step++ // aumenta il numero della mossa
        mossa_valida = false
        mostra_gioco()
        v := controlla_vittoria()
        switch v {
        case 1:
            fmt.Println("****************************")
            fmt.Println("*** Vittoria Giocatore 1 ***")
            fmt.Println("****************************")
            reset()
            mostra_gioco()
            break
        case 2:
            fmt.Println("****************************")
            fmt.Println("*** Vittoria Giocatore 2 ***")
            fmt.Println("****************************")
            reset()
            mostra_gioco()
            break
        }
        if step == 9 {
            fmt.Println("***************************")
            fmt.Println("******** Pareggio *********")
            fmt.Println("***************************")
            reset()
            mostra_gioco()
            break
        }
    }
    os.Exit(0)
}

Rest client in GO

Un semplice di client di servizio Restful con GO


package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func main() {
    client := http.Client{}
    req, err := http.NewRequest("GET", "http://xxxxxxxxxxxxxxxxx/api/v1/authentication/", nil)
    if err != nil {
        //Handle Error
    }

    req.Header = http.Header{
        "Host":                  []string{"http://xxxxxxxxxxxxxxxxxx/api/v1/authentication/"},
        "api-key":         []string{"axxxxxxxxxxxx"},
        "api-version":     []string{"v1"},
        "device-language": []string{"it"},
        "id-user-session": []string{"guest"},
        "Accept":                []string{"application/json"},
        "Authorization":         []string{"Basic Z2lvxxxxxxxxxxxxxxsaQ=="},
    }

    res, err := client.Do(req)

    if err != nil {
        fmt.Errorf("got error")
    } else {
        //fmt.Println("--------------------------")
        //fmt.Println(res)
    }
    defer res.Body.Close()

    b, err := ioutil.ReadAll(res.Body)
    if err != nil {
        log.Fatalln(err)
    }

    fmt.Println(string(b))
}

Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...