Добавьте файлы проекта.

This commit is contained in:
vladdy 2024-05-23 00:29:24 +04:00
parent b2ecc07f77
commit d88bcf2360
8 changed files with 369 additions and 0 deletions

25
UlstuGosApi.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UlstuGosApi", "UlstuGosApi\UlstuGosApi.csproj", "{664D9DC0-1E75-406D-A3BA-DDFD958BD729}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{664D9DC0-1E75-406D-A3BA-DDFD958BD729}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{664D9DC0-1E75-406D-A3BA-DDFD958BD729}.Debug|Any CPU.Build.0 = Debug|Any CPU
{664D9DC0-1E75-406D-A3BA-DDFD958BD729}.Release|Any CPU.ActiveCfg = Release|Any CPU
{664D9DC0-1E75-406D-A3BA-DDFD958BD729}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1D74895A-13EC-44F0-9764-2FDECE58D9E9}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "8.0.5",
"commands": [
"dotnet-ef"
]
}
}
}

40
UlstuGosApi/Program.cs Normal file
View File

@ -0,0 +1,40 @@
using System.Reflection;
using UlstuGosApi;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSystemd();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
});
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseCors();
app.MapGet("/", () => Results.LocalRedirect("/swagger"))
.ExcludeFromDescription();
app.MapGroup("/timetable")
.AddTimeTable()
.WithTags("TimeTable");
app.Run();

View File

