mirror of
https://github.com/XFox111/bonch-calendar.git
synced 2026-04-22 07:08:01 +03:00
139 lines
5.0 KiB
C#
139 lines
5.0 KiB
C#
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
using AngleSharp.Dom;
|
|
using AngleSharp.Html.Dom;
|
|
using AngleSharp.Html.Parser;
|
|
using BonchCalendar.Utils;
|
|
using Ical.Net.CalendarComponents;
|
|
using Ical.Net.DataTypes;
|
|
|
|
namespace BonchCalendar.Services;
|
|
|
|
public partial class ParsingService
|
|
{
|
|
public CalendarEvent[] ParseGeneralTimetable(string rawHtml, DateTime semesterStartDate, string groupName)
|
|
{
|
|
using IHtmlDocument doc = new HtmlParser().ParseDocument(rawHtml);
|
|
|
|
IHtmlCollection<IElement> rawClasses = doc.QuerySelectorAll(".pair");
|
|
List<CalendarEvent> classes = [];
|
|
|
|
foreach (IElement classItem in rawClasses)
|
|
{
|
|
var (className, classType, professors, auditorium) = ParseBaseInfo(classItem);
|
|
int weekday = int.Parse(classItem.GetAttribute("weekday")!);
|
|
|
|
string timeLabelText = classItem.ParentElement!.ParentElement!.Children[0].TextContent;
|
|
Match timeMatch = ParserUtils.TimeLabelRegex().Match(timeLabelText);
|
|
string number = timeMatch.Success ? timeMatch.Groups["number"].Value : timeLabelText;
|
|
(TimeSpan startTime, TimeSpan endTime) = !timeMatch.Success ?
|
|
ParserUtils.GetTimesFromLabel(timeLabelText) :
|
|
(
|
|
TimeSpan.Parse(timeMatch.Groups["start"].Value),
|
|
TimeSpan.Parse(timeMatch.Groups["end"].Value)
|
|
);
|
|
|
|
int[] weeks = [
|
|
.. ParserUtils.NumberRegex().Matches(classItem.QuerySelector(".weeks")!.TextContent)
|
|
.Select(i => int.Parse(i.Value))
|
|
];
|
|
|
|
foreach (int week in weeks)
|
|
{
|
|
DateTime classDate = semesterStartDate
|
|
.AddDays((week - 1) * 7) // Move to the correct week
|
|
.AddDays(weekday - 1); // Move to the correct weekday
|
|
|
|
classes.Add(GetEvent(
|
|
$"{number}. {className} ({classType})", auditorium,
|
|
GetDescription(groupName, professors, auditorium, weeks),
|
|
classDate, startTime, endTime));
|
|
}
|
|
}
|
|
|
|
return [.. classes];
|
|
}
|
|
|
|
public CalendarEvent[] ParseExamTimetable(string rawHtml, string groupName)
|
|
{
|
|
using IHtmlDocument doc = new HtmlParser().ParseDocument(rawHtml);
|
|
|
|
IHtmlCollection<IElement> rawClasses = doc.QuerySelectorAll(".pair");
|
|
List<CalendarEvent> classes = new(rawClasses.Count);
|
|
|
|
foreach (IElement classItem in rawClasses)
|
|
{
|
|
var (className, classType, professors, auditorium) = ParseBaseInfo(classItem);
|
|
|
|
DateTime classDate = DateTime.ParseExact(classItem.Children[0].ChildNodes[0].TextContent, "dd.MM.yyyy", CultureInfo.InvariantCulture);
|
|
Match timeMatch = ParserUtils.ExamTimeRegex().Match(classItem.GetAttribute("pair")!);
|
|
|
|
if (!timeMatch.Success)
|
|
timeMatch = ParserUtils.ExamTimeAltRegex().Match(classItem.GetAttribute("pair")!);
|
|
|
|
string number = timeMatch.Groups["number"].Success ?
|
|
$"{timeMatch.Groups["number"].Value}. " : string.Empty;
|
|
|
|
TimeSpan startTime = TimeSpan.Parse(timeMatch.Groups["start"].Value.Replace('.', ':'));
|
|
TimeSpan endTime = TimeSpan.Parse(timeMatch.Groups["end"].Value.Replace('.', ':'));
|
|
|
|
classes.Add(GetEvent(
|
|
$"{number}{className} ({classType})", auditorium,
|
|
GetDescription(groupName, professors, auditorium),
|
|
classDate, startTime, endTime));
|
|
}
|
|
|
|
return [.. classes];
|
|
}
|
|
|
|
private static CalendarEvent GetEvent(string title, string auditorium, string description, DateTime date, TimeSpan startTime, TimeSpan endTime) =>
|
|
new()
|
|
{
|
|
Summary = title,
|
|
Description = description,
|
|
Start = new CalDateTime(date.Add(startTime - TimeSpan.FromHours(3)).ToUniversalTime()),
|
|
End = new CalDateTime(date.Add(endTime - TimeSpan.FromHours(3)).ToUniversalTime()),
|
|
Location = auditorium
|
|
};
|
|
|
|
private static string GetDescription(string groupName, string[] professors, string auditorium, int[]? weeks = null)
|
|
{
|
|
string str = $"""
|
|
Группа: {groupName}
|
|
Преподаватель(и):
|
|
- {string.Join("\n- ", professors)}
|
|
""";
|
|
|
|
if (weeks is not null && weeks.Length > 0)
|
|
str += $"\nНедели: {string.Join(", ", weeks)}";
|
|
|
|
Match auditoriumMatch = ParserUtils.AuditoriumRegex().Match(auditorium);
|
|
|
|
if (!auditoriumMatch.Success)
|
|
auditoriumMatch = ParserUtils.AuditoriumAltRegex().Match(auditorium);
|
|
|
|
if (auditoriumMatch.Success)
|
|
str += "\n\n" + $"""
|
|
ГУТ.Навигатор:
|
|
https://nav.sut.ru/?cab=k{auditoriumMatch.Groups["wing"].Value}-{auditoriumMatch.Groups["room"].Value}
|
|
""";
|
|
|
|
return str;
|
|
}
|
|
|
|
private static (string className, string classType, string[] professors, string auditorium) ParseBaseInfo(IElement classElement)
|
|
{
|
|
string className = classElement.QuerySelector(".subect")?.TextContent ?? string.Empty;
|
|
string classType = classElement.QuerySelector(".type")?.TextContent
|
|
.Replace("(", string.Empty).Replace(")", string.Empty).Trim() ?? string.Empty;
|
|
|
|
string[] professors = classElement.QuerySelector(".teacher[title]")?.GetAttribute("title")
|
|
?.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) ?? [];
|
|
|
|
string auditorium = classElement.QuerySelector(".aud")?.TextContent
|
|
.Replace("ауд.:", string.Empty).Replace(';', ',').Trim() ?? string.Empty;
|
|
|
|
return (className, classType, professors, auditorium);
|
|
}
|
|
}
|