This commit is contained in:
Alex 2025-03-09 18:02:57 +03:00
parent fcad583362
commit e335e9f5d9
16 changed files with 496 additions and 0 deletions

13
.idea/.idea.Hard_Demo/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/contentModel.xml
/modules.xml
/.idea.Hard_Demo.iml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
namespace Hard_Demo.Models;
public partial class Client
{
public int Id { get; set; }
public string Fio { get; set; } = null!;
public int ClientCode { get; set; }
public string Passport { get; set; } = null!;
public DateOnly Birthday { get; set; }
public string Address { get; set; } = null!;
public string Email { get; set; } = null!;
public string Password { get; set; } = null!;
public int RoleId { get; set; }
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace Hard_Demo.Models;
public partial class Employee
{
public int EmployeId { get; set; }
public int RoleId { get; set; }
public string Fio { get; set; } = null!;
public string EmployeLogin { get; set; } = null!;
public string EmployePassword { get; set; } = null!;
public string? EmployePhoto { get; set; }
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
namespace Hard_Demo.Models;
public partial class LastEnter
{
public int EmployeId { get; set; }
public DateTime EnterDatetime { get; set; }
public string EnterType { get; set; } = null!;
public string? Login { get; set; }
}

27
Hard_Demo/Models/Order.cs Normal file
View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace Hard_Demo.Models;
public partial class Order
{
public int Id { get; set; }
public string OrderCode { get; set; } = null!;
public DateOnly OrderDate { get; set; }
public TimeOnly OrderTime { get; set; }
public int ClientCode { get; set; }
public int ServiceId { get; set; }
public string Status { get; set; } = null!;
public DateOnly? DateClose { get; set; }
public int RentalTime { get; set; }
public virtual ICollection<Service> Idservices { get; set; } = new List<Service>();
}

11
Hard_Demo/Models/Role.cs Normal file
View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
namespace Hard_Demo.Models;
public partial class Role
{
public int RoleId { get; set; }
public string RoleName { get; set; } = null!;
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
namespace Hard_Demo.Models;
public partial class Service
{
public int Id { get; set; }
public string ServiceName { get; set; } = null!;
public string ServiceCode { get; set; } = null!;
public string ServiceCost { get; set; } = null!;
public virtual ICollection<Order> Idorders { get; set; } = new List<Order>();
}

View File

@ -0,0 +1,185 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace Hard_Demo.Models;
public partial class User2Context : DbContext
{
public User2Context()
{
}
public User2Context(DbContextOptions<User2Context> options)
: base(options)
{
}
public virtual DbSet<Client> Clients { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<LastEnter> LastEnters { get; set; }
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<Service> Services { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseNpgsql("Host=45.67.56.214;Port=5454;USERNAME=user2;DATABASE=user2;Password=hGcLvi0i");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Client>(entity =>
{
entity.HasKey(e => e.Id).HasName("clients_pk");
entity.ToTable("clients");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.Address)
.HasColumnType("character varying")
.HasColumnName("address");
entity.Property(e => e.Birthday).HasColumnName("birthday");
entity.Property(e => e.ClientCode).HasColumnName("client_code");
entity.Property(e => e.Email)
.HasColumnType("character varying")
.HasColumnName("email");
entity.Property(e => e.Fio)
.HasColumnType("character varying")
.HasColumnName("fio");
entity.Property(e => e.Passport)
.HasColumnType("character varying")
.HasColumnName("passport");
entity.Property(e => e.Password)
.HasColumnType("character varying")
.HasColumnName("password");
entity.Property(e => e.RoleId).HasColumnName("role_id");
});
modelBuilder.Entity<Employee>(entity =>
{
entity.HasKey(e => e.EmployeId).HasName("employees_pk");
entity.ToTable("employees");
entity.Property(e => e.EmployeId)
.ValueGeneratedNever()
.HasColumnName("employe_id");
entity.Property(e => e.EmployeLogin)
.HasColumnType("character varying")
.HasColumnName("employe_login");
entity.Property(e => e.EmployePassword)
.HasColumnType("character varying")
.HasColumnName("employe_password");
entity.Property(e => e.EmployePhoto)
.HasColumnType("character varying")
.HasColumnName("employe_photo");
entity.Property(e => e.Fio)
.HasColumnType("character varying")
.HasColumnName("fio");
entity.Property(e => e.RoleId).HasColumnName("role_id");
});
modelBuilder.Entity<LastEnter>(entity =>
{
entity.HasKey(e => e.EmployeId).HasName("last_enter_pk");
entity.ToTable("last_enter");
entity.Property(e => e.EmployeId)
.ValueGeneratedNever()
.HasColumnName("employe_id");
entity.Property(e => e.EnterDatetime)
.HasColumnType("timestamp without time zone")
.HasColumnName("enter_datetime");
entity.Property(e => e.EnterType)
.HasColumnType("character varying")
.HasColumnName("enter_type");
entity.Property(e => e.Login)
.HasColumnType("character varying")
.HasColumnName("login");
});
modelBuilder.Entity<Order>(entity =>
{
entity.HasKey(e => e.Id).HasName("orders_pk");
entity.ToTable("orders");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.ClientCode).HasColumnName("client_code");
entity.Property(e => e.DateClose).HasColumnName("date_close");
entity.Property(e => e.OrderCode)
.HasColumnType("character varying")
.HasColumnName("order_code");
entity.Property(e => e.OrderDate).HasColumnName("order_date");
entity.Property(e => e.OrderTime).HasColumnName("order_time");
entity.Property(e => e.RentalTime).HasColumnName("rental_time");
entity.Property(e => e.ServiceId).HasColumnName("service_id");
entity.Property(e => e.Status)
.HasColumnType("character varying")
.HasColumnName("status");
});
modelBuilder.Entity<Role>(entity =>
{
entity.HasKey(e => e.RoleId).HasName("roles_pk");
entity.ToTable("roles");
entity.Property(e => e.RoleId).HasColumnName("role_id");
entity.Property(e => e.RoleName)
.HasColumnType("character varying")
.HasColumnName("role_name");
});
modelBuilder.Entity<Service>(entity =>
{
entity.HasKey(e => e.Id).HasName("service_pk");
entity.ToTable("service");
entity.HasIndex(e => e.ServiceCode, "service_unique").IsUnique();
entity.Property(e => e.Id)
.ValueGeneratedNever()
.HasColumnName("id");
entity.Property(e => e.ServiceCode)
.HasColumnType("character varying")
.HasColumnName("service_code");
entity.Property(e => e.ServiceCost)
.HasColumnType("character varying")
.HasColumnName("service_cost");
entity.Property(e => e.ServiceName)
.HasColumnType("character varying")
.HasColumnName("service_name");
entity.HasMany(d => d.Idorders).WithMany(p => p.Idservices)
.UsingEntity<Dictionary<string, object>>(
"OrderService",
r => r.HasOne<Order>().WithMany()
.HasForeignKey("Idorder")
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("order_service_orders_fk"),
l => l.HasOne<Service>().WithMany()
.HasForeignKey("Idservice")
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("order_service_service_fk"),
j =>
{
j.HasKey("Idservice", "Idorder").HasName("order_service_pk");
j.ToTable("order_service");
j.IndexerProperty<int>("Idservice").HasColumnName("idservice");
j.IndexerProperty<int>("Idorder").HasColumnName("idorder");
});
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

22
Hard_Demo/Program.cs Normal file
View File

@ -0,0 +1,22 @@
using Avalonia;
using System;
using Hard_Demo;
namespace demo_hard;
class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}

40
Library/Library.cs Normal file
View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
namespace Library
{
public class Calculations
{
public string[] AvailablePeriods(TimeSpan[] startTimes, int[] durations, TimeSpan beginWorkingTime, TimeSpan endWorkingTime, int consultationTime)
{
TimeSpan consultationDuration = TimeSpan.FromMinutes(consultationTime);
List<string> freeSlots = new List<string>();
TimeSpan current = beginWorkingTime;
for (int i = 0; i < startTimes.Length; i++)
{
TimeSpan start = startTimes[i];
TimeSpan end = start.Add(TimeSpan.FromMinutes(durations[i]));
while (current.Add(consultationDuration) <= start)
{
freeSlots.Add($"{current:hh\\:mm}-{current.Add(consultationDuration):hh\\:mm}");
current = current.Add(consultationDuration);
}
if (current < end)
{
current = end;
}
}
while (current.Add(consultationDuration) <= endWorkingTime)
{
freeSlots.Add($"{current:hh\\:mm}-{current.Add(consultationDuration):hh\\:mm}");
current = current.Add(consultationDuration);
}
return freeSlots.ToArray();
}
}
}

9
Library/Library.csproj Normal file
View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

27
Tests/Tests.csproj Normal file
View File

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Library\Library.csproj" />
</ItemGroup>
</Project>

68
Tests/UnitTest1.cs Normal file
View File

@ -0,0 +1,68 @@
using System;
using Xunit;
using Library;
namespace Library.Tests
{
public class CalculationsTests
{
[Fact]
public void AvailablePeriods_ReturnsFullDaySlots_WhenNoAppointments()
{
// Arrange
var calculations = new Calculations();
TimeSpan[] startTimes = Array.Empty<TimeSpan>();
int[] durations = Array.Empty<int>();
TimeSpan beginWorkingTime = new TimeSpan(9, 0, 0);
TimeSpan endWorkingTime = new TimeSpan(17, 0, 0);
int consultationTime = 30;
// Act
var result = calculations.AvailablePeriods(startTimes, durations, beginWorkingTime, endWorkingTime, consultationTime);
// Assert
Assert.NotEmpty(result);
Assert.Contains("09:00-09:30", result);
Assert.Contains("16:30-17:00", result);
}
[Fact]
public void AvailablePeriods_ReturnsCorrectSlots_WhenThereAreAppointments()
{
// Arrange
var calculations = new Calculations();
TimeSpan[] startTimes = { new TimeSpan(10, 0, 0), new TimeSpan(14, 0, 0) };
int[] durations = { 60, 60 };
TimeSpan beginWorkingTime = new TimeSpan(9, 0, 0);
TimeSpan endWorkingTime = new TimeSpan(17, 0, 0);
int consultationTime = 30;
// Act
var result = calculations.AvailablePeriods(startTimes, durations, beginWorkingTime, endWorkingTime, consultationTime);
// Assert
Assert.DoesNotContain("10:00-10:30", result);
Assert.DoesNotContain("14:00-14:30", result);
Assert.Contains("09:00-09:30", result);
Assert.Contains("15:30-16:00", result);
}
[Fact]
public void AvailablePeriods_ReturnsEmpty_WhenNoFreeSlots()
{
// Arrange
var calculations = new Calculations();
TimeSpan[] startTimes = { new TimeSpan(9, 0, 0) };
int[] durations = { 480 }; // 8 hours (full workday)
TimeSpan beginWorkingTime = new TimeSpan(9, 0, 0);
TimeSpan endWorkingTime = new TimeSpan(17, 0, 0);
int consultationTime = 30;
// Act
var result = calculations.AvailablePeriods(startTimes, durations, beginWorkingTime, endWorkingTime, consultationTime);
// Assert
Assert.Empty(result);
}
}
}