Добавлено: загрузка и парсинг расписания в одной функции

This commit is contained in:
far-galaxy 2023-08-02 08:42:07 +04:00
parent aea8cb77b2
commit 16f5abc820
8 changed files with 157 additions and 76 deletions

View File

@ -21,17 +21,16 @@ type ShedulesInUser struct {
}
type Group struct {
GroupId int64 `xorm:"pk"`
GroupName string
SpecName string
GroupId int64 `xorm:"pk"`
GroupName string // Полный номер группы
SpecName string // Шифр и название специальности
}
type Teacher struct {
TeacherId int64 `xorm:"pk"`
LastName string
FirstName string
MidName string
SpecName string
TeacherId int64 `xorm:"pk"`
FirstName string // Фамилия
LastName string // Имя, отчество и прочие окончания
SpecName string // Место работы
}
type Lesson struct {

View File

@ -8,8 +8,22 @@ import (
"xorm.io/xorm"
)
func UpdateSchedule(db *xorm.Engine, sh WeekShedule) error {
err := checkGroupOrTeacher(db, sh)
if err != nil {
return err
}
first_new := sh.Uncovered[0]
_, week := first_new.Begin.ISOWeek()
var old []database.Lesson
db.Where("WEEK(`Begin`) = ?", week).Asc("Begin").Find(&old)
Compare(sh.Uncovered, old)
return nil
}
func UploadShedule(db *xorm.Engine, sh WeekShedule) error {
err := addGroupOrTeacher(db, sh)
err := checkGroupOrTeacher(db, sh)
if err != nil {
return err
}
@ -42,7 +56,7 @@ func UploadShedule(db *xorm.Engine, sh WeekShedule) error {
gr.IsGroup = false
gr.SheduleId = subLesson.TeacherId[0]
GetSheduleInfo(doc.Doc, &gr)
addGroupOrTeacher(db, gr)
checkGroupOrTeacher(db, gr)
}
for _, groupId := range subLesson.GroupId {
@ -63,7 +77,7 @@ func UploadShedule(db *xorm.Engine, sh WeekShedule) error {
gr.IsGroup = true
gr.SheduleId = groupId
GetSheduleInfo(doc.Doc, &gr)
addGroupOrTeacher(db, gr)
checkGroupOrTeacher(db, gr)
}
var existsLessons []database.Lesson
@ -109,7 +123,9 @@ func isTeacherExists(db *xorm.Engine, teacherId int64) (bool, error) {
return len(exists) == 1, nil
}
func addGroupOrTeacher(db *xorm.Engine, sh WeekShedule) error {
// Проверка наличия группы или преподавателя в БД и добавление при необходимости
// TODO: Добавить проверку изменений в полях данных
func checkGroupOrTeacher(db *xorm.Engine, sh WeekShedule) error {
if sh.IsGroup {
exists, err := isGroupExists(db, sh.SheduleId)
if err != nil {
@ -135,8 +151,8 @@ func addGroupOrTeacher(db *xorm.Engine, sh WeekShedule) error {
log.Println(name)
teacher := database.Teacher{
TeacherId: sh.SheduleId,
LastName: name[0],
FirstName: strings.Join(name[1:], " "),
FirstName: name[0],
LastName: strings.Join(name[1:], " "),
SpecName: sh.SpecName,
}
db.InsertOne(teacher)

View File

@ -11,7 +11,7 @@ import (
)
// Раскрытие недельного расписания в список занятий для базы данных и сравнения
func UncoverShedule(sh WeekShedule) []database.Lesson {
func (sh *WeekShedule) UncoverShedule() {
var lessons []database.Lesson
for y, line := range sh.Lessons {
for x, pair := range line {
@ -41,7 +41,7 @@ func UncoverShedule(sh WeekShedule) []database.Lesson {
}
}
}
return lessons
sh.Uncovered = lessons
}
// Сравнивание списков занятий на предмет добавления и удаления

View File

@ -1,14 +1,17 @@
package ssau_parser
import (
"errors"
"strconv"
"strings"
"time"
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database"
"github.com/PuerkitoBio/goquery"
"golang.org/x/exp/slices"
)
// Пара, состоящая из занятий
type Pair struct {
Begin time.Time
End time.Time
@ -16,6 +19,7 @@ type Pair struct {
Lessons []Lesson
}
// Отдельные занятия внутри пары
type Lesson struct {
Type string
Name string
@ -27,14 +31,16 @@ type Lesson struct {
Hash []byte
}
// Недельное расписание
type WeekShedule struct {
IsGroup bool
SheduleId int64
FullName string
SpecName string
Week int
WeekBegin int
Lessons [][]Pair
Week int // Номер недели в семестре
WeekBegin int // Номер недели в году начала семестра
Lessons [][]Pair // Таблица пар в форме недельного расписания
Uncovered []database.Lesson // Раскрытый список всех занятий для дальнейшей обработки в БД
}
// Получить полный номер группы и название специальности (ФИО и место работы для преподавателей)
@ -58,10 +64,9 @@ func GetSheduleInfo(doc *goquery.Document, sh *WeekShedule) {
var hourMap = map[int]int{8: 0, 9: 1, 11: 2, 13: 3, 15: 4, 17: 5, 18: 6, 20: 7}
// Парсинг страницы с расписанием
func Parse(p Page) (*WeekShedule, error) {
var sh WeekShedule
func (sh *WeekShedule) Parse(p Page, uncover bool) error {
doc := p.Doc
GetSheduleInfo(doc, &sh)
GetSheduleInfo(doc, sh)
var raw_dates []string
doc.Find(".schedule__head-date").Each(func(i int, s *goquery.Selection) {
@ -88,7 +93,7 @@ func Parse(p Page) (*WeekShedule, error) {
if t == 0 {
begin, err := time.Parse(" 15:04 -07", raw_times[t])
if err != nil {
return nil, err
return err
}
firstNum = hourMap[begin.Hour()]
}
@ -98,12 +103,12 @@ func Parse(p Page) (*WeekShedule, error) {
begin_raw := date + raw_times[t]
begin, err := time.Parse(" 02.01.2006 15:04 -07", begin_raw)
if err != nil {
return nil, err
return err
}
end_raw := date + raw_times[t+1]
end, err := time.Parse(" 02.01.2006 15:04 -07", end_raw)
if err != nil {
return nil, err
return err
}
idx := (len(raw_dates))*t/2 + d
lesson := Pair{
@ -120,7 +125,11 @@ func Parse(p Page) (*WeekShedule, error) {
sh.SheduleId = p.ID
sh.Week = p.Week
sh.Lessons = shedule
return &sh, nil
if uncover {
sh.UncoverShedule()
}
return nil
}
var types = [4]string{"lect", "lab", "pract", "other"}
@ -212,3 +221,37 @@ func ParseLesson(s *goquery.Selection, isGroup bool, sheduleId int64) []Lesson {
return lessons
}
// Загрузка, парсинг и раскрытие расписания в одной функции
// Обязательно наличие IsGroup, SheduleId, Week в объекте
func (sh *WeekShedule) DownloadById(uncover bool) error {
if sh.SheduleId == 0 {
return errors.New("schedule id not included")
}
if sh.Week == 0 {
return errors.New("week not included")
}
page, err := DownloadSheduleById(sh.SheduleId, sh.IsGroup, sh.Week)
if err != nil {
return err
}
err = sh.Parse(page, uncover)
if err != nil {
return err
}
return nil
}
// Загрузка, парсинг и раскрытие расписания в одной функции по URI и номеру недели
func (sh *WeekShedule) Download(uri string, week int, uncover bool) error {
page, err := DownloadShedule(uri, week)
if err != nil {
return err
}
err = sh.Parse(page, uncover)
if err != nil {
return err
}
return nil
}

View File

@ -3,6 +3,8 @@ package ssau_parser
import (
"log"
"testing"
"git.l9labs.ru/anufriev.g.a/l9_stud_bot/modules/database"
)
var queries = []string{
@ -21,6 +23,13 @@ var urls = []string{
"http://127.0.0.1:5000",
}
// Вывод некритических ошибок тестирования в консоль
func handleError(err error) {
if err != nil {
log.Println(err)
}
}
// TODO: выдумать и прописать упоротые тесты для всего
func TestSearchInRasp(t *testing.T) {
// Проверка запросов
@ -75,68 +84,83 @@ func TestDownloadShedule(t *testing.T) {
func TestParse(t *testing.T) {
headURL = "http://127.0.0.1:5000"
page, err := DownloadSheduleById(802440189, true, 3)
if err != nil {
log.Println(err)
return
}
_, err = Parse(page)
if err != nil {
log.Println(err)
sh := WeekShedule{
SheduleId: 802440189,
IsGroup: true,
Week: 3,
}
err := sh.DownloadById(false)
handleError(err)
// Ошибки в скелете расписания
for i := 1; i < 6; i++ {
page, err := DownloadSheduleById(123, true, i)
if err != nil {
log.Println(err)
return
}
_, err = Parse(page)
if err != nil {
log.Println(err)
sh := WeekShedule{
SheduleId: 123,
IsGroup: true,
Week: i,
}
err = sh.DownloadById(false)
handleError(err)
}
// Ошибки внутри пар
for i := 2; i < 3; i++ {
page, err := DownloadSheduleById(62806001, false, i)
if err != nil {
log.Println(err)
return
}
sh, err := Parse(page)
if err != nil {
log.Println(err)
sh := WeekShedule{
SheduleId: 62806001,
IsGroup: false,
Week: i,
}
err = sh.DownloadById(false)
handleError(err)
log.Println(sh.FullName)
}
}
func TestSheduleCompare(t *testing.T) {
headURL = "http://127.0.0.1:5000"
page, err := DownloadSheduleById(802440189, true, 4)
if err != nil {
log.Println(err)
return
sh := WeekShedule{
SheduleId: 802440189,
IsGroup: true,
Week: 4,
}
sh, err := Parse(page)
if err != nil {
log.Println(err)
}
lessons := UncoverShedule(*sh)
err := sh.DownloadById(true)
handleError(err)
page, err = DownloadSheduleById(802440189, true, 8)
if err != nil {
log.Println(err)
return
new_sh := WeekShedule{
SheduleId: 802440189,
IsGroup: true,
Week: 8,
}
sh, err = Parse(page)
if err != nil {
log.Println(err)
}
new_lessons := UncoverShedule(*sh)
err = new_sh.DownloadById(true)
handleError(err)
add, del := Compare(new_lessons, lessons)
add, del := Compare(new_sh.Uncovered, sh.Uncovered)
log.Println(add, del)
}
func TestCheckGroupOrTeacher(t *testing.T) {
db, err := database.Connect("test", "TESTpass1!", "testdb")
if err != nil {
log.Println(err)
return
}
// Очистка всех данных для теста
_, err = db.Where("groupid > 0").Delete(&database.Group{})
handleError(err)
_, err = db.Where("teacherid > 0").Delete(&database.Teacher{})
handleError(err)
headURL = "http://127.0.0.1:5000"
sh := WeekShedule{
SheduleId: 802440189,
IsGroup: true,
Week: 4,
}
err = sh.DownloadById(false)
handleError(err)
err = checkGroupOrTeacher(db, sh)
handleError(err)
// Повторяем на предмет наличия
err = checkGroupOrTeacher(db, sh)
handleError(err)
}

View File

@ -102,7 +102,6 @@ func (bot *Bot) Find(query string) error {
TeacherId: elem.Id,
LastName: name[0],
FirstName: name[1],
MidName: name[2],
})
}
}

View File

@ -323,8 +323,8 @@ func PairToStr(pair []database.Lesson, db *xorm.Engine) (string, error) {
name := GenerateName(t)
str += fmt.Sprintf("👤 %s\n", name)
}
if sublesson.SubGroup != "" {
str += fmt.Sprintf("👥 %s\n", sublesson.SubGroup)
if sublesson.SubGroup != 0 {
str += fmt.Sprintf("👥 %d\n", sublesson.SubGroup)
}
if sublesson.Comment != "" {
str += fmt.Sprintf("💬 %s\n", sublesson.Comment)

View File

@ -257,8 +257,8 @@ func (bot *Bot) CreateHTMLShedule(week int, shedule [][6][]database.Lesson, date
if l[0].Place != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[0].Place)
}
if l[0].SubGroup != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[0].SubGroup)
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)
@ -278,8 +278,8 @@ func (bot *Bot) CreateHTMLShedule(week int, shedule [][6][]database.Lesson, date
if l[1].Place != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[1].Place)
}
if l[1].SubGroup != "" {
html += fmt.Sprintf("<h3>%s</h3>\n", l[1].SubGroup)
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)