set bdd
This commit is contained in:
parent
a112fa589f
commit
0deab5858d
79
bdd/bdd.go
79
bdd/bdd.go
@ -1,27 +1,82 @@
|
|||||||
package bdd
|
package bdd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"time"
|
||||||
|
|
||||||
bolt "go.etcd.io/bbolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BDD_VOTES est le nom de la base
|
// OpenDB a key-value store.
|
||||||
var BDD_VOTES = "VotesBucket"
|
func OpenDB() (*bolt.DB, error) {
|
||||||
|
|
||||||
// InitBDD initialise la BDD
|
|
||||||
func InitBDD() {
|
|
||||||
db, err := bolt.Open("foods.db", 0600, nil)
|
db, err := bolt.Open("foods.db", 0600, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return nil, fmt.Errorf("could not open db, %v", err)
|
||||||
}
|
}
|
||||||
|
err = db.Update(func(tx *bolt.Tx) error {
|
||||||
db.Update(func(tx *bolt.Tx) error {
|
root, err := tx.CreateBucketIfNotExists([]byte("DB"))
|
||||||
_, err := tx.CreateBucketIfNotExists([]byte(BDD_VOTES))
|
|
||||||
if err != nil {
|
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
|
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
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FoodOfTheDay is the food list of the day
|
// FoodOfTheDay is the food list of the day
|
||||||
@ -21,7 +22,7 @@ type Food struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetFoodOfTheDay return the list of food of the day
|
// GetFoodOfTheDay return the list of food of the day
|
||||||
func GetFoodOfTheDay(Today string) FoodOfTheDay {
|
func GetFoodOfTheDay() FoodOfTheDay {
|
||||||
foodcsv, _ := os.Open("foodlist/foods.csv")
|
foodcsv, _ := os.Open("foodlist/foods.csv")
|
||||||
foodreader := csv.NewReader(bufio.NewReader(foodcsv))
|
foodreader := csv.NewReader(bufio.NewReader(foodcsv))
|
||||||
foods := FoodOfTheDay{}
|
foods := FoodOfTheDay{}
|
||||||
@ -35,7 +36,7 @@ func GetFoodOfTheDay(Today string) FoodOfTheDay {
|
|||||||
food := Food{line[0], line[1]}
|
food := Food{line[0], line[1]}
|
||||||
foods.Foods = append(foods.Foods, food)
|
foods.Foods = append(foods.Foods, food)
|
||||||
}
|
}
|
||||||
foods.Date = Today
|
foods.Date = time.Now().Format("02/01/2006")
|
||||||
|
|
||||||
return foods
|
return foods
|
||||||
}
|
}
|
||||||
|
52
server.go
52
server.go
@ -3,42 +3,48 @@ package main
|
|||||||
import (
|
import (
|
||||||
"cadoles/foodoles/bdd"
|
"cadoles/foodoles/bdd"
|
||||||
"cadoles/foodoles/foodlist"
|
"cadoles/foodoles/foodlist"
|
||||||
votefood "cadoles/foodoles/vote"
|
"cadoles/foodoles/vote"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Today is today
|
|
||||||
var Today = time.Now().Format("02/01/2006")
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
http.HandleFunc("/", base)
|
http.HandleFunc("/", Base)
|
||||||
http.HandleFunc("/results", resultsPage)
|
http.HandleFunc("/results", ResultsPage)
|
||||||
bdd.InitBDD()
|
db, err := bdd.OpenDB()
|
||||||
log.Print("ready: listening on localhost:8080\n")
|
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 {
|
if err := http.ListenAndServe(":8080", nil); err != nil {
|
||||||
panic(err)
|
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 {
|
if r.Method == http.MethodPost {
|
||||||
votePage(w, r)
|
VotePage(w, r)
|
||||||
} else if r.Method == http.MethodGet {
|
} else if r.Method == http.MethodGet {
|
||||||
homePage(w, r)
|
HomePage(w, r)
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
w.Write([]byte("400 - Unsupported Request Method!"))
|
w.Write([]byte("400 - Unsupported Request Method!"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func homePage(w http.ResponseWriter, r *http.Request) {
|
// HomePage is the homepage of the app
|
||||||
foods := foodlist.GetFoodOfTheDay(Today)
|
func HomePage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
foods := foodlist.GetFoodOfTheDay()
|
||||||
paths := []string{
|
paths := []string{
|
||||||
"./templates/index.tmpl",
|
"./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{
|
paths := []string{
|
||||||
"./templates/results.tmpl",
|
"./templates/results.tmpl",
|
||||||
}
|
}
|
||||||
t := template.Must(template.New("results.tmpl").ParseFiles(paths...))
|
t := template.Must(template.New("results.tmpl").ParseFiles(paths...))
|
||||||
err := t.Execute(w, "")
|
err = t.Execute(w, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("\nExecute error: %v", err)
|
log.Printf("\nExecute error: %v", err)
|
||||||
return
|
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()
|
r.ParseForm()
|
||||||
option := r.Form.Get("option")
|
option := r.Form.Get("option")
|
||||||
|
|
||||||
log.Print("vote for : ", option)
|
log.Print("vote for : ", option)
|
||||||
votefood.ForFood(Today, option)
|
vote.ForFood(option)
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
{{ range .Foods }}
|
||||||
|
<div>
|
||||||
|
<div class="ui massive label"> {{ .Icon }}</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
<h2 class="ui header">TV Show - Poll Results</h2><br/>
|
<h2 class="ui header">TV Show - Poll Results</h2><br/>
|
||||||
<div class="ui one column grid link cards">
|
<div class="ui one column grid link cards">
|
||||||
@ -17,6 +22,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="color:#fff" id="key">{{.Key}}</div>
|
<div style="color:#fff" id="key">{{.Key}}</div>
|
||||||
<div style="color:#fff" id="cluster">{{.Cluster}}</div>
|
<div style="color:#fff" id="cluster">{{.Cluster}}</div>
|
||||||
</body>
|
</body>
|
||||||
|
72
vote/vote.go
72
vote/vote.go
@ -1,5 +1,12 @@
|
|||||||
package vote
|
package vote
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cadoles/foodoles/bdd"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// VotesOfTheDay est le résultat des votes du jour
|
// VotesOfTheDay est le résultat des votes du jour
|
||||||
type VotesOfTheDay struct {
|
type VotesOfTheDay struct {
|
||||||
Date string
|
Date string
|
||||||
@ -13,6 +20,69 @@ type Vote struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ForFood vote pour un choix du jour
|
// 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
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user