This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues or pull requests.
l9_stud_bot/modules/tg/week_shedule.go

302 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tg
import (
"fmt"
"log"
"math"
"os"
"sort"
"strings"
"time"
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database"
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/ssau_parser"
wkhtml "github.com/SebastiaanKlippert/go-wkhtmltopdf"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/icza/gox/timex"
)
func (bot *Bot) GetWeekLessons(shedules []database.ShedulesInUser, week int, isRetry ...int) ([]database.Lesson, error) {
condition := CreateCondition(shedules)
var lessons []database.Lesson
err := bot.DB.
Where("WEEK(`begin`, 1) = ?", week+bot.Week).
And(condition).
OrderBy("begin").
Find(&lessons)
if err != nil {
return nil, err
}
if len(isRetry) == 0 || isRetry[0] < 2 {
isRetry, err = bot.LoadShedule(shedules, week+bot.Week, isRetry...)
if err != nil {
return nil, err
}
dw := isRetry[0]
return bot.GetWeekLessons(shedules, week, dw+1)
} else if len(isRetry) != 0 && len(lessons) != 0 {
return lessons, nil
} else {
return nil, nil
}
}
var days = [6]string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}
func (bot *Bot) GetPersonalWeekSummary(dt int, msg ...tgbotapi.Message) {
var shedules []database.ShedulesInUser
bot.DB.ID(bot.TG_user.L9Id).Find(&shedules)
if len(shedules) == 0 {
bot.Etc()
return
} else {
err := bot.GetWeekSummary(shedules, dt, true, msg...)
if err != nil {
log.Fatal(err)
}
}
}
func (bot *Bot) GetWeekSummary(shedules []database.ShedulesInUser, dw int, isPersonal bool, editMsg ...tgbotapi.Message) error {
_, week := time.Now().ISOWeek()
week += dw
lessons, err := bot.GetWeekLessons(shedules, week-bot.Week)
if err != nil {
log.Fatal(err)
}
var dates []time.Time
begins := make(map[time.Time]bool)
ends := make(map[time.Time]bool)
height := 0
minDay := lessons[0].NumInShedule
for _, lesson := range lessons {
t := lesson.Begin
begin := time.Date(2000, 1, 1, t.Hour(), t.Minute(), 0, 0, t.Location())
begins[begin] = true
e := lesson.End
end := time.Date(2000, 1, 1, e.Hour(), e.Minute(), 0, 0, e.Location())
ends[end] = true
if lesson.NumInShedule > height {
height = lesson.NumInShedule
} else if lesson.NumInShedule < minDay {
minDay = lesson.NumInShedule
}
}
var times []ssau_parser.Pair
var beginsSlice []time.Time
var endsSlice []time.Time
for b := range begins {
beginsSlice = append(beginsSlice, b)
}
for e := range ends {
endsSlice = append(endsSlice, e)
}
sort.Slice(beginsSlice, func(i, j int) bool {
return beginsSlice[i].Before(beginsSlice[j])
})
sort.Slice(endsSlice, func(i, j int) bool {
return endsSlice[i].Before(endsSlice[j])
})
for i, b := range beginsSlice {
sh := ssau_parser.Pair{
Begin: b,
End: endsSlice[i],
}
times = append(times, sh)
}
weekBegin := timex.WeekStart(lessons[0].Begin.Year(), week)
for i := range days {
dates = append(dates, weekBegin.Add(time.Hour*time.Duration(24*i)))
}
shedule := make([][6][]database.Lesson, height-minDay+1)
pairs := GroupPairs(lessons)
for _, p := range pairs {
day := int(math.Floor(p[0].Begin.Sub(weekBegin).Hours() / 24))
shedule[p[0].NumInShedule-minDay][day] = p
}
html := bot.CreateHTMLShedule(week, shedule, dates, times)
if _, err := os.Stat("shedules"); os.IsNotExist(err) {
err = os.Mkdir("shedules", os.ModePerm)
if err != nil {
return err
}
}
fname := fmt.Sprintf("./shedules/%d_%d.html", bot.TG_user.L9Id, week-bot.Week)
f, _ := os.Create(fname)
defer f.Close()
f.WriteString(html)
wkhtml.SetPath(bot.WkPath)
pdfg, err := wkhtml.NewPDFGenerator()
if err != nil {
return err
}
pdfg.Dpi.Set(300)
pdfg.MarginBottom.Set(0)
pdfg.MarginTop.Set(0)
pdfg.MarginLeft.Set(0)
pdfg.MarginRight.Set(0)
pdfg.Orientation.Set(wkhtml.OrientationLandscape)
pdfg.PageSize.Set(wkhtml.PageSizeA4)
pdfg.AddPage(wkhtml.NewPageReader(strings.NewReader(html)))
err = pdfg.Create()
if err != nil {
return err
}
fname = fmt.Sprintf("./shedules/%d_%d.pdf", bot.TG_user.L9Id, week-bot.Week)
err = pdfg.WriteFile(fname)
if err != nil {
return err
}
photoBytes, err := os.ReadFile(fname)
if err != nil {
return err
}
fname = fmt.Sprintf("Расписание %d неделя.pdf", week-bot.Week)
photoFileBytes := tgbotapi.FileBytes{
Name: fname,
Bytes: photoBytes,
}
msg := tgbotapi.NewDocument(bot.TG_user.TgId, photoFileBytes)
_, err = bot.TG.Send(msg)
if err != nil {
return err
}
var shId int64
if isPersonal {
shId = 0
} else {
shId = shedules[0].SheduleId
}
markup := SummaryKeyboard(
"week",
shId,
shedules[0].IsTeacher,
dw,
)
_, nowWeek := time.Now().ISOWeek()
var str string
if week == nowWeek {
str = fmt.Sprintf("Расписание на текущую (%d) неделю сообщением ниже 👇", week-bot.Week)
} else if week-nowWeek == 1 {
str = fmt.Sprintf("Расписание на следующую (%d) неделю сообщением ниже 👇", week-bot.Week)
} else {
str = fmt.Sprintf("Расписание на %d неделю сообщением ниже 👇", week-bot.Week)
}
bot.EditOrSend(str, markup, editMsg...)
return nil
}
const head = `<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Тестовая страница с расписанием</title>
<meta name='viewport' content='width=device-width,initial-scale=1'/>
<meta name="mobile-web-app-capable" content="yes">
</head>
<style>
.note div,.rasp div{background-color:#f0f8ff;padding:10px;text-align:center;border-radius:10px}.note,th.head,th.time{font-family:monospace}.subj div #text,.subj p{display:none}html{font-size:1.5rem}body{background:#dc14bd}table{table-layout:fixed;width:100%;border-spacing:5px 5px}.note div{margin:10px 0}.head p,.subj p,hr{margin:0}.rasp div{transition:.3s}th.head{background-color:#0ff;border-radius:10px;padding:5px;font-size:1.05rem}th.subj,th.time{background-color:#f0f8ff;padding:10px;border-radius:10px}th.time{font-size:1.1rem}.subj h2,.subj p{font-size:.85rem}th.subj:not(.lab,.lect,.pract,.other){background-color:#a9a9a9}.subj div{border-radius:10px;padding:5px}.subj p{font-family:monospace;color:#f0f8ff}.subj h2,.subj h3,.subj h5{font-family:monospace;text-align:left;margin:5px}.subj h3{font-size:.65rem}.subj h5{font-size:.7rem;font-weight:400}.lect div{background-color:#7fff00}.pract div{background-color:#dc143c}.lab div{background-color:#8a2be2}.other div{background-color:#ff8c00}
</style>
<body>
`
const lessonHead = `<th class="subj %s" valign="top">
<div><p></p></div>
<h2>%s</h2><hr>`
var weekdays = [6]string{
"пн",
"вт",
"ср",
"чт",
"пт",
"сб",
}
func (bot *Bot) CreateHTMLShedule(week int, shedule [][6][]database.Lesson, dates []time.Time, times []ssau_parser.Pair) string {
html := head
html += fmt.Sprintf("<div class=\"note\"><div id=\"week\">%d неделя</div></div>\n", week-bot.Week)
html += "<table class=\"rasp\">\n<tr><th class=\"head\" style=\"width: 4rem\">Время</th>\n"
for i, d := range dates {
day := d.Format("02")
html += fmt.Sprintf("<th class=\"head\">%s<p>%s</p></th>", weekdays[i], day)
}
html += "</tr>\n"
for t, tline := range shedule {
begin := times[t].Begin.Format("15:04")
end := times[t].End.Format("15:04")
html += fmt.Sprintf("<tr>\n<th class=\"time\">%s<hr>%s</th>", begin, end)
for i, l := range tline {
if len(l) > 0 {
html += fmt.Sprintf(lessonHead, l[0].Type, l[0].Name)
if l[0].TeacherId != 0 {
var t database.Teacher
bot.DB.ID(l[0].TeacherId).Get(&t)
name := GenerateName(t)
html += fmt.Sprintf("<h5 id=\"prep\">%s</h5>\n", name)
}
if l[0].Place != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[0].Place)
}
if l[0].SubGroup != 0 {
html += fmt.Sprintf("<h3>%d</h3>\n", l[0].SubGroup)
}
if l[0].Comment != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[0].Comment)
}
if len(l) == 2 {
html += "<hr>\n"
if l[0].Name != l[1].Name {
html += fmt.Sprintf("<div><p></p></div>\n<h2>%s</h2><hr>", l[1].Name)
}
if l[1].TeacherId != 0 {
var t database.Teacher
bot.DB.ID(l[1].TeacherId).Get(&t)
name := GenerateName(t)
html += fmt.Sprintf("<h5 id=\"prep\">%s</h5>\n", name)
}
if l[1].Place != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[1].Place)
}
if l[1].SubGroup != 0 {
html += fmt.Sprintf("<h3>%d</h3>\n", l[1].SubGroup)
}
if l[1].Comment != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[1].Comment)
}
}
html += "</th>\n"
} else {
html += "<th class=\"subj\"></th>\n"
}
if i%7 == 6 {
html += "</tr>\n"
}
}
}
html += "</table></body></html>"
return html
}