diff --git a/agt/ballotagent/vote.go b/agt/ballotagent/vote.go index ac17b11b1147241a3c7ee2c0bed154d09d32ca66..0bb7f8746a471a7f309f2e88c7ae355f59c25c16 100644 --- a/agt/ballotagent/vote.go +++ b/agt/ballotagent/vote.go @@ -3,8 +3,28 @@ package ballotagent import ( "fmt" "net/http" + + rad "gitlab.utc.fr/gvandevi/ia04binome2a" + cs "gitlab.utc.fr/gvandevi/ia04binome2a/comsoc" ) +func contains[S []string | []rad.Ballot, E string | rad.Ballot](s S, e E) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} + +func intToAlt(s []int) []cs.Alternative { + res := make([]cs.Alternative, len(s)) + for i, v := range s { + res[i] = cs.Alternative(v) + } + return res +} + func (rsa *BallotServerAgent) receiveVote(w http.ResponseWriter, r *http.Request) { // mise à jour du nombre de requêtes rsa.Lock() @@ -17,7 +37,7 @@ func (rsa *BallotServerAgent) receiveVote(w http.ResponseWriter, r *http.Request } // décodage de la requête - req, err := rsa.decodeRequest(r) + req, err := decodeRequest[rad.Vote](r) if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprint(w, err.Error()) @@ -25,5 +45,60 @@ func (rsa *BallotServerAgent) receiveVote(w http.ResponseWriter, r *http.Request } // recupération des infos - scrutin := req. + scrutin := req.BallotID + voteBallot := rad.Ballot{BallotID: scrutin} + ballots := make([]rad.Ballot, len(rsa.ballots)) + + // Check if ballot exists + i := 0 + for k := range rsa.ballots { + ballots[i] = k + i++ + } + if !contains[[]rad.Ballot, rad.Ballot](ballots, voteBallot) { + w.WriteHeader(http.StatusBadRequest) + msg := fmt.Sprintf("The ballot '%s' does not exist", scrutin) + w.Write([]byte(msg)) + return + } + ballot := rsa.ballots[voteBallot] + + // Check que la deadline n'est pas déjà passée + if !ballot.isOpen { + w.WriteHeader(http.StatusServiceUnavailable) + msg := fmt.Sprintf("The deadline has passed, the ballot '%s' is therefore closed.", scrutin) + w.Write([]byte(msg)) + return + } + + // Check que l'agent fait bien partie des votants + if !contains(ballot.votersId, req.AgentID) { + w.WriteHeader(http.StatusForbidden) + msg := fmt.Sprintf("The user '%s' has either already voted or cannot vote", req.AgentID) + w.Write([]byte(msg)) + return + } + + // Check if vote is valid beforehand (don't want to register a vote that could break the results' calculation) + tempProf := make(cs.Profile, 1) + tempProf[0] = intToAlt(req.Prefs) + _, errPrefs := cs.MajoritySWF(tempProf) + if errPrefs != nil || len(req.Prefs) != ballot.nbAlts { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprint(w, errPrefs.Error()) + return + } + + // Register the vote + ballot.profile = append(ballot.profile, intToAlt(req.Prefs)) + if len(req.Options) != 0 { + ballot.options = append(ballot.options, req.Options[0]) + } + // On elève l'agent de la liste des agents votants + for i, agt := range ballot.votersId { + if agt == req.AgentID { + ballot.votersId[i] = ballot.votersId[len(ballot.votersId)-1] + ballot.votersId = ballot.votersId[:len(ballot.votersId)-1] + } + } }