core/pkg/excel_export.go

100 lines
2.8 KiB
Go
Raw Normal View History

2024-02-19 17:48:04 +00:00
package pkg
import (
"github.com/tealeg/xlsx"
"io"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
"sort"
)
func WriteDataToExcel(buffer io.Writer, questions []model.Question, answers []model.Answer) error {
file := xlsx.NewFile()
sheet, err := file.AddSheet("Results")
if err != nil {
return err
}
headers := []string{"Данные респондента"}
mapQueRes := make(map[uint64]string)
for _, q := range questions {
if !q.Deleted {
if q.Type == model.TypeResult {
mapQueRes[q.Id] = q.Title + "\n" + q.Description
} else {
headers = append(headers, q.Title)
}
}
}
headers = append(headers, "Результат")
// добавляем заголовки в первую строку
row := sheet.AddRow()
for _, header := range headers {
cell := row.AddCell()
cell.Value = header
}
// мапа для хранения обычных ответов респондентов
standart := make(map[string][]model.Answer)
// мапа для хранения данных респондентов
results := make(map[string]model.Answer)
// заполняем мапу ответами и данными респондентов
for _, answer := range answers {
if answer.Result {
// если это результат то данные респондента берутся из контента ответа по сессии
results[answer.Session] = answer
} else {
// если это обычный ответ то добавляем его в соответствующий список ответов респондента
standart[answer.Session] = append(standart[answer.Session], answer)
}
}
// записываем данные в файл
for session, _ := range results {
response := standart[session]
row := sheet.AddRow()
row.AddCell().Value = results[session].Content // данные респондента
for _, q := range questions {
if !q.Deleted && q.Type != model.TypeResult {
sort.Slice(response, func(i, j int) bool {
return response[i].QuestionId < response[j].QuestionId
})
index := binarySearch(response, q.Id)
if index != -1 {
row.AddCell().Value = response[index].Content
} else {
row.AddCell().Value = "-"
}
}
}
row.AddCell().Value = mapQueRes[results[session].QuestionId]
}
// cохраняем данные в буфер
err = file.Write(buffer)
if err != nil {
return err
}
return nil
}
func binarySearch(answers []model.Answer, questionID uint64) int {
left := 0
right := len(answers) - 1
for left <= right {
mid := left + (right-left)/2
if answers[mid].QuestionId == questionID {
return mid
} else if answers[mid].QuestionId < questionID {
left = mid + 1
} else {
right = mid - 1
}
}
return -1
}