feat(sim): F4.6f1 what a run leaves goes back into the document

The oracle SaveAfterRunRun saves Java's project after a run. The room writes
what a run leaves that Java keeps - files, running servers, virtual hosts,
mail servers' domains and accounts, mail programs' accounts and folders,
firewalls, DHCP clients' addresses - into the document as origin 'sim', at
most once a second, after each action and at the stop; writeRunState writes
only what differs. The command line now goes on in a folder made before a
restart, as Java's does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 17:05:11 +00:00
co-authored by Claude Opus 5.5
parent 11f13bca84
commit 3d6655e736
15 changed files with 705 additions and 22 deletions
+149
View File
@@ -0,0 +1,149 @@
// What a run leaves in FILIUS' project: an example opened and started as
// FILIUS does (ScenarioNetwork.fromFile), a story played through the
// programs as their windows call them, the simulation stopped as the design
// mode stops it (GUIMainMenu.stopSimulation: every node's beenden) and the
// project saved (SzenarioVerwaltung.speichern; Java saves only in the design
// mode). The reference for the room's write-back into the document
// (packages/sim/test/writeBack.test.ts).
//
// SaveAfterRunRun <file.fls> <story> <out.fls>
//
// email email_komplett, with FILIUS' command line installed on Rechner 1
// before the start: Rechner 1 and 2 set their accounts (as typed
// into the program's dialog), Rechner 1 types "mkdir ordner" and
// "touch ordner/notiz.txt", writes to rechner2@filius.de; Rechner 2
// fetches; Mail-Server (filius.de) gets the account "neu"; the
// Web-Server is switched off, its virtual hosts on with the row
// a.de → ordner; Mail-Server (senior.de) is switched off and its
// domain set to senior.org
// dhcp einfaches_rechnernetz_komplett: the notebooks get their
// addresses from the server (10 s)
import filius.gui.GUIContainer;
import filius.gui.netzwerksicht.GUIKnotenItem;
import filius.hardware.knoten.Knoten;
import filius.rahmenprogramm.SzenarioVerwaltung;
import filius.software.email.Email;
import filius.software.email.EmailAnwendung;
import filius.software.email.EmailKonto;
import filius.software.email.EmailServer;
import filius.software.email.EmailUtils;
import filius.software.lokal.Terminal;
import filius.software.system.Betriebssystem;
import filius.software.system.InternetKnotenBetriebssystem;
import filius.software.www.WebServer;
import java.util.Arrays;
import java.util.StringTokenizer;
public class SaveAfterRunRun {
static ScenarioNetwork network;
static InternetKnotenBetriebssystem system(String name) {
Knoten knoten = network.nodes.get(name);
if (knoten == null) throw new IllegalStateException("no node " + name);
return (InternetKnotenBetriebssystem) knoten.getSystemSoftware();
}
/** GUIApplicationTerminalWindow on Enter: the line handed to the program. */
static void type(Terminal terminal, String line) throws Exception {
StringTokenizer tokens = new StringTokenizer(line, " ");
String command = tokens.nextToken();
String[] parameters = new String[3 + tokens.countTokens()];
Arrays.fill(parameters, "");
for (int index = 0; tokens.hasMoreTokens(); index++) parameters[index] = tokens.nextToken();
terminal.terminalEingabeAuswerten(command, parameters);
Thread.sleep(500);
}
/**
* The account as one types it into the program's dialog and saves it
* (kontoSpeichern: setzeKonto, speichern): the file keeps it only in the
* older kontoListe, which FILIUS 2.14 no longer reads.
*/
static EmailKonto account(EmailAnwendung program, String user, String server, String domain, String lastName) {
EmailKonto account = new EmailKonto();
account.setVorname("Rechner");
account.setNachname(lastName);
account.setBenutzername(user);
account.setPasswort(user);
account.setPop3port("110");
account.setPop3server(server);
account.setSmtpport("25");
account.setSmtpserver(server);
account.setEmailAdresse(user + "@" + domain);
program.setzeKonto(account);
program.speichern();
return account;
}
public static void main(String[] args) throws Exception {
try {
run(args);
} catch (Throwable error) {
error.printStackTrace();
System.exit(1);
}
System.exit(0);
}
static void run(String[] args) throws Exception {
network = ScenarioNetwork.fromFile(args[0]);
String story = args[1];
if (story.equals("email")) {
((Betriebssystem) system("Rechner 1")).installAndStartAppIfAvailable("filius.software.lokal.Terminal");
}
network.start();
Thread.sleep(2000);
switch (story) {
case "email": {
Terminal terminal = (Terminal) system("Rechner 1").holeSoftware("filius.software.lokal.Terminal");
type(terminal, "mkdir ordner");
type(terminal, "touch ordner/notiz.txt");
EmailAnwendung one = (EmailAnwendung) system("Rechner 1").holeSoftware("filius.software.email.EmailAnwendung");
EmailKonto account = account(one, "rechner1", "141.99.50.232", "filius.de", "1");
Email mail = new Email();
mail.setAbsender(account.getVorname() + (!account.getNachname().isEmpty() ? (" " + account.getNachname()) : "") + " <" + account.getEmailAdresse() + ">");
mail.setEmpfaenger(EmailUtils.stringToAddressEntryList("rechner2@filius.de"));
mail.setCc(EmailUtils.stringToAddressEntryList(""));
mail.setBcc(EmailUtils.stringToAddressEntryList(""));
mail.setBetreff("Nach dem Lauf");
mail.setText("Erste Zeile\nZweite Zeile");
one.versendeEmail(account.getSmtpserver(), mail, account.getEmailAdresse());
Thread.sleep(8000);
EmailAnwendung two = (EmailAnwendung) system("Rechner 2").holeSoftware("filius.software.email.EmailAnwendung");
EmailKonto other = account(two, "rechner2", "141.99.50.232", "filius.de", "2");
two.emailsAbholenEmails(other.getBenutzername(), other.getPasswort(), other.getPop3port(), other.getPop3server());
Thread.sleep(8000);
((EmailServer) system("Mail-Server (filius.de)").holeSoftware("filius.software.email.EmailServer")).benutzerHinzufuegen("neu", "pw", "Nachname", "Vorname");
WebServer web = (WebServer) system("Web-Server").holeSoftware("filius.software.www.WebServer");
web.setAktiv(false);
web.setUseVHost(true);
web.changeVHostTable(0, 0, "a.de");
web.changeVHostTable(0, 1, "ordner");
EmailServer senior = (EmailServer) system("Mail-Server (senior.de)").holeSoftware("filius.software.email.EmailServer");
senior.setAktiv(false);
senior.setMailDomain("senior.org");
Thread.sleep(1000);
break;
}
case "dhcp":
Thread.sleep(10000);
break;
default:
throw new IllegalArgumentException("unknown story " + story);
}
// GUIMainMenu.stopSimulation, then the design mode's save.
for (GUIKnotenItem item : GUIContainer.getGUIContainer().getKnotenItems()) {
try {
item.getKnoten().getSystemSoftware().beenden();
} catch (Exception error) {}
}
Thread.sleep(1000);
GUIContainer gui = GUIContainer.getGUIContainer();
if (!SzenarioVerwaltung.getInstance().speichern(args[2], gui.getKnotenItems(), gui.getCableItems(), gui.getDocuItems())) {
throw new IllegalStateException("FILIUS could not save " + args[2]);
}
System.out.println("saved after the run: " + story);
}
}