Skip to content
Snippets Groups Projects
Commit be7b14e5 authored by Balthazar Wilson's avatar Balthazar Wilson
Browse files

debut implementation bureau de vote

parent 87aacc97
No related branches found
No related tags found
1 merge request!7Partie serveur
package main
import (
"fmt"
"log"
"math/rand"
"gitlab.utc.fr/lagruesy/ia04/demos/restagentdemo/restclientagent"
"gitlab.utc.fr/lagruesy/ia04/demos/restagentdemo/restserveragent"
)
func main() {
const n = 100
const url1 = ":8080"
const url2 = "http://localhost:8080"
ops := [...]string{"+", "-", "*"}
clAgts := make([]restclientagent.RestClientAgent, 0, n)
servAgt := restserveragent.NewRestServerAgent(url1)
log.Println("démarrage du serveur...")
go servAgt.Start()
log.Println("démarrage des clients...")
for i := 0; i < n; i++ {
id := fmt.Sprintf("id%02d", i)
op := ops[rand.Intn(3)]
op1 := rand.Intn(100)
op2 := rand.Intn(100)
agt := restclientagent.NewRestClientAgent(id, url2, op, op1, op2)
clAgts = append(clAgts, *agt)
}
for _, agt := range clAgts {
// attention, obligation de passer par cette lambda pour faire capturer la valeur de l'itération par la goroutine
func(agt restclientagent.RestClientAgent) {
go agt.Start()
}(agt)
}
fmt.Scanln()
}
package main
import (
"fmt"
"gitlab.utc.fr/lagruesy/ia04/demos/restagentdemo/restclientagent"
)
func main() {
ag := restclientagent.NewRestClientAgent("id1", "http://localhost:8080", "+", 11, 1)
ag.Start()
fmt.Scanln()
}
package main
import (
"fmt"
ras "gitlab.utc.fr/lagruesy/ia04/demos/restagentdemo/restserveragent"
)
func main() {
server := ras.NewRestServerAgent(":8080")
server.Start()
fmt.Scanln()
}
module gitlab.utc.fr/gvandevi/ia04
module tp5
go 1.21.1
go 1.21
require gitlab.utc.fr/lagruesy/ia04 v0.2.1 // indirect
# Exemple de serveur Rest en Go
Un agent permet de faire de petites opérations arithmétiques (`+`, `-`, `*`) sur 2 entiers si on lui demande en REST.
Techniquement le serveur n'est pas pur REST (à vous de trouver pourquoi), mais il est fonctionnel et peut tenir la charge.
3 exécutables (indépendants) sont fournis :
* `launch-all-rest-agents` permet de lancer une démo avec un seul exécutable
* `lanch-rsagt` permet de lancer un agent de type serveur
* `lanch-rsagt` permet de lancer un agent de type client
\ No newline at end of file
package restclientagent
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
rad "gitlab.utc.fr/lagruesy/ia04/demos/restagentdemo"
)
type RestClientAgent struct {
id string
url string
operator string
arg1 int
arg2 int
}
func NewRestClientAgent(id string, url string, op string, arg1 int, arg2 int) *RestClientAgent {
return &RestClientAgent{id, url, op, arg1, arg2}
}
func (rca *RestClientAgent) treatResponse(r *http.Response) int {
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
var resp rad.Response
json.Unmarshal(buf.Bytes(), &resp)
return resp.Result
}
func (rca *RestClientAgent) doRequest() (res int, err error) {
req := rad.Request{
Operator: rca.operator,
Args: [2]int{rca.arg1, rca.arg2},
}
// sérialisation de la requête
url := rca.url + "/calculator"
data, _ := json.Marshal(req)
// envoi de la requête
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
// traitement de la réponse
if err != nil {
return
}
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("[%d] %s", resp.StatusCode, resp.Status)
return
}
res = rca.treatResponse(resp)
return
}
func (rca *RestClientAgent) Start() {
log.Printf("démarrage de %s", rca.id)
res, err := rca.doRequest()
if err != nil {
log.Fatal(rca.id, "error:", err.Error())
} else {
log.Printf("[%s] %d %s %d = %d\n", rca.id, rca.arg1, rca.operator, rca.arg2, res)
}
}
package restserveragent
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"sync"
"time"
rad "ia04" // à remplacer par le nom du dossier actuel
)
type RestServerAgent struct {
sync.Mutex
id string
reqCount int
addr string
}
func NewRestServerAgent(addr string) *RestServerAgent {
return &RestServerAgent{id: addr, addr: addr}
}
// Test de la méthode
func (rsa *RestServerAgent) checkMethod(method string, w http.ResponseWriter, r *http.Request) bool {
if r.Method != method {
w.WriteHeader(http.StatusMethodNotAllowed)
fmt.Fprintf(w, "method %q not allowed", r.Method)
return false
}
return true
}
func (*RestServerAgent) decodeRequest(r *http.Request) (req rad.BallotRequest, err error) {
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
err = json.Unmarshal(buf.Bytes(), &req)
return
}
func (rsa *RestServerAgent) doCalc(w http.ResponseWriter, r *http.Request) {
// mise à jour du nombre de requêtes
rsa.Lock()
defer rsa.Unlock()
rsa.reqCount++
// vérification de la méthode de la requête
if !rsa.checkMethod("POST", w, r) {
return
}
// décodage de la requête
req, err := rsa.decodeRequest(r)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, err.Error())
return
}
// traitement de la requête
var resp rad.Ballot
resp.BallotID = "ballot1"
switch req.Rule {
case "majority":
case "borda":
case "approval":
case "stv":
default:
w.WriteHeader(http.StatusNotImplemented)
msg := fmt.Sprintf("Unkonwn rule '%s'", req.Rule)
w.Write([]byte(msg))
return
}
w.WriteHeader(http.StatusOK)
serial, _ := json.Marshal(resp)
w.Write(serial)
}
func (rsa *RestServerAgent) doReqcount(w http.ResponseWriter, r *http.Request) {
if !rsa.checkMethod("GET", w, r) {
return
}
w.WriteHeader(http.StatusOK)
rsa.Lock()
defer rsa.Unlock()
serial, _ := json.Marshal(rsa.reqCount)
w.Write(serial)
}
func (rsa *RestServerAgent) Start() {
// création du multiplexer
mux := http.NewServeMux()
mux.HandleFunc("/calculator", rsa.doCalc)
mux.HandleFunc("/reqcount", rsa.doReqcount)
// création du serveur http
s := &http.Server{
Addr: rsa.addr,
Handler: mux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20}
// lancement du serveur
log.Println("Listening on", rsa.addr)
go log.Fatal(s.ListenAndServe())
}
types.go 0 → 100644
package ia04binom2a
type BallotRequest struct {
Rule string `json:"rule"`
Deadline string `json:"deadline"`
VotersID []string `json:"voters-id"`
NbAlts int `json:"#alts"`
TieBreak []int `json:"tie-break"`
}
type Vote struct {
AgentID string `json:"agent-id"`
BallotID string `json:"ballot-id"`
Prefs []int `json:"prefs"`
Options []int `json:"options"`
}
type Ballot struct {
BallotID string `json:"ballot-id"`
}
type ResultResponse struct {
Winner int `json:"winner"`
Ranking []int `json:"ranking"`
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment