2022-02-28 18:00:30 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-03-03 13:23:31 +00:00
|
|
|
"fmt"
|
2022-02-28 18:00:30 +00:00
|
|
|
"log"
|
|
|
|
"net/http"
|
2023-03-03 13:23:31 +00:00
|
|
|
"strings"
|
2022-02-28 18:00:30 +00:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
"github.com/gin-gonic/gin"
|
2022-02-28 18:00:30 +00:00
|
|
|
"nhooyr.io/websocket"
|
|
|
|
"nhooyr.io/websocket/wsjson"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2022-03-01 15:38:52 +00:00
|
|
|
OffsetQuestionTimer uint = 700
|
|
|
|
WSClients = map[int64][]WSClient{}
|
|
|
|
WSClientsMutex = sync.RWMutex{}
|
|
|
|
WSAdmin = []WSClient{}
|
|
|
|
WSAdminMutex = sync.RWMutex{}
|
2022-02-28 18:00:30 +00:00
|
|
|
)
|
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
func declareAPIAuthDirectRoutes(router *gin.RouterGroup) {
|
|
|
|
router.GET("/ws", SurveyWS)
|
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
func declareAPIAdminDirectRoutes(router *gin.RouterGroup) {
|
|
|
|
router.GET("/ws-admin", SurveyWSAdmin)
|
|
|
|
|
|
|
|
router.GET("/ws/stats", func(c *gin.Context) {
|
|
|
|
s := c.MustGet("survey").(*Survey)
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, WSSurveyStats(s.Id))
|
|
|
|
})
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func WSSurveyStats(sid int64) map[string]interface{} {
|
2022-09-06 17:26:05 +00:00
|
|
|
var users []map[string]interface{}
|
2022-02-28 18:00:30 +00:00
|
|
|
var nb int
|
|
|
|
|
|
|
|
WSClientsMutex.RLock()
|
|
|
|
defer WSClientsMutex.RUnlock()
|
|
|
|
if w, ok := WSClients[sid]; ok {
|
|
|
|
nb = len(w)
|
|
|
|
for _, ws := range w {
|
2022-09-06 17:26:05 +00:00
|
|
|
users = append(users, map[string]interface{}{
|
|
|
|
"id": ws.u.Id,
|
|
|
|
"login": ws.u.Login,
|
|
|
|
})
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return map[string]interface{}{
|
|
|
|
"nb_clients": nb,
|
|
|
|
"users": users,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type WSClient struct {
|
|
|
|
ws *websocket.Conn
|
|
|
|
c chan WSMessage
|
|
|
|
u *User
|
|
|
|
sid int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func SurveyWS_run(ws *websocket.Conn, c chan WSMessage, sid int64, u *User) {
|
|
|
|
for {
|
|
|
|
msg, ok := <-c
|
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := wsjson.Write(ctx, ws, msg)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Error on WebSocket:", err)
|
|
|
|
ws.Close(websocket.StatusInternalError, "error on write")
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ws.Close(websocket.StatusNormalClosure, "end")
|
|
|
|
|
|
|
|
WSClientsMutex.Lock()
|
|
|
|
defer WSClientsMutex.Unlock()
|
|
|
|
|
|
|
|
for i, clt := range WSClients[sid] {
|
|
|
|
if clt.ws == ws {
|
|
|
|
WSClients[sid][i] = WSClients[sid][len(WSClients[sid])-1]
|
|
|
|
WSClients[sid] = WSClients[sid][:len(WSClients[sid])-1]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Println(u.Login, "disconnected")
|
|
|
|
}
|
|
|
|
|
|
|
|
func msgCurrentState(survey *Survey) (msg WSMessage) {
|
|
|
|
if *survey.Direct == 0 {
|
|
|
|
msg = WSMessage{
|
|
|
|
Action: "pause",
|
|
|
|
}
|
|
|
|
} else {
|
2022-09-01 20:09:14 +00:00
|
|
|
var correction map[string]int
|
|
|
|
if survey.Corrected {
|
|
|
|
correction = getCorrectionString(*survey.Direct)
|
|
|
|
}
|
|
|
|
|
2022-02-28 18:00:30 +00:00
|
|
|
msg = WSMessage{
|
2022-09-01 20:09:14 +00:00
|
|
|
Action: "new_question",
|
|
|
|
QuestionId: survey.Direct,
|
|
|
|
Corrected: survey.Corrected,
|
|
|
|
Corrections: correction,
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
func SurveyWS(c *gin.Context) {
|
|
|
|
u := c.MustGet("LoggedUser").(*User)
|
|
|
|
survey := c.MustGet("survey").(*Survey)
|
|
|
|
|
|
|
|
if survey.Direct == nil {
|
|
|
|
c.AbortWithStatusJSON(http.StatusPaymentRequired, gin.H{"errmsg": "Not a live survey"})
|
2022-02-28 18:00:30 +00:00
|
|
|
return
|
2022-07-09 17:42:00 +00:00
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
ws, err := websocket.Accept(c.Writer, c.Request, nil)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("error get connection", err)
|
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
log.Println(u.Login, "is now connected to WS", survey.Id)
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
ch := make(chan WSMessage, 1)
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
WSClientsMutex.Lock()
|
|
|
|
defer WSClientsMutex.Unlock()
|
|
|
|
WSClients[survey.Id] = append(WSClients[survey.Id], WSClient{ws, ch, u, survey.Id})
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
// Send current state
|
|
|
|
ch <- msgCurrentState(survey)
|
|
|
|
|
|
|
|
go SurveyWS_run(ws, ch, survey.Id, u)
|
2022-09-06 17:26:05 +00:00
|
|
|
go func(c chan WSMessage, sid int) {
|
|
|
|
var v WSMessage
|
|
|
|
var err error
|
|
|
|
for {
|
|
|
|
err = wsjson.Read(context.Background(), ws, &v)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Error when receiving message:", err)
|
|
|
|
close(c)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if v.Action == "myscroll" {
|
|
|
|
v.UserId = &u.Id
|
|
|
|
v.SurveyId = &survey.Id
|
|
|
|
WSAdminWriteAll(v)
|
|
|
|
} else {
|
|
|
|
log.Println("Unknown ws response:", v.Action)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}(ch, int(survey.Id))
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func WSWriteAll(message WSMessage) {
|
|
|
|
WSClientsMutex.RLock()
|
|
|
|
defer WSClientsMutex.RUnlock()
|
|
|
|
|
|
|
|
for _, wss := range WSClients {
|
|
|
|
for _, ws := range wss {
|
|
|
|
ws.c <- message
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type WSMessage struct {
|
2022-09-01 20:09:14 +00:00
|
|
|
Action string `json:"action"`
|
|
|
|
SurveyId *int64 `json:"survey,omitempty"`
|
|
|
|
QuestionId *int64 `json:"question,omitempty"`
|
|
|
|
Stats map[string]interface{} `json:"stats,omitempty"`
|
|
|
|
UserId *int64 `json:"user,omitempty"`
|
|
|
|
Response string `json:"value,omitempty"`
|
|
|
|
Corrected bool `json:"corrected,omitempty"`
|
|
|
|
Corrections map[string]int `json:"corrections,omitempty"`
|
|
|
|
Timer uint `json:"timer,omitempty"`
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Survey) WSWriteAll(message WSMessage) {
|
|
|
|
WSClientsMutex.RLock()
|
|
|
|
defer WSClientsMutex.RUnlock()
|
|
|
|
|
|
|
|
if wss, ok := WSClients[s.Id]; ok {
|
|
|
|
for _, ws := range wss {
|
|
|
|
ws.c <- message
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Survey) WSCloseAll(message string) {
|
|
|
|
WSClientsMutex.RLock()
|
|
|
|
defer WSClientsMutex.RUnlock()
|
|
|
|
|
|
|
|
if wss, ok := WSClients[s.Id]; ok {
|
|
|
|
for _, ws := range wss {
|
|
|
|
close(ws.c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Admin //////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
func SurveyWSAdmin_run(ctx context.Context, ws *websocket.Conn, c chan WSMessage, sid int64, u *User) {
|
|
|
|
ct := time.Tick(25000 * time.Millisecond)
|
|
|
|
loopadmin:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ct:
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := wsjson.Write(ctx, ws, WSMessage{
|
|
|
|
Action: "stats",
|
|
|
|
Stats: WSSurveyStats(sid),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Error on WebSocket:", err)
|
|
|
|
ws.Close(websocket.StatusInternalError, "error on write")
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
case msg, ok := <-c:
|
|
|
|
if !ok {
|
|
|
|
break loopadmin
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := wsjson.Write(ctx, ws, msg)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Error on WebSocket:", err)
|
|
|
|
ws.Close(websocket.StatusInternalError, "error on write")
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ws.Close(websocket.StatusNormalClosure, "end")
|
|
|
|
|
|
|
|
WSAdminMutex.Lock()
|
|
|
|
defer WSAdminMutex.Unlock()
|
|
|
|
|
|
|
|
for i, clt := range WSAdmin {
|
|
|
|
if clt.ws == ws {
|
|
|
|
WSAdmin[i] = WSAdmin[len(WSAdmin)-1]
|
|
|
|
WSAdmin = WSAdmin[:len(WSAdmin)-1]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Println(u.Login, "admin disconnected")
|
|
|
|
}
|
|
|
|
|
2022-09-01 20:09:14 +00:00
|
|
|
func getCorrectionString(qid int64) (ret map[string]int) {
|
|
|
|
q, err := getQuestion(int(qid))
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
cts, err := q.GetCorrectionTemplates()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = map[string]int{}
|
|
|
|
for _, ct := range cts {
|
|
|
|
ret[ct.RegExp] = ct.Score
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-03-03 13:23:31 +00:00
|
|
|
func getResponsesStats(qid int64) map[string]interface{} {
|
|
|
|
q, err := getQuestion(int(qid))
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
responses, err := q.GetResponses()
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Unable to retrieve responses:", err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
labels := []string{}
|
|
|
|
values := []uint{}
|
|
|
|
|
|
|
|
if q.Kind == "mcq" || q.Kind == "ucq" {
|
|
|
|
proposals, err := q.GetProposals()
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
proposal_idx := map[string]int{}
|
|
|
|
for _, p := range proposals {
|
|
|
|
proposal_idx[fmt.Sprintf("%d", p.Id)] = len(labels)
|
|
|
|
labels = append(labels, p.Label)
|
|
|
|
values = append(values, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, r := range responses {
|
|
|
|
for _, v := range strings.Split(r.Answer, ",") {
|
|
|
|
values[proposal_idx[v]]++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
stats := map[string]uint{}
|
|
|
|
|
|
|
|
for _, r := range responses {
|
|
|
|
stats[r.Answer]++
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range stats {
|
|
|
|
labels = append(labels, k)
|
|
|
|
values = append(values, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return map[string]interface{}{
|
|
|
|
"labels": labels,
|
|
|
|
"datasets": []map[string][]uint{
|
|
|
|
map[string][]uint{
|
|
|
|
"values": values,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
func SurveyWSAdmin(c *gin.Context) {
|
|
|
|
u := c.MustGet("LoggedUser").(*User)
|
|
|
|
survey := c.MustGet("survey").(*Survey)
|
|
|
|
|
|
|
|
if survey.Direct == nil {
|
|
|
|
c.AbortWithStatusJSON(http.StatusPaymentRequired, gin.H{"errmsg": "Not a live survey"})
|
2022-02-28 18:00:30 +00:00
|
|
|
return
|
2022-07-09 17:42:00 +00:00
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
ws, err := websocket.Accept(c.Writer, c.Request, nil)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("error get connection", err)
|
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
log.Println(u.Login, "is now connected to WS-admin", survey.Id)
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
ch := make(chan WSMessage, 2)
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
WSAdminMutex.Lock()
|
|
|
|
defer WSAdminMutex.Unlock()
|
|
|
|
WSAdmin = append(WSAdmin, WSClient{ws, ch, u, survey.Id})
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
// Send current state
|
|
|
|
ch <- msgCurrentState(survey)
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
go SurveyWSAdmin_run(c.Request.Context(), ws, ch, survey.Id, u)
|
|
|
|
go func(c chan WSMessage, sid int) {
|
|
|
|
var v WSMessage
|
|
|
|
var err error
|
2023-03-03 12:15:36 +00:00
|
|
|
var surveyTimer *time.Timer
|
2022-07-09 17:42:00 +00:00
|
|
|
for {
|
2022-09-02 09:54:58 +00:00
|
|
|
// Reset variable state
|
|
|
|
v.Corrected = false
|
|
|
|
v.Corrections = nil
|
|
|
|
v.Timer = 0
|
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
err = wsjson.Read(context.Background(), ws, &v)
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Error when receiving message:", err)
|
|
|
|
close(c)
|
|
|
|
break
|
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
if v.Action == "new_question" && v.QuestionId != nil {
|
|
|
|
if survey, err := getSurvey(sid); err != nil {
|
|
|
|
log.Println("Unable to retrieve survey:", err)
|
|
|
|
} else {
|
2023-03-03 12:15:36 +00:00
|
|
|
// Skip any existing scheduled timer
|
|
|
|
if surveyTimer != nil {
|
|
|
|
if !surveyTimer.Stop() {
|
|
|
|
<-surveyTimer.C
|
|
|
|
}
|
|
|
|
surveyTimer = nil
|
|
|
|
}
|
|
|
|
|
2022-09-02 12:07:39 +00:00
|
|
|
survey.Direct = v.QuestionId
|
2022-07-09 17:42:00 +00:00
|
|
|
if v.Timer > 0 {
|
2022-09-02 12:07:39 +00:00
|
|
|
survey.Corrected = false
|
|
|
|
survey.Update()
|
|
|
|
|
2023-03-03 12:15:36 +00:00
|
|
|
// Save corrected state for the callback
|
|
|
|
corrected := v.Corrected
|
2023-03-03 13:23:31 +00:00
|
|
|
with_stats := v.Stats != nil
|
2022-09-01 17:14:57 +00:00
|
|
|
|
2023-03-03 12:15:36 +00:00
|
|
|
surveyTimer = time.AfterFunc(time.Duration(OffsetQuestionTimer+v.Timer)*time.Millisecond, func() {
|
|
|
|
surveyTimer = nil
|
2022-09-01 17:14:57 +00:00
|
|
|
if corrected {
|
|
|
|
survey.Corrected = v.Corrected
|
|
|
|
survey.Update()
|
|
|
|
|
2023-03-03 13:23:31 +00:00
|
|
|
var stats map[string]interface{}
|
|
|
|
if with_stats {
|
|
|
|
stats = getResponsesStats(*v.QuestionId)
|
|
|
|
}
|
|
|
|
|
|
|
|
survey.WSWriteAll(WSMessage{Action: "new_question", QuestionId: v.QuestionId, Corrected: true, Stats: stats, Corrections: getCorrectionString(*v.QuestionId)})
|
2022-09-01 17:14:57 +00:00
|
|
|
} else {
|
2022-09-02 12:07:39 +00:00
|
|
|
var z int64 = 0
|
|
|
|
survey.Direct = &z
|
|
|
|
survey.Update()
|
|
|
|
|
2022-09-01 17:14:57 +00:00
|
|
|
survey.WSWriteAll(WSMessage{Action: "pause"})
|
|
|
|
WSAdminWriteAll(WSMessage{Action: "pause", SurveyId: &survey.Id})
|
|
|
|
}
|
2023-03-03 12:15:36 +00:00
|
|
|
})
|
2022-09-01 17:14:57 +00:00
|
|
|
v.Corrected = false
|
2023-03-03 13:23:31 +00:00
|
|
|
v.Stats = nil
|
2022-07-09 17:42:00 +00:00
|
|
|
} else {
|
2022-09-01 17:14:57 +00:00
|
|
|
survey.Corrected = v.Corrected
|
2022-09-01 20:09:14 +00:00
|
|
|
if v.Corrected {
|
|
|
|
v.Corrections = getCorrectionString(*v.QuestionId)
|
2023-03-03 13:23:31 +00:00
|
|
|
if v.Stats != nil {
|
|
|
|
v.Stats = getResponsesStats(*v.QuestionId)
|
|
|
|
} else {
|
|
|
|
v.Stats = nil
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
v.Stats = nil
|
2022-09-01 20:09:14 +00:00
|
|
|
}
|
2022-07-09 17:42:00 +00:00
|
|
|
}
|
|
|
|
_, err = survey.Update()
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Unable to update survey:", err)
|
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
survey.WSWriteAll(v)
|
|
|
|
v.SurveyId = &survey.Id
|
|
|
|
WSAdminWriteAll(v)
|
|
|
|
}
|
|
|
|
} else if v.Action == "pause" {
|
|
|
|
if survey, err := getSurvey(sid); err != nil {
|
|
|
|
log.Println("Unable to retrieve survey:", err)
|
|
|
|
} else {
|
|
|
|
var u int64 = 0
|
|
|
|
survey.Direct = &u
|
|
|
|
_, err = survey.Update()
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Unable to update survey:", err)
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
|
2022-07-09 17:42:00 +00:00
|
|
|
survey.WSWriteAll(v)
|
|
|
|
v.SurveyId = &survey.Id
|
|
|
|
WSAdminWriteAll(v)
|
|
|
|
}
|
|
|
|
} else if v.Action == "end" {
|
|
|
|
if survey, err := getSurvey(sid); err != nil {
|
|
|
|
log.Println("Unable to retrieve survey:", err)
|
|
|
|
} else {
|
2022-09-02 10:00:13 +00:00
|
|
|
survey.EndAvailability = time.Now()
|
2022-07-09 17:42:00 +00:00
|
|
|
survey.Direct = nil
|
|
|
|
_, err = survey.Update()
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Unable to update survey:", err)
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
2022-07-09 17:42:00 +00:00
|
|
|
|
|
|
|
survey.WSCloseAll("Fin du live")
|
|
|
|
v.SurveyId = &survey.Id
|
|
|
|
WSAdminWriteAll(v)
|
|
|
|
}
|
|
|
|
} else if v.Action == "get_stats" {
|
|
|
|
err = wsjson.Write(context.Background(), ws, WSMessage{Action: "stats", Stats: WSSurveyStats(int64(sid))})
|
|
|
|
} else if v.Action == "get_responses" {
|
|
|
|
if survey, err := getSurvey(sid); err != nil {
|
|
|
|
log.Println("Unable to retrieve survey:", err)
|
|
|
|
} else if questions, err := survey.GetQuestions(); err != nil {
|
|
|
|
log.Println("Unable to retrieve questions:", err)
|
|
|
|
} else {
|
|
|
|
for _, q := range questions {
|
|
|
|
if responses, err := q.GetResponses(); err != nil {
|
|
|
|
log.Println("Unable to retrieve questions:", err)
|
|
|
|
} else {
|
|
|
|
for _, r := range responses {
|
|
|
|
wsjson.Write(context.Background(), ws, WSMessage{Action: "new_response", UserId: &r.IdUser, QuestionId: &q.Id, Response: r.Answer})
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-09 17:42:00 +00:00
|
|
|
}
|
|
|
|
} else if v.Action == "get_asks" {
|
|
|
|
if survey, err := getSurvey(sid); err != nil {
|
|
|
|
log.Println("Unable to retrieve survey:", err)
|
|
|
|
} else if asks, err := survey.GetAsks(v.Response == ""); err != nil {
|
|
|
|
log.Println("Unable to retrieve asks:", err)
|
|
|
|
} else {
|
|
|
|
for _, a := range asks {
|
|
|
|
wsjson.Write(context.Background(), ws, WSMessage{Action: "new_ask", UserId: &a.IdUser, QuestionId: &a.Id, Response: a.Content})
|
2022-03-01 14:26:30 +00:00
|
|
|
}
|
2022-07-09 17:42:00 +00:00
|
|
|
}
|
|
|
|
} else if v.Action == "mark_answered" && v.QuestionId != nil {
|
|
|
|
if asks, err := GetAsk(int(*v.QuestionId)); err != nil {
|
|
|
|
log.Println("Unable to retrieve ask:", err)
|
|
|
|
} else {
|
|
|
|
asks.Answered = true
|
|
|
|
err = asks.Update()
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Unable to update:", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if v.Action == "mark_answered" && v.Response == "all" {
|
|
|
|
if survey, err := getSurvey(sid); err != nil {
|
|
|
|
log.Println("Unable to retrieve survey:", err)
|
|
|
|
} else if asks, err := survey.GetAsks(v.Response == ""); err != nil {
|
|
|
|
log.Println("Unable to retrieve asks:", err)
|
|
|
|
} else {
|
|
|
|
for _, ask := range asks {
|
|
|
|
ask.Answered = true
|
|
|
|
err = ask.Update()
|
2022-03-01 14:26:30 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Println("Unable to update:", err)
|
|
|
|
}
|
|
|
|
}
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
2022-09-06 17:26:05 +00:00
|
|
|
} else if v.Action == "where_are_you" {
|
|
|
|
survey.WSWriteAll(v)
|
2022-07-09 17:42:00 +00:00
|
|
|
} else {
|
|
|
|
log.Println("Unknown admin action:", v.Action)
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
2022-07-09 17:42:00 +00:00
|
|
|
}
|
|
|
|
}(ch, int(survey.Id))
|
2022-02-28 18:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func WSAdminWriteAll(message WSMessage) {
|
|
|
|
WSAdminMutex.RLock()
|
|
|
|
defer WSAdminMutex.RUnlock()
|
|
|
|
|
|
|
|
for _, ws := range WSAdmin {
|
|
|
|
ws.c <- message
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Survey) WSAdminWriteAll(message WSMessage) {
|
|
|
|
WSAdminMutex.RLock()
|
|
|
|
defer WSAdminMutex.RUnlock()
|
|
|
|
|
|
|
|
for _, ws := range WSAdmin {
|
|
|
|
if ws.sid == s.Id {
|
|
|
|
ws.c <- message
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|