diff --git a/bdd/bdd.go b/bdd/bdd.go index 4475c14..6b86638 100644 --- a/bdd/bdd.go +++ b/bdd/bdd.go @@ -1,27 +1,82 @@ package bdd import ( + "bytes" "fmt" - "log" + "time" - bolt "go.etcd.io/bbolt" + "github.com/boltdb/bolt" ) -// BDD_VOTES est le nom de la base -var BDD_VOTES = "VotesBucket" - -// InitBDD initialise la BDD -func InitBDD() { +// OpenDB a key-value store. +func OpenDB() (*bolt.DB, error) { db, err := bolt.Open("foods.db", 0600, nil) if err != nil { - log.Fatal(err) + return nil, fmt.Errorf("could not open db, %v", err) } - - db.Update(func(tx *bolt.Tx) error { - _, err := tx.CreateBucketIfNotExists([]byte(BDD_VOTES)) + err = db.Update(func(tx *bolt.Tx) error { + root, err := tx.CreateBucketIfNotExists([]byte("DB")) if err != nil { - return fmt.Errorf("create bucket: %s", err) + return fmt.Errorf("could not create root bucket: %v", err) + } + _, err = root.CreateBucketIfNotExists([]byte("VOTES")) + if err != nil { + return fmt.Errorf("could not create votes bucket: %v", err) } return nil }) + if err != nil { + return nil, fmt.Errorf("could not set up buckets, %v", err) + } + return db, nil + +} + +// CloseDB closes the key-value store file. +func CloseDB(db *bolt.DB) error { + return db.Close() +} + +// AddVote ajoute un vote à la bdd +func AddVote(db *bolt.DB, vote string, date time.Time) error { + + err := db.Update(func(tx *bolt.Tx) error { + err := tx.Bucket([]byte("DB")).Bucket([]byte("VOTES")).Put([]byte(date.Format(time.RFC3339)), []byte(vote)) + if err != nil { + return fmt.Errorf("could not insert vote: %v", err) + } + return nil + }) + fmt.Println("Added vote") + return err +} + +// GetAllVotes liste tous les votes +func GetAllVotes(db *bolt.DB) ([]string, error) { + + res := []string{} + err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("DB")).Bucket([]byte("VOTES")) + b.ForEach(func(k, v []byte) error { + res = append(res, string(v)) + return nil + }) + return nil + }) + return res, err +} + +// GetVotesOfTheDay liste tous les votes du jour +func GetVotesOfTheDay(db *bolt.DB, date time.Time) ([]string, error) { + res := []string{} + err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("DB")).Bucket([]byte("VOTES")).Cursor() + min := []byte(time.Now().AddDate(0, 0, -1).Format(time.RFC3339)) + max := []byte(time.Now().AddDate(0, 0, 0).Format(time.RFC3339)) + for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; k, v = c.Next() { + res = append(res, string(v)) + } + return nil + }) + return res, err } diff --git a/foodlist/foodlist.go b/foodlist/foodlist.go index b0b6c22..9e42278 100644 --- a/foodlist/foodlist.go +++ b/foodlist/foodlist.go @@ -6,6 +6,7 @@ import ( "io" "log" "os" + "time" ) // FoodOfTheDay is the food list of the day @@ -21,7 +22,7 @@ type Food struct { } // GetFoodOfTheDay return the list of food of the day -func GetFoodOfTheDay(Today string) FoodOfTheDay { +func GetFoodOfTheDay() FoodOfTheDay { foodcsv, _ := os.Open("foodlist/foods.csv") foodreader := csv.NewReader(bufio.NewReader(foodcsv)) foods := FoodOfTheDay{} @@ -35,7 +36,7 @@ func GetFoodOfTheDay(Today string) FoodOfTheDay { food := Food{line[0], line[1]} foods.Foods = append(foods.Foods, food) } - foods.Date = Today + foods.Date = time.Now().Format("02/01/2006") return foods } diff --git a/foods.db b/foods.db index 655109f..b21f79b 100644 Binary files a/foods.db and b/foods.db differ diff --git a/my.db b/my.db deleted file mode 100644 index ffa854c..0000000 Binary files a/my.db and /dev/null differ diff --git a/server b/server index de9bf4e..43052d1 100755 Binary files a/server and b/server differ diff --git a/server.go b/server.go index 6d1693c..cbcfbda 100644 --- a/server.go +++ b/server.go @@ -3,42 +3,48 @@ package main import ( "cadoles/foodoles/bdd" "cadoles/foodoles/foodlist" - votefood "cadoles/foodoles/vote" + "cadoles/foodoles/vote" "html/template" "log" "net/http" - "time" ) -// Today is today -var Today = time.Now().Format("02/01/2006") - func main() { - http.HandleFunc("/", base) - http.HandleFunc("/results", resultsPage) - bdd.InitBDD() - log.Print("ready: listening on localhost:8080\n") + http.HandleFunc("/", Base) + http.HandleFunc("/results", ResultsPage) + db, err := bdd.OpenDB() + if err != nil { + log.Printf("\nOpenDB error: %v", err) + return + } + bdd.CloseDB(db) + + vote.GetVotesOfTheDay() + + log.Print("\nready: listening on localhost:8080\n") if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } } -func base(w http.ResponseWriter, r *http.Request) { +// Base is the entry point to all requests +func Base(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { - votePage(w, r) + VotePage(w, r) } else if r.Method == http.MethodGet { - homePage(w, r) + HomePage(w, r) } else { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("400 - Unsupported Request Method!")) } } -func homePage(w http.ResponseWriter, r *http.Request) { - foods := foodlist.GetFoodOfTheDay(Today) +// HomePage is the homepage of the app +func HomePage(w http.ResponseWriter, r *http.Request) { + foods := foodlist.GetFoodOfTheDay() paths := []string{ "./templates/index.tmpl", } @@ -50,23 +56,33 @@ func homePage(w http.ResponseWriter, r *http.Request) { } } -func resultsPage(w http.ResponseWriter, r *http.Request) { +// ResultsPage is the page displaiyng the votes results +func ResultsPage(w http.ResponseWriter, r *http.Request) { + db, err := bdd.OpenDB() + if err != nil { + log.Printf("\nOpenDB error: %v", err) + return + } + //vote, _ := bdd.GetVotesOfTheDay(db, time.Now().AddDate(0, 0, -1)) + bdd.CloseDB(db) paths := []string{ "./templates/results.tmpl", } t := template.Must(template.New("results.tmpl").ParseFiles(paths...)) - err := t.Execute(w, "") + err = t.Execute(w, "") if err != nil { log.Printf("\nExecute error: %v", err) return } } -func votePage(w http.ResponseWriter, r *http.Request) { +// VotePage is the endpoint to add votes +func VotePage(w http.ResponseWriter, r *http.Request) { r.ParseForm() option := r.Form.Get("option") + log.Print("vote for : ", option) - votefood.ForFood(Today, option) + vote.ForFood(option) w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") diff --git a/templates/results.tmpl b/templates/results.tmpl index 4703768..84afca0 100644 --- a/templates/results.tmpl +++ b/templates/results.tmpl @@ -9,6 +9,11 @@ +{{ range .Foods }} +
+
{{ .Icon }}
+
+ {{ end }}

