Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,4 @@ FodyWeavers.xsd
*.msi
*.msix
*.msm
*.msp
*.msp
8 changes: 4 additions & 4 deletions Client.Wasm/Components/StudentCard.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
</CardHeader>
<CardBody>
<UnorderedList Unstyled>
<UnorderedListItem>Номер <Strong>№X "Название лабораторной"</Strong></UnorderedListItem>
<UnorderedListItem>Вариант <Strong>№Х "Название варианта"</Strong></UnorderedListItem>
<UnorderedListItem>Выполнена <Strong>Фамилией Именем 65ХХ</Strong> </UnorderedListItem>
<UnorderedListItem><Link To="https://puginarug.com/">Ссылка на форк</Link></UnorderedListItem>
<UnorderedListItem>Номер <Strong>№1 "«Кэширование» - Реализация сервиса генерации контрактов, кэширование его ответов"</Strong></UnorderedListItem>
<UnorderedListItem>Вариант <Strong>№7 "Программный проект"</Strong></UnorderedListItem>
<UnorderedListItem>Выполнена <Strong>Земель Алексеем 6511</Strong> </UnorderedListItem>
<UnorderedListItem><Link To="https://github.com/AlexeyZemel/cloud-development">Ссылка на форк</Link></UnorderedListItem>
</UnorderedList>
</CardBody>
</Card>
2 changes: 1 addition & 1 deletion Client.Wasm/wwwroot/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
}
},
"AllowedHosts": "*",
"BaseAddress": ""
"BaseAddress": "http://localhost:5179/api/project"
Comment thread
danlla marked this conversation as resolved.
Outdated
}
27 changes: 25 additions & 2 deletions CloudDevelopment.sln
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36811.4
VisualStudioVersion = 17.13.35931.197
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.Wasm", "Client.Wasm\Client.Wasm.csproj", "{AE7EEA74-2FE0-136F-D797-854FD87E022A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectApp.Api", "ProjectApp.Api\ProjectApp.Api.csproj", "{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectApp.Domain", "ProjectApp.Domain\ProjectApp.Domain.csproj", "{CC5A9873-4CC3-4B71-83AF-E4FD09F7B1AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectApp.ServiceDefaults", "ProjectApp.ServiceDefaults\ProjectApp.ServiceDefaults.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectApp.AppHost", "ProjectApp.AppHost\ProjectApp.AppHost.csproj", "{2A5FB573-9376-4FEB-9289-A8387F435C13}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -15,6 +22,22 @@ Global
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.Build.0 = Release|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Release|Any CPU.Build.0 = Release|Any CPU
{CC5A9873-4CC3-4B71-83AF-E4FD09F7B1AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC5A9873-4CC3-4B71-83AF-E4FD09F7B1AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC5A9873-4CC3-4B71-83AF-E4FD09F7B1AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC5A9873-4CC3-4B71-83AF-E4FD09F7B1AD}.Release|Any CPU.Build.0 = Release|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.Build.0 = Release|Any CPU
{2A5FB573-9376-4FEB-9289-A8387F435C13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A5FB573-9376-4FEB-9289-A8387F435C13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A5FB573-9376-4FEB-9289-A8387F435C13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A5FB573-9376-4FEB-9289-A8387F435C13}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
33 changes: 33 additions & 0 deletions ProjectApp.Api/Controllers/ProjectController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using ProjectApp.Domain.Entities;
using Microsoft.AspNetCore.Mvc;
using ProjectApp.Api.Services;

namespace ProjectApp.Api.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ProjectController(ProgramProjectGeneratorService generatorService, ILogger<ProjectController> logger) : ControllerBase
{
/// <summary>
/// Âîçâðàùàåò ïðîåêò ïî èäåíòèôèêàòîðó èëè ãåíåðèðóåò íîâûé, åñëè îí íå íàéäåí â êýøå
/// </summary>
/// <param name="id">Èäåíòèôèêàòîð ïðîåêòà</param>
/// <param name="cancellationToken">Òîêåí îòìåíû</param>
/// <returns>Ïðîãðàììíûé ïðîåêò</returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<ProgramProject>> GetById([FromQuery] int id, CancellationToken cancellationToken)
{
if (id < 0)
{
return BadRequest("id must be a positive integer.");
}

logger.LogInformation("Received request to retrieve/generate project {Id}", id);

var project = await generatorService.GetByIdAsync(id, cancellationToken);

return Ok(project);
}
}
6 changes: 6 additions & 0 deletions ProjectApp.Api/Options/CacheSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ProjectApp.Api.Options;

public class CacheSettings
{
public int ExpirationMinutes { get; set; } = 10;
}
64 changes: 64 additions & 0 deletions ProjectApp.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using ProjectApp.Api.Services;
using ProjectApp.ServiceDefaults;
using ProjectApp.Api.Options;
using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.AddRedisDistributedCache("cache");

builder.Services.Configure<CacheSettings>(builder.Configuration.GetSection("CacheSettings"));
builder.Services.AddSingleton(new JsonSerializerOptions(JsonSerializerDefaults.Web));

builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.SetIsOriginAllowed(origin => new Uri(origin).Host == "localhost")
Comment thread
danlla marked this conversation as resolved.
Outdated
.WithMethods("GET")
.WithHeaders("Content-Type");
});
});

