feat: Chemikalien-Recherche über lokale RiSU-Stoffliste (kein KI-Aufruf mehr)
Ersetzt den ursprünglichen KI-Websuche-Ansatz (GESTIS scheiterte sowohl über Websuche als auch über direkten API-Zugriff an fehlenden schulspezifischen Tätigkeitsbeschränkungen) durch einen reinen lokalen Datenbank-Lookup gegen die offizielle RiSU-Stoffliste (1764 Stoffe inkl. Tätigkeitsbeschränkungs-Codes, Legende zur Abfragezeit übersetzt statt in die Datenbank gebacken). Keine KI-Kosten, keine Drittanbieter-Abhängigkeit mehr für diese Funktion. HazardSubstance.AgeRestriction zu ActivityRestriction umbenannt, da die Tätigkeitsbeschränkung mehr abdeckt als reine Altersgrenzen. Details und verworfene Zwischenstände in TODO.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using LehrerApp.Core.AiPlanning;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Desktop.Services;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
using Xunit;
|
||||
|
||||
@@ -8,6 +10,13 @@ public sealed class HazardAssessmentWizardViewModelTests
|
||||
{
|
||||
private static HazardAssessmentWizardViewModel Build(HazardAssessment? editing = null) => new(editing, "10c");
|
||||
|
||||
private static string BuildTempPath()
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), $"lehrerapp-gbuwizard-tests-{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Neu_StartetAufSchritt0OhneKiOhneEditingKennzeichnung()
|
||||
{
|
||||
@@ -227,6 +236,111 @@ public sealed class HazardAssessmentWizardViewModelTests
|
||||
Assert.Equal("Notiz", vm.Notes);
|
||||
Assert.True(vm.IsAiAssisted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanUseAi_OhneKiAbhaengigkeiten_IstFalseUndSubstanzenKoennenNichtRecherchieren()
|
||||
{
|
||||
var vm = Build();
|
||||
vm.AddSubstanceCommand.Execute(null);
|
||||
|
||||
Assert.False(vm.CanUseAi);
|
||||
Assert.False(vm.Substances[0].CanResearch);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanUseAi_MitAngemeldeterKiUndUnitUndLesson_IstTrueUndSubstanzenKoennenRecherchieren()
|
||||
{
|
||||
var aiSettings = new AiSettingsService(BuildTempPath());
|
||||
aiSettings.SetEnabled(true);
|
||||
aiSettings.SetCredentialsAndToken("sebastian", "token-abc");
|
||||
var ai = new AiPlanningService(new HttpClient(), new FakeLessons(), new FakeGroups([]),
|
||||
new FakeSubjects([]), new FakeCompetencyDomains(), new FakeAlternativeLessonPaths([]));
|
||||
var unit = new Unit { Title = "Redoxreaktionen" };
|
||||
var lesson = new Lesson { Topic = "Natrium in Wasser" };
|
||||
|
||||
var vm = new HazardAssessmentWizardViewModel(null, "10c", ai, aiSettings, unit, lesson);
|
||||
vm.AddSubstanceCommand.Execute(null);
|
||||
|
||||
Assert.True(vm.CanUseAi);
|
||||
Assert.True(vm.Substances[0].CanResearch);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HazardSubstanceEditItemTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Research_OhneOnResearch_TutNichtsUndBleibtOhneFehler()
|
||||
{
|
||||
var item = new HazardSubstanceEditItem { Name = "Natrium" };
|
||||
|
||||
await item.ResearchCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.Equal("", item.ResearchError);
|
||||
Assert.False(item.IsResearching);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Research_OhneNamen_SetztFehlerUndRuftDelegateNicht()
|
||||
{
|
||||
var called = false;
|
||||
var item = new HazardSubstanceEditItem
|
||||
{
|
||||
Name = " ",
|
||||
OnResearch = _ => { called = true; return Task.FromResult(new AiSubstanceResearchResponse()); },
|
||||
};
|
||||
|
||||
await item.ResearchCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.False(called);
|
||||
Assert.Equal("Stoffname eingeben.", item.ResearchError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Research_UebernimmtAlleFelderAusDerAntwort()
|
||||
{
|
||||
var item = new HazardSubstanceEditItem { Name = "Natrium" };
|
||||
item.OnResearch = name =>
|
||||
{
|
||||
Assert.Equal("Natrium", name);
|
||||
return Task.FromResult(new AiSubstanceResearchResponse
|
||||
{
|
||||
Name = "Natrium",
|
||||
Cas = "7440-23-5",
|
||||
SignalWord = "Gefahr",
|
||||
HStatements = "H260",
|
||||
PStatements = "P223, P231+P232",
|
||||
ActivityRestriction = "Für Schüler ab der 5. Klasse freigegeben",
|
||||
GhsPictograms = ["GHS02", "GHS05"],
|
||||
});
|
||||
};
|
||||
|
||||
await item.ResearchCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.Equal("Natrium", item.Name);
|
||||
Assert.Equal("7440-23-5", item.Cas);
|
||||
Assert.Equal("Gefahr", item.SignalWord);
|
||||
Assert.Equal("H260", item.HStatements);
|
||||
Assert.Equal("P223, P231+P232", item.PStatements);
|
||||
Assert.Equal("Für Schüler ab der 5. Klasse freigegeben", item.ActivityRestriction);
|
||||
Assert.True(item.PictogramOptions.Single(o => o.Value == GhsPictogram.Flammable).IsSelected);
|
||||
Assert.True(item.PictogramOptions.Single(o => o.Value == GhsPictogram.Corrosive).IsSelected);
|
||||
Assert.False(item.PictogramOptions.Single(o => o.Value == GhsPictogram.Toxic).IsSelected);
|
||||
Assert.False(item.IsResearching);
|
||||
Assert.Equal("", item.ResearchError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Research_BeiFehler_SetztResearchErrorUndBehaeltAlteFelderUnveraendert()
|
||||
{
|
||||
var item = new HazardSubstanceEditItem { Name = "Unbekannt", HStatements = "H999" };
|
||||
item.OnResearch = _ => throw new AiBackendException("Nicht genügend KI-Guthaben. Bitte Guthaben aufladen.");
|
||||
|
||||
await item.ResearchCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.Equal("Nicht genügend KI-Guthaben. Bitte Guthaben aufladen.", item.ResearchError);
|
||||
Assert.Equal("H999", item.HStatements);
|
||||
Assert.False(item.IsResearching);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ExperimentKindDisplayTests
|
||||
|
||||
@@ -162,8 +162,9 @@ public sealed class PdfExportServiceTests
|
||||
"Natrium in Wasser", "10c", "12.09.2026", "Lehrerversuch",
|
||||
"Ein kleines Stück Natrium wird in eine Schale mit Wasser gegeben.",
|
||||
[
|
||||
new HazardSubstancePrintRow("Natrium", "ca. 0,5 g", "GHS02, GHS05",
|
||||
"H260 - Reagiert mit Wasser unter Bildung entzündbarer Gase", "P223, P231+P232, P370+P378"),
|
||||
new HazardSubstancePrintRow("Natrium", "7440-23-5", "ca. 0,5 g", "GHS02, GHS05", "Gefahr",
|
||||
"H260 - Reagiert mit Wasser unter Bildung entzündbarer Gase", "P223, P231+P232, P370+P378",
|
||||
"Abgabe an unter 18-Jährige verboten"),
|
||||
],
|
||||
["Wasserstoffbildung, Verpuffungsgefahr", "Verätzungsgefahr durch Natronlauge"],
|
||||
["Schutzbrille", "Sicherheitsabstand einhalten", "Abzug/Freiluftversuch"],
|
||||
|
||||
Reference in New Issue
Block a user