TV Show - Poll Results


+
{{.Key}}
{{.Cluster}}
diff --git a/vote/vote.go b/vote/vote.go index 03c3bcc..4d17635 100644 --- a/vote/vote.go +++ b/vote/vote.go @@ -1,5 +1,12 @@ package vote +import ( + "cadoles/foodoles/bdd" + "fmt" + "log" + "time" +) + // VotesOfTheDay est le résultat des votes du jour type VotesOfTheDay struct { Date string @@ -13,6 +20,69 @@ type Vote struct { } // ForFood vote pour un choix du jour -func ForFood(Today string, Food string) { +func ForFood(Food string) { + db, err := bdd.OpenDB() + if err != nil { + log.Printf("\nOpenDB error: %v", err) + return + } + bdd.AddVote(db, Food, time.Now().AddDate(0, 0, 0)) + bdd.CloseDB(db) return } + +// GetVotesOfTheDay récupère les votes du jour +func GetVotesOfTheDay() VotesOfTheDay { + time.Now() + vo := VotesOfTheDay{time.Now().Format("02/01/2006"), nil} + duplicate := FoodList() + + dupmap := dupcount(duplicate) + + fmt.Println(dupmap) + + for k, v := range dupmap { + vv := Vote{k, v} + vo.Votes = append(vo.Votes, vv) + } + fmt.Println(vo) + return vo +} + +// FoodList return a list of food +func FoodList() []Vote { + f := []Vote{} + + db, err := bdd.OpenDB() + if err != nil { + log.Fatal(err) + } + + lvotes, _ := bdd.GetVotesOfTheDay(db, time.Now()) + + for _, fo := range lvotes { + vf := Vote{fo, 1} + f = append(f, vf) + } + bdd.CloseDB(db) + + return f +} + +func dupcount(list []Vote) map[string]int { + + duplicatefrequency := make(map[string]int) + + for _, item := range list { + // check if the item/element exist in the duplicate_frequency map + + _, exist := duplicatefrequency[item.Food] + + if exist { + duplicatefrequency[item.Food]++ // increase counter by 1 if already in the map + } else { + duplicatefrequency[item.Food] = 1 // else start counting from 1 + } + } + return duplicatefrequency +}