@ -0,0 +1,39 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:26590",
"sslPort": 44388
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5189",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7254;http://localhost:5189",
"executablePath": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,216 @@
using System.Net;
namespace UlstuGosApi;
public static class TimeTableRouteGroup
{
public static RouteGroupBuilder AddTimeTable(this RouteGroupBuilder group)
{
group.MapGet("/groups", () => TypedResults.Ok(groups))
.WithSummary("Список групп");
group.MapGet("/rooms", () => TypedResults.Ok(rooms))
.WithSummary("Список аудиторий");
group.MapGet("/teachers", () => TypedResults.Ok(teachers))
.WithSummary("Список преподавателей");
group.MapGet("/by-group/{groupName}", (string groupName) =>
{
var group = groups.FirstOrDefault(m => m.Name == groupName);
if (group == default)
{
return Results.NotFound();
}
return Results.Ok(GenerateByGroup(group));
})
.Produces<TimetableWeek[]>()
.WithSummary("Расписание по учебной группе");
group.MapGet("/by-room/{roomName}", (string roomName) =>
{
var room = rooms.FirstOrDefault(m => m.Name == WebUtility.UrlDecode(roomName));
if (room == default)
{
return Results.NotFound();
}
return Results.Ok(GenerateByRoom(room));
})
.Produces<TimetableWeek[]>()
.WithSummary("Расписание по аудитории");
group.MapGet("/by-teacher/{teacherFullName}", (string teacherFullName) =>
{
var teacher = teachers.FirstOrDefault(m => m.FullName == teacherFullName);
if (teacher == default)
{
return Results.NotFound();
}
return Results.Ok(GenerateByTeacher(teacher));
})
.Produces<TimetableWeek[]>()
.WithSummary("Расписание по преподавателю");
return group;
}
private static TimetableGroup[] groups = [
new TimetableGroup("ПИбд-41"),
new TimetableGroup("ПИбд-42"),
new TimetableGroup("ПИбд-43"),
];
private static TimetableRoom[] rooms = [
new TimetableRoom("3/420"),
new TimetableRoom("3/424"),
new TimetableRoom("3/429"),
new TimetableRoom("3/431"),
];
private static TimetableTeacher[] teachers = [
new TimetableTeacher("Иванов И.И."),
new TimetableTeacher("Петров П.П."),
new TimetableTeacher("Сидорова С.С."),
];
private static TimetableSubject[] subjects = [
new TimetableSubject(teachers[0], "Основы программирования", "лек"),
new TimetableSubject(teachers[0], "Базы данных", "лек"),
new TimetableSubject(teachers[0], "Схемотехника", "лек"),
new TimetableSubject(teachers[1], "Основы программирования", "л/р"),
new TimetableSubject(teachers[1], "Базы данных", "л/р"),
new TimetableSubject(teachers[2], "Философия", "лек"),
new TimetableSubject(teachers[2], "Философия", "сем"),
];
private const int LessonsMaxCount = 2 * 6 * 8;
private static List<TimetableLesson> lessons = new();
private static object lessonsLockObj = new object();
public static IReadOnlyList<TimetableLesson> Lessons
{
get
{
lock (lessonsLockObj)
{
if (lessons.Count == 0)
{
GenerateLessons();
}
}
return lessons;
}
}
private static void GenerateLessons()
{
foreach (var idx in Enumerable.Range(0, LessonsMaxCount))
{
lessons.Add(
new TimetableLesson(
groups[Random.Shared.Next(groups.Length)], rooms[Random.Shared.Next(rooms.Length)], subjects[Random.Shared.Next(subjects.Length)]
));
}
}
private static TimetableWeek[] GenerateByGroup(TimetableGroup group) => GenerateWithLessons(Lessons.Where(i => i.Group == group));
private static TimetableWeek[] GenerateByRoom(TimetableRoom room) => GenerateWithLessons(Lessons.Where(i => i.Room == room));
private static TimetableWeek[] GenerateByTeacher(TimetableTeacher teacher) => GenerateWithLessons(Lessons.Where(i => i.Subject.Teacher == teacher));
private static TimetableWeek[] GenerateWithLessons(IEnumerable<TimetableLesson> filteredLessons)
{
var weeks = new List<TimetableWeek>();
var lessonsEnumerator = filteredLessons.GetEnumerator();
weeks.Add(new TimetableWeek(GenerateDays(lessonsEnumerator), true));
weeks.Add(new TimetableWeek(GenerateDays(lessonsEnumerator), false));
return weeks.ToArray();
}
private static TimetableDay[] GenerateDays(IEnumerator<TimetableLesson> filteredLessons)
{
var result = new List<TimetableDay>();
foreach (var _ in Enumerable.Range(1, 6))
{
result.Add(GenerateDay(filteredLessons));
}
return result.ToArray();
}
private static TimetableDay GenerateDay(IEnumerator<TimetableLesson> filteredLessons)
{
var result = new List<TimetableLesson?>();
foreach (var _ in Enumerable.Range(1, 8))
{
if (Random.Shared.NextDouble() < 0.25)
{
filteredLessons.MoveNext();
result.Add(filteredLessons.Current);
}
else
{
result.Add(null);
}
}
return new TimetableDay(result.ToArray());
}
}
/// <summary>
/// Неделя расписания.
/// </summary>
/// <param name="Days">Массив дней недели: ПН, ВТ, СР и до субботы.</param>
/// <param name="IsOdd">Флаг нечётности.</param>
public sealed record TimetableWeek(
TimetableDay[] Days,
bool IsOdd
);
/// <summary>
/// День расписания.
/// </summary>
/// <param name="Lessons">Массив пар от 1й до 8й. Если пары в "слоте" нет, возвращается null.</param>
public sealed record TimetableDay(
TimetableLesson?[] Lessons
);
/// <summary>
/// "Слот" расписания, непосредственно пара.
/// </summary>
/// <param name="Group">Группа.</param>
/// <param name="Room">Аудитория.</param>
/// <param name="Subject">Дисциплина.</param>
public sealed record TimetableLesson(
TimetableGroup Group,
TimetableRoom Room,
TimetableSubject Subject
);
/// <summary>
/// Группа.
/// </summary>
/// <param name="Name">Название.</param>
public sealed record TimetableGroup(
string Name
);
/// <summary>
/// Аудитория.
/// </summary>
/// <param name="Name">Номер.</param>
public sealed record TimetableRoom(
string Name
);
/// <summary>
/// Дисциплина.
/// </summary>
/// <param name="Teacher">Преподаватель.</param>
/// <param name="Name">Имя.</param>
/// <param name="Type">Тип занятия.</param>
public sealed record TimetableSubject(
TimetableTeacher Teacher,
string Name,
string Type
);
/// <summary>
/// Преподаватель
/// </summary>
/// <param name="FullName">ФИО.</param>
public sealed record TimetableTeacher(
string FullName
);

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}