diff --git a/README.md b/README.md index edba579..f52610c 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ Simulation tunables live under the `Simulation` section of | `ModsDirectory` | `mods` | pack folders; `core` is required | | `SaveIntervalSeconds` | 30 | rare clock snapshot; not every tick | | `MinSaveIntervalMilliseconds` | 1000 | shortest gap between saves caused by pause or speed | -| `MonthlyPayrollCap` | 40000 | monthly payroll the player may commit; hires and assignments that would exceed it are rejected | +| `MonthlyPayrollCap` | 100000 | monthly payroll the player may commit; hires and assignments that would exceed it are rejected | | `SchoolWeekDays` | 5 | working days from Monday (5 is Mon–Fri; 6 adds Saturday) | ## What is deliberately missing diff --git a/docs/protocol.md b/docs/protocol.md index eb5fa28..9668ca0 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -244,9 +244,9 @@ those lessons will not happen. ```json { - "allocated": 10000, + "allocated": 100000, "payroll": 5000, - "remaining": 5000, + "remaining": 95000, "uncovered": [ { "defName": "Mathematics", diff --git a/src/HSchool.Client/src/style.css b/src/HSchool.Client/src/style.css index 05cf18a..f5a4d54 100644 --- a/src/HSchool.Client/src/style.css +++ b/src/HSchool.Client/src/style.css @@ -63,8 +63,13 @@ body { justify-content: center; } +/* + * No cap. A reading column has a sensible maximum width; a management screen does not — it is a + * tree, a table and a timetable grid, and every pixel taken away from them is a pixel of scrolling. + * The menu below keeps its column, because a row of cards centred on a wide display reads better. + */ .screen.game { - max-width: 1500px; + max-width: none; } #status { @@ -585,6 +590,27 @@ body { text-transform: uppercase; } +/* + * Blocks on a card need a line between them, not just a caption: needs, family and the timetable + * ran together into one wall. The rule hangs off the caption rather than a wrapper because not + * every block has one — the timetable is a bare heading plus a grid. + * + * The faint hairlines inside a block (rows of a pair grid) stay lighter than this one on purpose: + * strong line means a new block, faint line means the next row. + */ +.people__card .people__section-title { + margin-top: 14px; + padding-top: 11px; + border-top: 1px solid var(--border); +} + +/* The first block sits right under the name, where a divider would only add noise. */ +.people__card > .people__card-meta + .people__section > .people__section-title { + margin-top: 0; + padding-top: 0; + border-top: 0; +} + /* * Name on the left, value on the right, as many columns as the panel is wide. As a bulleted list * fourteen skills ran the card past the fold with three quarters of the width empty. diff --git a/src/HSchool.Server/appsettings.json b/src/HSchool.Server/appsettings.json index 18c0ec9..b483337 100644 --- a/src/HSchool.Server/appsettings.json +++ b/src/HSchool.Server/appsettings.json @@ -14,7 +14,7 @@ "SavesDirectory": "saves", "ModsDirectory": "mods", "SaveIntervalSeconds": 30, - "MonthlyPayrollCap": 40000, + "MonthlyPayrollCap": 100000, "SchoolWeekDays": 5 } } diff --git a/src/HSchool.Simulation/SimulationOptions.cs b/src/HSchool.Simulation/SimulationOptions.cs index 231b18f..e9a8ac3 100644 --- a/src/HSchool.Simulation/SimulationOptions.cs +++ b/src/HSchool.Simulation/SimulationOptions.cs @@ -53,7 +53,7 @@ public sealed class SimulationOptions /// Monthly payroll the player may commit. Hire and subject assignment that would exceed it /// are rejected immediately; money itself does not move. /// - public float MonthlyPayrollCap { get; set; } = 40_000f; + public float MonthlyPayrollCap { get; set; } = 100_000f; /// /// Working days from Monday. Five is Mon–Fri; six adds Saturday; seven is every day. diff --git a/tests/HSchool.AppHost.Tests/StaffingApiTests.cs b/tests/HSchool.AppHost.Tests/StaffingApiTests.cs index 01f9c7b..48a9f85 100644 --- a/tests/HSchool.AppHost.Tests/StaffingApiTests.cs +++ b/tests/HSchool.AppHost.Tests/StaffingApiTests.cs @@ -26,9 +26,9 @@ public class StaffingApiTests(AppHostFixture fixture) var staffing = await GetStaffingAsync(client, school.Id); - Assert.Equal(40_000f, staffing.Allocated); + Assert.Equal(100_000f, staffing.Allocated); Assert.Equal(0f, staffing.Payroll); - Assert.Equal(40_000f, staffing.Remaining); + Assert.Equal(100_000f, staffing.Remaining); Assert.Equal(12, staffing.Applicants.Count); Assert.Empty(staffing.Staff); Assert.Contains(staffing.Uncovered, subject => subject.DefName == "Mathematics"); @@ -121,14 +121,13 @@ public class StaffingApiTests(AppHostFixture fixture) } [Fact] - public async Task Hire_PastTheCap_IsRejectedWithTheNumbers() + public async Task Hire_IdlePool_FitsUnderTheCap() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); var school = await SchoolApiTests.CreateAsync(client, "Штат предел", Start); var staffing = await GetStaffingAsync(client, school.Id); - ProblemResponse? problem = null; while (staffing.Applicants.Count > 0) { var applicant = staffing.Applicants[0]; @@ -136,22 +135,15 @@ public class StaffingApiTests(AppHostFixture fixture) $"/api/schools/{school.Id}/staff/hire", new { personId = applicant.Id, position = "Teacher" }, TestContext.Current.CancellationToken); - if (response.StatusCode == HttpStatusCode.Conflict) - { - problem = await response.Content.ReadFromJsonAsync(TestContext.Current.CancellationToken); - break; - } - response.EnsureSuccessStatusCode(); staffing = await response.Content.ReadFromJsonAsync(TestContext.Current.CancellationToken); Assert.NotNull(staffing); } - Assert.Equal("payroll-exceeded", problem?.Code); - Assert.Equal(40_000f, problem?.Allocated); - Assert.True(problem?.Payroll <= 40_000f); - Assert.True(problem?.Attempted > 40_000f); - Assert.True(staffing.Staff.Count >= 1); + Assert.Equal(100_000f, staffing.Allocated); + Assert.True(staffing.Payroll > 0f); + Assert.True(staffing.Payroll <= staffing.Allocated); + Assert.Equal(12, staffing.Staff.Count); } [Fact]