builder.Services.AddScoped<ProgramProjectGenerator>();
builder.Services.AddScoped<ProgramProjectGeneratorService>();

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Microsoft.OpenApi.OpenApiInfo
{
Title = "Project Generator API"
});

var xmlFilename = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFilename);
if (File.Exists(xmlPath))
{
options.IncludeXmlComments(xmlPath);
}

var domainXmlPath = Path.Combine(AppContext.BaseDirectory, "ProjectApp.Domain.xml");
if (File.Exists(domainXmlPath))
{
options.IncludeXmlComments(domainXmlPath);
}
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseCors();
app.MapControllers();
app.MapDefaultEndpoints();

app.Run();
23 changes: 23 additions & 0 deletions ProjectApp.Api/ProjectApp.Api.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspire.StackExchange.Redis.DistributedCaching" Version="9.5.2" />
<PackageReference Include="Bogus" Version="35.6.5" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.24" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.4" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ProjectApp.Domain\ProjectApp.Domain.csproj" />
<ProjectReference Include="..\ProjectApp.ServiceDefaults\ProjectApp.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions ProjectApp.Api/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:46825",
"sslPort": 44333
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5179",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7170;http://localhost:5179",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
76 changes: 76 additions & 0 deletions ProjectApp.Api/Services/ProgramProjectGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using Bogus;
using ProjectApp.Domain.Entities;

namespace ProjectApp.Api.Services;

/// <summary>
/// Ãåíåðèðóåò ñëó÷àéíûé ïðîãðàììíûé ïðîåêò
/// </summary>
Comment thread
danlla marked this conversation as resolved.
public class ProgramProjectGenerator
Comment thread
danlla marked this conversation as resolved.
Outdated
{
private readonly Faker<ProgramProject> _faker;

private static readonly string[] _patronymics = new[]
{
"Èâàíîâè÷", "Ïåòðîâè÷", "Ñèäîðîâè÷", "Àëåêñàíäðîâè÷", "Äìèòðèåâè÷",
"Àíäðååâè÷", "Ñåðãååâè÷", "Àëåêñååâè÷", "Íèêîëàåâè÷", "Âëàäèìèðîâè÷",
"Èâàíîâíà", "Ïåòðîâíà", "Ñèäîðîâíà", "Àëåêñàíäðîâíà", "Äìèòðèåâíà",
"Àíäðååâíà", "Ñåðãååâíà", "Àëåêñååâíà", "Íèêîëàåâíà", "Âëàäèìèðîâíà"
};
public ProgramProjectGenerator()
{

_faker = new Faker<ProgramProject>("ru")
Comment thread
danlla marked this conversation as resolved.
Outdated
.RuleFor(p => p.Id, f => f.IndexFaker + 1)
Comment thread
danlla marked this conversation as resolved.
Outdated
.RuleFor(p => p.ProjectName, f =>
$"{f.Commerce.ProductName()} {f.Hacker.Noun()} {f.Finance.AccountName()} {f.Lorem.Word()}")
.RuleFor(p => p.Customer, f =>
f.Company.CompanyName())
.RuleFor(p => p.ProjectManager, f =>
{
var lastName = f.Name.LastName();
var firstName = f.Name.FirstName();
var patronymic = f.PickRandom(_patronymics);
Comment thread
danlla marked this conversation as resolved.
Outdated
return $"{lastName} {firstName} {patronymic}";
Comment thread
danlla marked this conversation as resolved.
Outdated
})
.RuleFor(p => p.StartDate,
f => f.Date.PastDateOnly(3))
.RuleFor(p => p.PlannedEndDate,
(f, p) => p.StartDate.AddDays(f.Random.Int(30, 730)))
.RuleFor(p => p.Budget,
f => Math.Round(f.Finance.Amount(500000, 50000000), 2))
.RuleFor(p => p.ActualEndDate, (f, p) =>
{
var completed = f.Random.Bool(0.4f);

if (!completed)
return null;

var start = p.StartDate.ToDateTime(TimeOnly.MinValue);
var end = f.Date.Between(start.AddDays(1), DateTime.Now);

return DateOnly.FromDateTime(end);
})
.RuleFor(p => p.CompletionPercentage, (f, p) =>
{
if (p.ActualEndDate != null)
return 100;

return f.Random.Int(0, 99);
})
.RuleFor(p => p.ActualCost, (f, p) =>
{
var minFactor = Math.Max(0.1m, p.CompletionPercentage / 100m * 0.8m);
var maxFactor = Math.Min(1.2m, p.CompletionPercentage / 100m * 1.2m);

var factor = f.Random.Decimal(minFactor, maxFactor);

return Math.Round(p.Budget * factor, 2);
});
}

public ProgramProject Generate()
{
return _faker.Generate();
}
}
Loading
Loading