Compare commits
9 Commits
Uebungstes
...
master
Author | SHA1 | Date | |
---|---|---|---|
708515ee4f
|
|||
a951b5c14a
|
|||
150eb7aa49
|
|||
ac40ada302
|
|||
cfba0106a9
|
|||
8f6320e069 | |||
d718ba90e3 | |||
eab0db8e40 | |||
406c9b02f7 |
@ -10,32 +10,32 @@ Diese Aufgabenstellung ist ein vollständiges IntelliJ-Projekt, das Sie bereits
|
||||
|
||||
- Einstellen des _Project SDK_: Öffnen Sie dazu in IntelliJ die Projekteinstellungen (_File_ -> _Project Structure..._) und wählen Sie ein JDK unter _Project | Project SDK_ aus.
|
||||
|
||||
## Thema
|
||||
Das allgemeine Thema dieses und der kommenden Aufgabenblätter ist der Weltraum und die Simulation der physikalischen Gesetze, die für Himmelskörper gelten. Obwohl ein möglichst exaktes physikalisches Modell wünschenswert ist, ist bei der Implementierung die Genauigkeit der physikalischen Modelle sekundär. Konzeptuelle Fehler bei den physikalischen Berechnungen spielen keine Rolle bei der Bewertung. Schwerpunkt sind die Konzepte der Programmiersprache.
|
||||
## Thema
|
||||
Das allgemeine Thema dieses und der kommenden Aufgabenblätter ist der Weltraum und die Simulation der physikalischen Gesetze, die für Himmelskörper gelten. Obwohl ein möglichst exaktes physikalisches Modell wünschenswert ist, ist bei der Implementierung die Genauigkeit der physikalischen Modelle sekundär. Konzeptuelle Fehler bei den physikalischen Berechnungen spielen keine Rolle bei der Bewertung. Schwerpunkt sind die Konzepte der Programmiersprache.
|
||||
|
||||
## Ziel
|
||||
Ziel der Aufgabe ist die Anwendung der Konzepte: Objekt- vs. Klassenmethode, Datensatz, Data Hiding, Konstruktoren (siehe Skriptum Seiten 31-50).
|
||||
|
||||
## Aufgaben
|
||||
1. Lesen Sie sich die Kommentare in den Dateien durch und führen Sie die Klasse `Simulation` aus.
|
||||
2. Data hiding:
|
||||
1. Lesen Sie sich die Kommentare in den Dateien durch und führen Sie die Klasse `Simulation` aus.
|
||||
2. Data hiding:
|
||||
1. Machen Sie in den Klassen `Vector3` und `Body` alle Objektvariablen `private`.
|
||||
2. Definieren Sie entsprechende Konstruktoren, um die Objektvariablen zu initialisieren. `Simulation` soll nur noch diese nutzen und nicht mehr direkt auf die Objektvariablen zugreifen dürfen. Testen Sie zunächst die vervollständigten Klassen `Vector3` und `Body` mit der Klasse `Aufgabe1Test`. Entfernen Sie dazu die Kommentarzeichen in der Klassendefinition.
|
||||
3. Datenkapselung: Anstelle der gegebenen statischen Methoden in der Datei `Simulation.java` sollen nur noch entsprechende Objektmethoden der Klassen `Body` und `Vector3` benutzt werden. (Ausnahme ist die Methode `main`. Die statischen Methoden der Klasse `SpaceDraw` müssen auch nicht verändert werden.) Implementieren Sie dazu die spezifizierten Methoden und bauen Sie `Simulation` so um, dass anstelle der Aufrufe statischer Methoden Objektmethoden genutzt werden. Sie sollen alle in `Body` und `Vector3` spezifizierten Methoden implementieren, auch wenn nicht alle von `Simulation` genutzt werden. Die in `Simulation.java` gegebenen statischen Methoden können dann entfernt werden (natürlich bis auf die erwähnten Ausnahmen). Nutzen Sie die implementierten Methoden auch in `Simulation.java`, um die Himmelskörper zu bewegen und zu zeichnen.
|
||||
3. Datenkapselung: Anstelle der gegebenen statischen Methoden in der Datei `Simulation.java` sollen nur noch entsprechende Objektmethoden der Klassen `Body` und `Vector3` benutzt werden. (Ausnahme ist die Methode `main`. Die statischen Methoden der Klasse `SpaceDraw` müssen auch nicht verändert werden.) Implementieren Sie dazu die spezifizierten Methoden und bauen Sie `Simulation` so um, dass anstelle der Aufrufe statischer Methoden Objektmethoden genutzt werden. Sie sollen alle in `Body` und `Vector3` spezifizierten Methoden implementieren, auch wenn nicht alle von `Simulation` genutzt werden. Die in `Simulation.java` gegebenen statischen Methoden können dann entfernt werden (natürlich bis auf die erwähnten Ausnahmen). Nutzen Sie die implementierten Methoden auch in `Simulation.java`, um die Himmelskörper zu bewegen und zu zeichnen.
|
||||
|
||||
## Zusatzfragen
|
||||
Beantworten Sie folgende Zusatzfragen als Kommentar in `Simulation.java`:
|
||||
|
||||
1. Was versteht man unter _Datenkapselung_? Geben Sie ein Beispiel, wo dieses Konzept in dieser Aufgabenstellung angewendet wird.
|
||||
1. Was versteht man unter _Datenkapselung_? Geben Sie ein Beispiel, wo dieses Konzept in dieser Aufgabenstellung angewendet wird.
|
||||
2. Was versteht man unter _Data Hiding_? Geben Sie ein Beispiel, wo dieses Konzept in dieser Aufgabenstellung angewendet wird.
|
||||
3. Was steht bei einem Methodenaufruf links vom `.` (z.B. bei `SpaceDraw.massToColor(1e30)` oder
|
||||
3. Was steht bei einem Methodenaufruf links vom `.` (z.B. bei `SpaceDraw.massToColor(1e30)` oder
|
||||
`body.radius()`)? Woran erkennt man dabei Objektmethoden?
|
||||
|
||||
### Denkanstöße (ohne Bewertung)
|
||||
Folgende Fragen sind als Denkanstöße gedacht und bilden die Grundlage für eine Diskussion in der Übungseinheit zu diesem Aufgabenblatt.
|
||||
|
||||
1. Welche anderen oder weiteren Objektmethoden hätten Sie zur Verfügung gestellt, wenn es keine Vorgaben gegeben hätte?
|
||||
2. Wann wäre es sinnvoll, die Klasse `SpaceDraw` so zu ändern, dass diese ebenfalls Objektmethoden
|
||||
2. Wann wäre es sinnvoll, die Klasse `SpaceDraw` so zu ändern, dass diese ebenfalls Objektmethoden
|
||||
zur Verfügung stellt?
|
||||
|
||||
#### _Punkteaufteilung_
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Aufgabenblatt 2
|
||||
|
||||
## Allgemeine Anmerkungen
|
||||
Ihre Lösung für dieses Aufgabenblatt ist bis Montag, 28.3. 11h durch `git commit` und `push`
|
||||
Ihre Lösung für dieses Aufgabenblatt ist bis Montag, 28.3. 11h durch `git commit` und `push`
|
||||
abzugeben. Mit der Angabe werden folgende Dateien mitgeliefert: `BodyQueue.java`, `BodyForceMap.java` und `Aufgabe2Test.java`. Diese Klassen dürfen nur an den Stellen verändert werden, die mit `TODO` markiert sind. Zusätzliche Klassen, Interfaces, Methoden und Variablen dürfen aber eingefügt werden. Wenn Sie zusätzlich zu den gefragten Klassen, weitere Klassen definieren, achten Sie darauf, dass die Klassennamen mit `My` beginnen, um Konflikte mit späteren Aufgabenblättern zu vermeiden.
|
||||
|
||||
## Ziel
|
||||
@ -10,10 +10,10 @@ Ziel der Aufgabe ist die Implementierung einer linearen und einer assoziativen D
|
||||
## Beschreibung der gegebenen Dateien
|
||||
- `BodyQueue` ist das Gerüst für eine Implementierung einer linearen Datenstruktur zur Verwaltung
|
||||
von Objekten des Typs `Body`.
|
||||
- `BodyForceMap` ist das Gerüst für eine Implementierung einer assoziativen Datenstruktur, die
|
||||
- `BodyForceMap` ist das Gerüst für eine Implementierung einer assoziativen Datenstruktur, die
|
||||
einen Himmelskörper mit der auf ihn wirkenden Kraft assoziiert.
|
||||
- `Aufgabe2Test` ist eine vorgegebene Klasse, die Sie zum Testen Ihrer Implementierung verwenden
|
||||
sollten. Bei einer fehlerfreien Implementierung sollten bei der Ausführung dieser Klasse keine Exceptions geworfen werden und alle Tests als erfolgreich ("successful") ausgegeben werden. Sie müssen diese Klasse nicht verändern, können aber eigene Testfälle hinzufügen.
|
||||
- `Aufgabe2Test` ist eine vorgegebene Klasse, die Sie zum Testen Ihrer Implementierung verwenden
|
||||
sollten. Bei einer fehlerfreien Implementierung sollten bei der Ausführung dieser Klasse keine Exceptions geworfen werden und alle Tests als erfolgreich ("successful") ausgegeben werden. Sie müssen diese Klasse nicht verändern, können aber eigene Testfälle hinzufügen.
|
||||
|
||||
## Aufgaben
|
||||
|
||||
@ -27,10 +27,10 @@ Ihre Aufgaben sind folgende:
|
||||
Body[] keys; // assume descending order according to mass
|
||||
Body toInsert;
|
||||
...
|
||||
|
||||
|
||||
int left = 0;
|
||||
int right = size - 1;
|
||||
|
||||
|
||||
while (left <= right) {
|
||||
int middle = left + ((right - left) / 2);
|
||||
if (keys[middle].mass() < toInsert.mass()) {
|
||||
@ -39,14 +39,14 @@ Ihre Aufgaben sind folgende:
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// index where to insert: right + 1
|
||||
```
|
||||
4. Bauen Sie die bereits bestehende Klasse `Simulation` so um, dass keine Kollisionen von Himmelskörpern mehr berücksichtigt werden. Dadurch soll der Programmcode vereinfacht werden. Die Anzahl der Himmelskörper ändert sich im Laufe der Simulation somit nicht. Testen Sie die Simulation.
|
||||
5. Ändern Sie nun die Klasse `Simulation` so, dass zur Verwaltung der Himmelskörper anstelle des Arrays Objekte der Klassen `BodyQueue` und `BodyForceMap` verwendet werden. Das heißt beispielsweise, dass die Zugriffe auf die Himmelskörper der Simulation über Methoden von `BodyQueue` erfolgen müssen. Anstelle des Arrays `forceOnBody` soll ein Objekt des Typs `BodyForceMap` benutzt werden.
|
||||
5. Ändern Sie nun die Klasse `Simulation` so, dass zur Verwaltung der Himmelskörper anstelle des Arrays Objekte der Klassen `BodyQueue` und `BodyForceMap` verwendet werden. Das heißt beispielsweise, dass die Zugriffe auf die Himmelskörper der Simulation über Methoden von `BodyQueue` erfolgen müssen. Anstelle des Arrays `forceOnBody` soll ein Objekt des Typs `BodyForceMap` benutzt werden.
|
||||
6. Testen Sie die Simulation wieder. Das Verhalten der Simulation sollte unverändert sein. Je nach Implementierung der Klassen `BodyQueue` und `BodyForceMap` ist es möglich (und kein Problem), dass die Simulation jetzt langsamer läuft, als nach dem Umbau in Schritt 4.
|
||||
7. (Freiwillige Zusatzaufgabe ohne Bewertung:) Testen Sie die Simulation mit den folgenden fünf
|
||||
Himmelskörpern:
|
||||
7. (Freiwillige Zusatzaufgabe ohne Bewertung:) Testen Sie die Simulation mit den folgenden fünf
|
||||
Himmelskörpern:
|
||||
```
|
||||
Body sun = new Body(1.989e30,new Vector3(0,0,0),new Vector3(0,0,0));
|
||||
Body earth = new Body(5.972e24,new Vector3(-1.394555e11,5.103346e10,0),new Vector3(-10308.53,-28169.38,0));
|
||||
@ -60,4 +60,4 @@ Himmelskörpern:
|
||||
- Implementierung von `BodyQueue`: 2 Punkte
|
||||
- Implementierung von `BodyForceMap`: 2 Punkte
|
||||
- Anpassung von `Simulation`: 1 Punkt
|
||||
- Gesamt: 5 Punkte
|
||||
- Gesamt: 5 Punkte
|
||||
|
@ -2,15 +2,15 @@
|
||||
|
||||
## Allgemeine Anmerkungen
|
||||
Ihre Lösung für dieses Aufgabenblatt ist bis Montag, 2.5. 11h durch `git commit` und `push`
|
||||
abzugeben. Mit der Angabe werden die Dateien `CosmicSystem.java`, `Drawable.java`,
|
||||
`NamedBodyForcePair.java`, `HierarchicalSystem.java`, `Simulation4.java` und `Aufgabe4Test.java`
|
||||
abzugeben. Mit der Angabe werden die Dateien `CosmicSystem.java`, `Drawable.java`,
|
||||
`NamedBodyForcePair.java`, `HierarchicalSystem.java`, `Simulation4.java` und `Aufgabe4Test.java`
|
||||
mitgeliefert.
|
||||
|
||||
Wenn Sie zusätzlich zu den gefragten Klassen weitere Klassen definieren, achten Sie darauf, dass
|
||||
die Klassennamen mit `My` beginnen, um Konflikte mit späteren Aufgabenblättern zu vermeiden.
|
||||
|
||||
## Ziel
|
||||
Ziel der Aufgabe ist die Anwendung der Konzepte: Interfaces, dynamisches Binden, toString()
|
||||
Ziel der Aufgabe ist die Anwendung der Konzepte: Interfaces, dynamisches Binden, toString()
|
||||
(siehe Skriptum Seite 75-84).
|
||||
|
||||
## Beschreibung der gegebenen Dateien
|
||||
@ -20,7 +20,7 @@ Ziel der Aufgabe ist die Anwendung der Konzepte: Interfaces, dynamisches Binden,
|
||||
Hierarchie von Systemen und Subsystemen beschreiben. Unser Sonnensystem ist ein Beispiel eines Systems,
|
||||
das mehrere Teilsysteme beinhaltet. Ein solches Teilsystem ist beispielsweise das System Erde und Erdmond.
|
||||
Ein anderes Teilsystem wäre Jupiter mit seinen Monden. Verändern Sie dieses Interface nicht.
|
||||
- [Drawable](../src/Drawable.java) wird von `CosmicSystem` verwendet. Verändern Sie dieses Interface
|
||||
- [Drawable](../src/Drawable.java) wird von `CosmicSystem` verwendet. Verändern Sie dieses Interface
|
||||
nicht.
|
||||
- [NamedBodyForcePair](../src/NamedBodyForcePair.java) ist das Gerüst für eine Klassendefinition.
|
||||
Die Klasse implementiert `CosmicSystem` und repräsentiert einen einzelnen benannten Himmelskörper
|
||||
@ -34,8 +34,8 @@ die Simulation analog zur Klasse `Simulation` implementiert werden (damit Sie Ih
|
||||
Datei](../src/Simulation.java) nicht überschreiben müssen).
|
||||
- [Aufgabe4Test](../src/Aufgabe4Test.java) ist eine vorgegebene Klasse, die Sie zum Testen Ihrer
|
||||
Implementierung verwenden sollten. Bei einer fehlerfreien Implementierung sollten bei der
|
||||
Ausführung dieser Klasse keine Exceptions geworfen werden und alle Tests als erfolgreich ("successful")
|
||||
ausgegeben werden. Entfernen Sie die Kommentarzeichen, um diese Klasse verwenden zu können. Sie
|
||||
Ausführung dieser Klasse keine Exceptions geworfen werden und alle Tests als erfolgreich ("successful")
|
||||
ausgegeben werden. Entfernen Sie die Kommentarzeichen, um diese Klasse verwenden zu können. Sie
|
||||
müssen diese Klasse nicht weiter verändern, können aber eigene Testfälle hinzufügen.
|
||||
|
||||
## Aufgaben
|
||||
@ -45,7 +45,7 @@ Ihre Aufgaben sind folgende:
|
||||
**1. Implementierung von `CosmicSystem` in `NamedBodyForcePair`:**
|
||||
Fügen Sie in der Klasse `Body` eine öffentliche Methode `massCenter()` hinzu, die die
|
||||
Position des Himmelskörpers liefert.
|
||||
Definieren Sie die Klasse `NamedBodyForcePair` so, dass sie das Interface `CosmicSystem`
|
||||
Definieren Sie die Klasse `NamedBodyForcePair` so, dass sie das Interface `CosmicSystem`
|
||||
implementiert. Die Methoden `getMass()` und `getMassCenter()` geben lediglich die Masse bzw.
|
||||
Position des Himmelskörpers zurück.
|
||||
|
||||
@ -84,14 +84,14 @@ Kraft, indem alle Kräfte die von Körpern aus `this` auf das `NamedBodyForcePai
|
||||
ausgeübt werden, zur Kraft im Objekt hinzuaddiert werden. Beispiel: Die
|
||||
Anweisung `cs.addForce(cs)` aktualisiert alle wechselseitigen im System `cs` wirkenden Kräfte.
|
||||
|
||||
- `update()` führt auf Basis der gespeicherten Kräfte alle Bewegungen im System `this` durch und
|
||||
- `update()` führt auf Basis der gespeicherten Kräfte alle Bewegungen im System `this` durch und
|
||||
setzt danach alle Kräfte wieder auf den null-Vektor zurück.
|
||||
|
||||
- `getBodies()` liefert eine Liste (Typ: `BodyLinkedList`) mit allen Himmelskörpern aus `this`.
|
||||
|
||||
**3. Implementierung von `Simulation4`:**
|
||||
|
||||
Implementieren Sie die Simulationsschleife unter Verwendung eines Objekts vom Typ
|
||||
Implementieren Sie die Simulationsschleife unter Verwendung eines Objekts vom Typ
|
||||
`HierachicalSystem`. Alle Berechnungen sollen mittels Methoden von `CosmicSystem` durchgeführt
|
||||
werden.
|
||||
|
||||
@ -110,7 +110,7 @@ die einzelnen Körper in `cs` dadurch erreicht werden, dass `this` für alle sei
|
||||
und Untersysteme `addForceTo(cs)` aufruft. Wird beim rekursiven Abstieg ein einzelner Himmelskörper
|
||||
erreicht (Blattknoten) ruft dieser `cs.addForceFrom(this)` auf.
|
||||
|
||||
- Achten Sie bei der Berechnung der Kräfte in `addForceFrom(Body b)` darauf, dass die Kraft nicht
|
||||
- Achten Sie bei der Berechnung der Kräfte in `addForceFrom(Body b)` darauf, dass die Kraft nicht
|
||||
verändert wird, wenn `this` und `b` derselbe Himmelskörper sind.
|
||||
|
||||
#### _Punkteaufteilung_
|
||||
|
@ -58,7 +58,7 @@ Ihre Aufgaben sind folgende:
|
||||
**3. Vervollständigen von `MassiveLinkedList`:**
|
||||
|
||||
Definieren Sie `MassiveLinkedList`. Die Klasse ist wie `BodyLinkedList` aufgebaut, mit dem
|
||||
Unterschied, dass der Elementtyp statt `Body` nun der Typ `Massive` ist. Die Methode `indexOf`
|
||||
Unterschied, dass der Elementtyp statt `Body` nun der Typ `Massive` ist. Die Methode `indexOf`
|
||||
vergleicht Objekte mittels `equals`.
|
||||
|
||||
**4. Implementierung von `MassiveForceHashMap`:**
|
||||
@ -98,5 +98,5 @@ Ihre Aufgaben sind folgende:
|
||||
- Implementierung von `MassiveForceHashMap`: 2 Punkte
|
||||
- Implementierung von `MassiveLinkedList`: 0.5 Punkte
|
||||
- Implementierung von `Simulation5`: 1 Punkte
|
||||
|
||||
|
||||
- Gesamt: 5 Punkte
|
||||
|
@ -3,8 +3,8 @@
|
||||
## Allgemeine Anmerkungen
|
||||
|
||||
Ihre Lösung für dieses Aufgabenblatt ist bis Montag, 23.5. 11h durch `git commit` und `git push`
|
||||
abzugeben. Mit der Angabe werden die Dateien `MassiveIterable.java`, `MassiveIterator.java`,
|
||||
`MassiveSet.java`, `MassiveForceTreeMap.java`, `Simulation6.java` und `Aufgabe6Test.java`
|
||||
abzugeben. Mit der Angabe werden die Dateien `MassiveIterable.java`, `MassiveIterator.java`,
|
||||
`MassiveSet.java`, `MassiveForceTreeMap.java`, `Simulation6.java` und `Aufgabe6Test.java`
|
||||
mitgeliefert.
|
||||
|
||||
Wenn Sie zusätzlich zu den gefragten Klassen weitere Klassen definieren, achten Sie darauf, dass
|
||||
@ -21,7 +21,7 @@ Ziel der Aufgabe ist die Anwendung der Konzepte: Iterator, Kopie vs. Sichtweise,
|
||||
Elementen vom Typ `Massive` spezifiziert. Verändern Sie diese Datei bitte nicht.
|
||||
- [MassiveIterator](../src/MassiveIterator.java) ist ein Interface, das einen Iterator über
|
||||
Elemente vom Typ `Massive` spezifiziert. Verändern Sie diese Datei bitte nicht.
|
||||
- [MassiveSet](../src/MassiveSet.java) ist ein Interface, das iterierbare Mengen mit
|
||||
- [MassiveSet](../src/MassiveSet.java) ist ein Interface, das iterierbare Mengen mit
|
||||
`Massive`-Elementen spezifiziert. Verändern Sie diese Datei bitte nicht.
|
||||
- [MassiveForceTreeMap](../src/MassiveForceTreeMap.java) ist das Gerüst für eine Implementierung
|
||||
einer assoziativen Datenstruktur, die ein `Massive`-Objekt mit der auf das Objekt wirkenden Kraft
|
||||
@ -41,25 +41,25 @@ Ihre Aufgaben sind folgende:
|
||||
|
||||
**1. Implementieren Sie die Klasse `MassiveForceTreeMap`.**
|
||||
|
||||
Implementieren Sie die Klasse `MassiveForceTreeMap`. `MassiveForceTreeMap` ist wie
|
||||
`BodyForceTreeMap` aufgebaut, mit dem Unterschied, dass der Typ des Schlüssels statt `Body` nun
|
||||
der Typ `Massive` ist. Weiters soll die Klasse Methode `getKeys()` zur Verfügung stellen,
|
||||
die eine `MassiveSet`-Sichtweise auf die Menge der Schlüssel liefert. Änderungen an dem
|
||||
zurückgelieferten `MassiveSet`-Objekt wirken sich auf das zugrunde
|
||||
liegende `MassiveForceTreeMap`-Objekt aus. Die Methode `toList()` liefert dagegen eine
|
||||
unabhängige Liste (Kopie) mit allen Schlüsseln der Map. Für die Implementierung von
|
||||
`MassiveSet` können Sie einen eigenen Klassennamen beginnend mit `My` wählen. Die Definition kann
|
||||
Implementieren Sie die Klasse `MassiveForceTreeMap`. `MassiveForceTreeMap` ist wie
|
||||
`BodyForceTreeMap` aufgebaut, mit dem Unterschied, dass der Typ des Schlüssels statt `Body` nun
|
||||
der Typ `Massive` ist. Weiters soll die Klasse Methode `getKeys()` zur Verfügung stellen,
|
||||
die eine `MassiveSet`-Sichtweise auf die Menge der Schlüssel liefert. Änderungen an dem
|
||||
zurückgelieferten `MassiveSet`-Objekt wirken sich auf das zugrunde
|
||||
liegende `MassiveForceTreeMap`-Objekt aus. Die Methode `toList()` liefert dagegen eine
|
||||
unabhängige Liste (Kopie) mit allen Schlüsseln der Map. Für die Implementierung von
|
||||
`MassiveSet` können Sie einen eigenen Klassennamen beginnend mit `My` wählen. Die Definition kann
|
||||
in einer eigenen Datei oder in der Datei `MassiveForceTreeMap.java` erfolgen.
|
||||
|
||||
|
||||
**2. Adaptieren Sie die Klasse `HierarchicalSystem`:**
|
||||
|
||||
Die Klasse `HierarchicalSystem` soll so geändert werden, dass sie das gegebene
|
||||
Interface `MassiveIterable` implementiert. Die Reihenfolge der vom Iterator gelieferten
|
||||
Elemente ist nicht festgelegt. Sie dürfen für die Implementierung bei Bedarf Ihren Klassen
|
||||
Die Klasse `HierarchicalSystem` soll so geändert werden, dass sie das gegebene
|
||||
Interface `MassiveIterable` implementiert. Die Reihenfolge der vom Iterator gelieferten
|
||||
Elemente ist nicht festgelegt. Sie dürfen für die Implementierung bei Bedarf Ihren Klassen
|
||||
`NamedBodyForcePair` und `HierarchicalSystem` neue, nicht angegebene Methoden hinzufügen.
|
||||
Die Verwendung von Klassen des Java-Collection-Frameworks (z.B. java.util.Stack) ist erlaubt
|
||||
(aber nicht notwendig).
|
||||
|
||||
|
||||
**3. Implementierung von `Simulation6`:**
|
||||
|
||||
Implementieren Sie die Simulationsschleife unter Verwendung eines Objekts vom Typ
|
||||
@ -71,5 +71,5 @@ Ihre Aufgaben sind folgende:
|
||||
- Implementierung von `MassiveForceTreeMap`: 3 Punkte
|
||||
- Implementierung von `MassiveIterable` in `HierarchicalSystem`: 1.5 Punkte
|
||||
- Implementierung von `Simulation6`: 0.5 Punkte
|
||||
|
||||
|
||||
- Gesamt: 5 Punkte
|
||||
|
152
angabe/Aufgabenblatt8.md
Normal file
152
angabe/Aufgabenblatt8.md
Normal file
@ -0,0 +1,152 @@
|
||||
# Aufgabenblatt 8
|
||||
|
||||
## Allgemeine Anmerkungen
|
||||
Ihre Lösung für dieses Aufgabenblatt ist bis Montag, 13.6., 11h durch `git commit` und `git push`
|
||||
abzugeben.
|
||||
Wenn Sie zusätzlich zu den gefragten Klassen und Interfaces weitere Klassen oder
|
||||
Interfaces definieren, achten Sie darauf, dass die Klassennamen mit `My` beginnen, um Konflikte
|
||||
mit späteren Aufgabenblättern zu vermeiden.
|
||||
|
||||
Weiters werden die Dateien `StateFileNotFoundException.java`,
|
||||
`StateFileFormatException.java`, `ReadDataUtil.java`, `Simulation8.java`, `Simulation9.java`,
|
||||
`Aufgabe8Test.java` und das Verzeichnis `states` mit `txt`-Dateien mitgeliefert.
|
||||
|
||||
## Ziel
|
||||
Ziel der Aufgabe ist das Verständnis und die Anwendung der Konzepte: Java-Collections, Eingabe mit
|
||||
Validierung, Exceptions (S. 110-123).
|
||||
|
||||
## Beschreibung der gegebenen Dateien
|
||||
|
||||
- [states](../states) ist ein Verzeichnis, in dem mehrere Dateien mit der Endung `.txt`
|
||||
mitgeliefert werden. Diese enthalten Daten von je einem Himmelskörper sowie dessen Positionen und
|
||||
Geschwindigkeitsvektoren für alle Tage der Jahre 2019-2021. Die Angaben sind wie gewohnt in
|
||||
kartesischen Koordinaten, wobei die Sonne den Ursprung des Koordinatensystems bildet und die
|
||||
Ekliptik die x-y-Ebene darstellt. Die Daten stammen von [https://ssd.jpl.nasa.gov/horizons.cgi#top](https://ssd.jpl.nasa.gov/horizons.cgi#top).
|
||||
|
||||
**ACHTUNG**: Die Werte sind in km bzw. km/sec angegeben!
|
||||
|
||||
- [StateFileNotFoundException](../src/StateFileNotFoundException.java) enthält die Definition
|
||||
der Klasse `StateFileNotFoundException`. Diese sollen Sie vervollständigen.
|
||||
- [StateFileFormatException](../src/StateFileFormatException.java) enthält die Definition
|
||||
der Klasse `StateFileFormatException`. Diese sollen Sie vervollständigen.
|
||||
- [ReadDataUtil](../src/ReadDataUtil.java) ist eine Klasse mit einer statischen Methode zum
|
||||
Einlesen von Position- und Bewegungsvektoren von Himmelskörpern aus Dateien.
|
||||
Diese sollen Sie vervollständigen.
|
||||
- [Simulation8](../src/Simulation8.java) ist ein Gerüst für eine ausführbare Klasse. Hier soll
|
||||
die Simulation analog zur Klasse `Simulation` implementiert werden (damit Sie Ihre [ursprüngliche
|
||||
Datei](../src/Simulation.java) nicht überschreiben müssen).
|
||||
- [Simulation9](../src/Simulation9.java) ist eine leere Datei. Hier soll eine weitere Simulation
|
||||
implementiert werden, die so wie `Simulation8` funktioniert, mit dem Unterschied, dass anstelle
|
||||
der selbst implementierten Datenstrukturen nur vorgefertigte Klassen aus dem
|
||||
Java-Collection-Framework benutzt werden sollen.
|
||||
- [Aufgabe8Test](../src/Aufgabe8Test.java) ist eine vorgegebene Klasse, die Sie zum Testen Ihrer
|
||||
Implementierung verwenden sollten. Bei einer fehlerfreien Implementierung sollten bei der
|
||||
Ausführung dieser Klasse keine Exceptions geworfen werden und alle Tests als erfolgreich ("successful")
|
||||
ausgegeben werden. Entfernen Sie die Kommentarzeichen, um diese Klasse verwenden zu können. Sie
|
||||
müssen diese Klasse nicht weiter verändern, können aber eigene Testfälle hinzufügen.
|
||||
|
||||
|
||||
## Aufgaben
|
||||
|
||||
1. Ändern Sie Ihre Implementierung, sodass ein `MassiveIterator` eine Exception
|
||||
vom Typ `java.util.NoSuchElementException` wirft, falls `next()` aufgerufen wird,
|
||||
jedoch der Iterator keine weitere Iteration hat (`hasNext()` liefert `false`).
|
||||
|
||||
2. Ändern Sie den Iterator von der von `getKeys()` zurückgelieferten
|
||||
Sichtweise auf `MassiveForceTreeMap` so, dass `remove()` überschrieben wird
|
||||
([siehe API Dokumentation](https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html#remove--)),
|
||||
sodass der Iterator Einträge in Objekten von `MassiveForceTreeMap` löschen kann. Achten Sie
|
||||
darauf, dass hier in bestimmten Fällen eine `java.lang.IllegalStateException` geworfen werden
|
||||
soll. Der Iterator von `HierarchicalSystem` muss nicht geändert werden.
|
||||
|
||||
3. Validierung von Eingabedaten:
|
||||
- Implementieren Sie in der Klasse `ReadDataUtil.java` die Methode `readConfiguration`.
|
||||
Es soll ein gepufferter Stream zum Einlesen genutzt werden (siehe Skriptum Seite 128).
|
||||
Erstellen Sie zum Testen auch Varianten der txt-Dateien mit Formatfehlern.
|
||||
- Fügen Sie der Klasse `NamedBody` bei Bedarf
|
||||
eine Methode `setState(Vector3 position, Vector3 velocity)` zum Setzen der Position
|
||||
und des Geschwindigkeitsvektors des Himmelskörpers hinzu.
|
||||
- Definieren Sie die beiden angegebenen Exceptionklassen in den entsprechenden
|
||||
mitgelieferten Dateien.
|
||||
|
||||
4. Ausnahmebehandlung:
|
||||
In der Klasse `Simulation8` sollen nun die Himmelskörper mit Daten aus den gegebenen
|
||||
txt-Dateien initialisiert werden. Dabei sollen zumindest die Sonne sowie die
|
||||
inneren Planeten
|
||||
Merkur, Venus, Erde und Mars vorkommen. Sie können weitere Himmelskörper (siehe txt-Dateien)
|
||||
hinzufügen. Nutzen Sie die Klasse `MassiveForceTreeMap` und ihre Iteratoren, um die
|
||||
Himmelskörper der Simulation zu verwalten. (Kollisionen von Himmelskörpern müssen nicht
|
||||
berücksichtigt werden.)
|
||||
Ändern Sie die Klasse `Simulation8` so, dass sie zwei Kommandozeilenargumente verarbeitet.
|
||||
Das erste Argument ist ein String mit der Angabe des Pfades zum Verzeichnis, wo die
|
||||
entsprechenden txt-Dateien (z.B. `Venus.txt`,`Mercury.txt`,`Earth.txt`) mit den Konfigurationen
|
||||
der Himmelskörper zu finden sind. Die Dateien haben die Namen der Himmelskörper mit Endung `
|
||||
.txt`. Für die Sonne gibt es keine txt-Datei (es wird die Position (0,0,0) angenommen).
|
||||
Das zweite Argument ist ein String mit einer Datumsangabe der Form YYYY-MMM-DD, also z.B.
|
||||
2020-Dec-04, die den Tag der auszulesenden Position und Bewegungsvektor bestimmt. Die Klasse
|
||||
soll beim Auftreten von Problemen bei der Ausführung entsprechende Fehlermeldungen ausgeben und
|
||||
die Ausführung in bestimmten Fällen beenden. Beispiele für Aufrufe im Kommandozeileninterpreter
|
||||
mit entsprechenden Fehlermeldungen (Sie können zum Ausführen das Terminal in IntelliJ nutzen
|
||||
oder die Programmargumente unter `Edit Configurations` angeben):
|
||||
```
|
||||
$ javac Simulation8.java
|
||||
$ java Simulation8 ../states 2021-May-28
|
||||
Running simulation ...
|
||||
$ java Simulation8 ../states
|
||||
Error: wrong number of arguments.
|
||||
$ java Simulation8 ../states 2025-Dec-12
|
||||
Warning: State not available for Earth.
|
||||
Running simulation without Earth.
|
||||
Warning: State not available for Venus.
|
||||
Running simulation without Venus.
|
||||
...
|
||||
$ java Simulation8 ../states-altered 2021-May-28
|
||||
Warning: File ../states-altered/Venus.txt does not have required format.
|
||||
Running simulation without Venus.
|
||||
Warning: File ../states-altered/Mars.txt not found.
|
||||
Running simulation without Mars.
|
||||
Running simulation ...
|
||||
$ java Simulation8 ../states -17
|
||||
Error: State has wrong format (requires YYYY-MM-DD), aborting.
|
||||
$ java Simulation8 blah 2021-May-28
|
||||
Warning: File blah/Earth.txt not found.
|
||||
Running simulation without Earth.
|
||||
Warning: File blah/Venus.txt not found.
|
||||
Running simulation without Venus.
|
||||
...
|
||||
```
|
||||
|
||||
5. Kopieren Sie den Inhalt der Datei `Simulation8.java` in die Datei `Simulation9.java` und bauen
|
||||
Sie `Simulation9` so um, dass anstelle der selbst implementierten Datenstrukturen nur
|
||||
vorgefertigte Klassen aus dem Java-Collection-Framework benutzt werden.
|
||||
|
||||
6. Freiwillige Zusatzaufgabe (ohne Bewertung):
|
||||
Ändern Sie die Klasse `Simulation8` so um, dass ein drittes optionales Kommandozeilenargument
|
||||
verarbeitet werden kann. Dieses gibt an, wie viele Tage simuliert werden sollen. Beispielsweise
|
||||
kann eine zweite Datumsangabe möglich sein, oder die Anzahl an Tagen.
|
||||
Sobald dieser Zeitpunkt in der Simulation erreicht wurde, können die aktuellen Positionen der
|
||||
Himmelskörper mit den in den txt-Dateien angegebenen Positionen verglichen werden (z.B.
|
||||
durch erneutem Aufruf von `readConfiguration` und `draw`). Wie groß sind die Abweichungen
|
||||
der von NASA errechneten Positionen zu den Positionen, die Ihre Simulation liefert?
|
||||
|
||||
### Denkanstöße (ohne Bewertung)
|
||||
|
||||
1. Haben Sie die remove-Methode des Iterators so implementiert, dass der Aufruf keine
|
||||
zusätzliche Suche nach dem zu löschenden Eintrag benötigt?
|
||||
2. Wie verhalten sich die von der Methode `toList()` der Klasse `MassiveForceTreeMap`
|
||||
zurückgelieferten Listen, wenn deren enthaltene Himmelskörper durch `setState` verändert werden?
|
||||
Werden dadurch die Himmelskörper der ursprünglichen `MassiveForceTreeMap`-Objekte auch geändert?
|
||||
(Anmerkung: diesbezüglich gibt es im Aufgabenblatt 6 keine Vorgaben).
|
||||
3. Wie verhalten sich Ihre Iteratoren, wenn Objekte geändert werden?
|
||||
4. Wie kann man durch Einfügen von Zeichen `,` und newlines (`\n`) aus den `txt`-Dateien eine
|
||||
"fehlerhafte" Datei machen, die trotzdem von der Methode akzeptiert wird? Kann man solche Probleme
|
||||
verhindern?
|
||||
|
||||
#### _Punkteaufteilung_
|
||||
|
||||
- Änderung von `next()` von `MassiveIterator`: 0.5 Punkte
|
||||
- Implementierung der Methode `remove()` im Iterator der `MassiveSet`-Sichtweise
|
||||
von `MassiveForceTreeMap`: 2 Punkte
|
||||
- Implementierung der Exceptionklassen und Implementierung von `readConfiguration`
|
||||
in `ReadDataUtil`: 1.5 Punkte
|
||||
- Implementierung von `Simulation8` und `Simulation9`: 1 Punkt
|
@ -113,4 +113,21 @@ public class Aufgabe6Test {
|
||||
}
|
||||
assertEquals(12, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
NamedBody sun1, mercury1, venus1;
|
||||
sun1 = new NamedBody(SolSystem4.SUN_NAMED);
|
||||
mercury1 = new NamedBody(SolSystem4.MERCURY_NAMED);
|
||||
venus1 = new NamedBody(SolSystem4.VENUS_NAMED);
|
||||
|
||||
MassiveForceTreeMap map = new MassiveForceTreeMap();
|
||||
|
||||
map.put(sun1, new Vector3());
|
||||
map.put(mercury1, new Vector3());
|
||||
map.put(venus1, new Vector3());
|
||||
for (Massive m : map.getKeys().toList()) {
|
||||
System.out.println(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
50
src/Aufgabe8Test.java
Normal file
50
src/Aufgabe8Test.java
Normal file
@ -0,0 +1,50 @@
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class Aufgabe8Test {
|
||||
|
||||
@Test
|
||||
public void testEP2() {
|
||||
MassiveForceTreeMap map = new MassiveForceTreeMap();
|
||||
NamedBody mars;
|
||||
|
||||
map.put(new NamedBody("Oumuamua", 8e6, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Earth", 5.972E24, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Moon", 7.349E22, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(mars = new NamedBody("Mars", 6.41712E23, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Deimos", 1.8E20, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Phobos", 1.08E20, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Mercury", 3.301E23, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Venus", 4.86747E24, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Vesta", 2.5908E20, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Pallas", 2.14E20, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Hygiea", 8.32E19, new Vector3(), new Vector3()), new Vector3());
|
||||
map.put(new NamedBody("Ceres", 9.394E20, new Vector3(), new Vector3()), new Vector3());
|
||||
|
||||
assertEquals(12, map.size());
|
||||
|
||||
MassiveIterator iterator = map.getKeys().iterator();
|
||||
int count;
|
||||
for (count = 0; iterator.hasNext(); count++) {
|
||||
if (iterator.next().equals(mars)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
assertEquals(12, count);
|
||||
assertEquals(11, map.getKeys().size());
|
||||
assertEquals(11, map.size());
|
||||
assertFalse(map.getKeys().contains(mars));
|
||||
|
||||
assertThrows(NoSuchElementException.class, iterator::next);
|
||||
|
||||
iterator = map.getKeys().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
iterator.remove();
|
||||
}
|
||||
assertEquals(0, map.getKeys().size());
|
||||
}
|
||||
}
|
@ -20,6 +20,19 @@ public class Body implements Massive {
|
||||
this.currentMovement = new Vector3(other.currentMovement);
|
||||
}
|
||||
|
||||
public Body(double mass) {
|
||||
this(mass, new Vector3(), new Vector3());
|
||||
}
|
||||
|
||||
public Body() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public void setState(Vector3 position, Vector3 velocity) {
|
||||
this.massCenter = new Vector3(position);
|
||||
this.currentMovement = new Vector3(velocity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance between the mass centers of this body and the specified body 'b'.
|
||||
*/
|
||||
|
@ -87,14 +87,14 @@ public class BodyForceTreeMap {
|
||||
}
|
||||
|
||||
private String toString(Item item) {
|
||||
String s = "";
|
||||
StringBuilder s = new StringBuilder();
|
||||
if (item == null) {
|
||||
return s;
|
||||
return s.toString();
|
||||
}
|
||||
s += this.toString(item.right);
|
||||
s += String.format("{%s: %s}\n", item.key, item.value);
|
||||
s += this.toString(item.left);
|
||||
return s;
|
||||
s.append(this.toString(item.right));
|
||||
s.append(String.format("{%s: %s}\n", item.key, item.value));
|
||||
s.append(this.toString(item.left));
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,7 @@
|
||||
import codedraw.CodeDraw;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* A cosmic system that is composed of a central named body (of type 'NamedBodyForcePair')
|
||||
* and an arbitrary number of subsystems (of type 'CosmicSystem') in its orbit.
|
||||
@ -136,17 +138,16 @@ public class HierarchicalSystem implements CosmicSystem, MassiveIterable {
|
||||
|
||||
@Override
|
||||
public Massive next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
if (cur != null && cur.hasNext()) return cur.next();
|
||||
|
||||
for (; i < all.length; i++) {
|
||||
CosmicSystem sys = all[i];
|
||||
while (i < all.length) {
|
||||
CosmicSystem sys = all[i++];
|
||||
if (sys instanceof NamedBodyForcePair m) {
|
||||
i++;
|
||||
return m.getBody();
|
||||
} else if (sys instanceof HierarchicalSystem hs) {
|
||||
cur = hs.iterator();
|
||||
if (cur.hasNext()) {
|
||||
i++;
|
||||
return cur.next();
|
||||
}
|
||||
}
|
||||
@ -159,14 +160,14 @@ public class HierarchicalSystem implements CosmicSystem, MassiveIterable {
|
||||
public boolean hasNext() {
|
||||
if (cur != null && cur.hasNext()) return true;
|
||||
|
||||
for (; i < all.length; i++) {
|
||||
while (i < all.length) {
|
||||
CosmicSystem sys = all[i];
|
||||
if (sys instanceof NamedBodyForcePair) {
|
||||
return true;
|
||||
} else if (sys instanceof HierarchicalSystem hs) {
|
||||
if (sys instanceof NamedBodyForcePair) return true;
|
||||
i++;
|
||||
|
||||
if (sys instanceof HierarchicalSystem hs) {
|
||||
cur = hs.iterator();
|
||||
if (cur.hasNext()) {
|
||||
i++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import codedraw.CodeDraw;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* A map that associates an object of 'Massive' with a Vector3. The number of key-value pairs
|
||||
* is not limited.
|
||||
@ -86,14 +88,14 @@ public class MassiveForceTreeMap implements MassiveSet {
|
||||
}
|
||||
|
||||
private String toString(Item item) {
|
||||
String s = "";
|
||||
StringBuilder s = new StringBuilder();
|
||||
if (item == null) {
|
||||
return s;
|
||||
return s.toString();
|
||||
}
|
||||
s += this.toString(item.right);
|
||||
s += String.format("{%s: %s}\n", item.key, item.value);
|
||||
s += this.toString(item.left);
|
||||
return s;
|
||||
s.append(this.toString(item.right));
|
||||
s.append(String.format("{%s: %s}\n", item.key, item.value));
|
||||
s.append(this.toString(item.left));
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,25 +122,36 @@ public class MassiveForceTreeMap implements MassiveSet {
|
||||
@Override
|
||||
public MassiveIterator iterator() {
|
||||
return new MassiveIterator() {
|
||||
private Item last = null;
|
||||
private Item next = root.getLeftLeaf();
|
||||
|
||||
@Override
|
||||
public Massive next() {
|
||||
if (next == null) return null;
|
||||
Massive m = next.key;
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
|
||||
last = next;
|
||||
Item newNext = (next.right != null) ? next.right.getLeftLeaf() : next.parent;
|
||||
|
||||
while (newNext != null && newNext.right == next) {
|
||||
next = newNext;
|
||||
newNext = newNext.parent;
|
||||
}
|
||||
|
||||
next = newNext;
|
||||
return m;
|
||||
return last.key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (last == null) throw new IllegalStateException();
|
||||
removeItem(last);
|
||||
last = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -152,18 +165,7 @@ public class MassiveForceTreeMap implements MassiveSet {
|
||||
Item item = root;
|
||||
while (item != null) {
|
||||
if (item.key.equals(element)) {
|
||||
Item newP = null;
|
||||
if (item.left != null) {
|
||||
newP = item.left.getRightLeaf();
|
||||
} else if (item.right != null) {
|
||||
newP = item.right.getLeftLeaf();
|
||||
}
|
||||
if (item.parent.left == item) {
|
||||
item.parent.setLeft(newP);
|
||||
} else {
|
||||
item.parent.setRight(newP);
|
||||
}
|
||||
size--;
|
||||
removeItem(item);
|
||||
return;
|
||||
} else if (item.key.mass() > element.mass()) {
|
||||
item = item.left;
|
||||
@ -171,6 +173,44 @@ public class MassiveForceTreeMap implements MassiveSet {
|
||||
item = item.right;
|
||||
}
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
private void removeItem(Item item) {
|
||||
size--;
|
||||
Item newP = null;
|
||||
|
||||
if (item.left != null) {
|
||||
newP = item.left.getRightLeaf();
|
||||
if (newP != item.left) {
|
||||
newP.parent.setRight(newP.left);
|
||||
newP.setLeft(item.left);
|
||||
}
|
||||
newP.setRight(item.right);
|
||||
} else if (item.right != null) {
|
||||
newP = item.right.getLeftLeaf();
|
||||
if (newP != item.right) {
|
||||
newP.parent.setLeft(newP.right);
|
||||
newP.setRight(item.right);
|
||||
}
|
||||
newP.setLeft(item.left);
|
||||
}
|
||||
|
||||
if (newP == null) {
|
||||
root = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.parent != null) {
|
||||
if (item.parent.left == item) {
|
||||
item.parent.setLeft(newP);
|
||||
} else {
|
||||
item.parent.setRight(newP);
|
||||
}
|
||||
} else {
|
||||
root = newP;
|
||||
newP.parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -217,17 +257,13 @@ public class MassiveForceTreeMap implements MassiveSet {
|
||||
|
||||
public Item getLeftLeaf() {
|
||||
Item cur = this;
|
||||
while (cur.left != null) {
|
||||
cur = cur.left;
|
||||
}
|
||||
while (cur.left != null) cur = cur.left;
|
||||
return cur;
|
||||
}
|
||||
|
||||
public Item getRightLeaf() {
|
||||
Item cur = this;
|
||||
while (cur.right != null) {
|
||||
cur = cur.right;
|
||||
}
|
||||
while (cur.right != null) cur = cur.right;
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* A list of massive objects implemented as a linked list.
|
||||
* The number of elements of the list is not limited.
|
||||
*/
|
||||
public class MassiveLinkedList implements Iterable<Massive> {
|
||||
public class MassiveLinkedList implements MassiveIterable {
|
||||
private int size = 0;
|
||||
private Item first;
|
||||
private Item last;
|
||||
@ -172,8 +173,8 @@ public class MassiveLinkedList implements Iterable<Massive> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Massive> iterator() {
|
||||
return new Iterator<>() {
|
||||
public MassiveIterator iterator() {
|
||||
return new MassiveIterator() {
|
||||
Item ptr = first;
|
||||
boolean yieldedFirst = false;
|
||||
|
||||
@ -184,6 +185,7 @@ public class MassiveLinkedList implements Iterable<Massive> {
|
||||
|
||||
@Override
|
||||
public Massive next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
if (!yieldedFirst) {
|
||||
yieldedFirst = true;
|
||||
} else {
|
||||
|
@ -1,43 +1,41 @@
|
||||
import codedraw.CodeDraw;
|
||||
|
||||
public class NamedBody implements Massive {
|
||||
public class NamedBody extends Body {
|
||||
|
||||
private final String name;
|
||||
private final Body body;
|
||||
|
||||
/**
|
||||
* Initializes this with name, mass, current position and movement.
|
||||
*/
|
||||
public NamedBody(String name, double mass, Vector3 massCenter, Vector3 currentMovement) {
|
||||
this(name, new Body(mass, massCenter, currentMovement));
|
||||
super(mass, massCenter, currentMovement);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public NamedBody(String name, double mass) {
|
||||
super(mass);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public NamedBody(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public NamedBody(String name, Body body) {
|
||||
super(body);
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public NamedBody(NamedBody other) {
|
||||
this(other.name, new Body(other.body));
|
||||
super(other);
|
||||
this.name = other.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the body.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Body getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public Vector3 getMassCenter() {
|
||||
return body.getMassCenter();
|
||||
}
|
||||
|
||||
public double getMass() {
|
||||
return body.getMass();
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,14 +64,4 @@ public class NamedBody implements Massive {
|
||||
public String toString() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(Vector3 force) {
|
||||
body.move(force);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(CodeDraw cd) {
|
||||
body.draw(cd);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class NamedBodyForcePair implements CosmicSystem {
|
||||
}
|
||||
|
||||
public Body getBody() {
|
||||
return body.getBody();
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,13 +72,13 @@ public class NamedBodyForcePair implements CosmicSystem {
|
||||
|
||||
@Override
|
||||
public void addForceTo(CosmicSystem cs) {
|
||||
cs.addForceFrom(body.getBody());
|
||||
cs.addForceFrom(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyLinkedList getBodies() {
|
||||
BodyLinkedList list = new BodyLinkedList();
|
||||
list.addFirst(body.getBody());
|
||||
list.addFirst(body);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
127
src/ReadDataUtil.java
Normal file
127
src/ReadDataUtil.java
Normal file
@ -0,0 +1,127 @@
|
||||
import java.io.*;
|
||||
import java.util.Scanner;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ReadDataUtil {
|
||||
|
||||
private static final Pattern LINE_FORMAT = Pattern.compile("^\\d+(\\.\\d+)?, *[A-Za-z \\d:.-]+(, *[-+]?\\d+(\\.\\d+)?([eE][+-]?\\d+)?){6}, *$");
|
||||
private static final Pattern DATE_COLUMN_FORMAT = Pattern.compile("^A\\.D\\. (?<year>\\d{4})-(?<month>[A-Z][a-z]{2})-(?<day>[0-3]\\d) \\d{2}:\\d{2}:\\d{2}(\\.\\d+)?$");
|
||||
private static final Pattern DATE_FORMAT_YYYY_MMM_DD = Pattern.compile("^(?<year>\\d{4})-(?<month>[A-Z][a-z]{2})-(?<day>[0-3]\\d)$");
|
||||
|
||||
/**
|
||||
* Reads the position and velocity vector on the specified 'day' from the file with the
|
||||
* specified 'path', and sets position and current velocity of 'b' accordingly. If
|
||||
* successful the method returns 'true'. If the specified 'day' was not found in the file,
|
||||
* 'b' is unchanged and the method returns 'false'.
|
||||
* The file format is validated before reading the state.
|
||||
* Lines before the line "$$SOE" and after the line "$$EOE" the are ignored. Each line of the
|
||||
* file between the line "$$SOE" and the line "$$EOE" is required to have the following format:
|
||||
* JDTDB, TIME, X, Y, Z, VX, VY, VZ
|
||||
* where JDTDB is interpretable as a 'double' value, TIME is a string and X, Y, Z, VX, VY and
|
||||
* VZ are interpretable as 'double' values. JDTDB can be ignored. The character ',' must only
|
||||
* be used as field separator. If the file is not found, an exception of the class
|
||||
* 'StateFileNotFoundException' is thrown. If it does not comply with the format described
|
||||
* above, the method throws an exception of the class 'StateFileFormatException'. Both
|
||||
* exceptions are subtypes of 'IOException'.
|
||||
* Precondition: b != null, path != null, day != null and has the format YYYY-MM-DD.
|
||||
*/
|
||||
public static boolean readConfiguration(NamedBody b, String path, String day) throws IOException {
|
||||
State state = State.Pre;
|
||||
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(path))) {
|
||||
Scanner lines = new Scanner(in);
|
||||
long lineNum = 0;
|
||||
while (lines.hasNextLine() && state != State.Post) {
|
||||
lineNum++;
|
||||
String line = lines.nextLine();
|
||||
State nextState = state.next(line);
|
||||
|
||||
if (state == State.In && nextState == State.In) {
|
||||
Matcher m = LINE_FORMAT.matcher(line);
|
||||
if (!m.matches()) {
|
||||
throw new StateFileFormatException(path, lineNum);
|
||||
}
|
||||
|
||||
String[] rows = line.split(", *");
|
||||
String date;
|
||||
try {
|
||||
date = convertDateColumn(rows[1]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new StateFileFormatException(path, lineNum);
|
||||
}
|
||||
if (date.equals(day)) {
|
||||
try {
|
||||
double x = Double.parseDouble(rows[2]); // [km]
|
||||
double y = Double.parseDouble(rows[3]); // [km]
|
||||
double z = Double.parseDouble(rows[4]); // [km]
|
||||
double vx = Double.parseDouble(rows[5]); // [km/s]
|
||||
double vy = Double.parseDouble(rows[6]); // [km/s]
|
||||
double vz = Double.parseDouble(rows[7]); // [km/s]
|
||||
b.setState(new Vector3(x * 1000, y * 1000, z * 1000), new Vector3(vx * 1000, vy * 1000, vz * 1000));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new StateFileFormatException(path, lineNum);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
state = nextState;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (e instanceof FileNotFoundException) {
|
||||
throw new StateFileNotFoundException(path);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String convertDateColumn(String column) {
|
||||
Matcher m = DATE_COLUMN_FORMAT.matcher(column);
|
||||
if (!m.matches()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
return m.group("year") + "-" + convertMonth(m.group("month")) + "-" + m.group("day");
|
||||
}
|
||||
|
||||
public static String convertDate(String date) {
|
||||
Matcher m = DATE_FORMAT_YYYY_MMM_DD.matcher(date);
|
||||
if (!m.matches()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return m.group("year") + "-" + convertMonth(m.group("month")) + "-" + m.group("day");
|
||||
}
|
||||
|
||||
private static String convertMonth(String month) {
|
||||
return switch (month) {
|
||||
case "Jan" -> "01";
|
||||
case "Feb" -> "02";
|
||||
case "Mar" -> "03";
|
||||
case "Apr" -> "04";
|
||||
case "May" -> "05";
|
||||
case "Jun" -> "06";
|
||||
case "Jul" -> "07";
|
||||
case "Aug" -> "08";
|
||||
case "Sep" -> "09";
|
||||
case "Oct" -> "10";
|
||||
case "Nov" -> "11";
|
||||
case "Dec" -> "12";
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
}
|
||||
|
||||
private enum State {
|
||||
Pre, In, Post;
|
||||
|
||||
public State next(String line) {
|
||||
switch (this) {
|
||||
case Pre: if (line.equals("$$SOE")) return In; break;
|
||||
case In: if (line.equals("$$EOE")) return Post; break;
|
||||
case Post: break;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
120
src/Simulation8.java
Normal file
120
src/Simulation8.java
Normal file
@ -0,0 +1,120 @@
|
||||
import codedraw.CodeDraw;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Simulates the solar system.
|
||||
*/
|
||||
public class Simulation8 {
|
||||
|
||||
// gravitational constant
|
||||
public static final double G = 6.6743e-11;
|
||||
|
||||
// one astronomical unit (AU) is the average distance of earth to the sun.
|
||||
public static final double AU = 150e9; // meters
|
||||
|
||||
// set some system parameters
|
||||
public static final double SECTION_SIZE = 10 * AU; // the size of the square region in space
|
||||
|
||||
// all quantities are based on units of kilogram respectively second and meter.
|
||||
|
||||
// The main simulation method using instances of other classes.
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 2) {
|
||||
System.err.println("Error: wrong number of arguments.");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String statePath = args[0];
|
||||
String date;
|
||||
try {
|
||||
date = ReadDataUtil.convertDate(args[1]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("Error: State has wrong format (requires YYYY-MMM-DD), aborting.");
|
||||
System.exit(2);
|
||||
return;
|
||||
}
|
||||
|
||||
// simulation
|
||||
CodeDraw cd = new CodeDraw();
|
||||
|
||||
// create solar system with 13 bodies
|
||||
MassiveForceTreeMap forceOnBody = new MassiveForceTreeMap();
|
||||
|
||||
forceOnBody.put(new NamedBody("Oumuamua", 8e6), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Earth", 5.972E24), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Moon", 7.349E22), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Mars", 6.41712E23), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Deimos", 1.8E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Phobos", 1.08E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Mercury", 3.301E23), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Venus", 4.86747E24), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Vesta", 2.5908E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Pallas", 2.14E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Hygiea", 8.32E19), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Ceres", 9.394E20), new Vector3());
|
||||
|
||||
MassiveIterator iter = forceOnBody.getKeys().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Massive a = iter.next();
|
||||
if (a instanceof NamedBody b) {
|
||||
boolean remove = false;
|
||||
|
||||
try {
|
||||
boolean found = ReadDataUtil.readConfiguration(b, statePath + "/" + b.getName() + ".txt", date);
|
||||
if (!found) {
|
||||
System.err.println("Warning: State not available for " + b.getName() + ".");
|
||||
remove = true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (e instanceof StateFileNotFoundException notFound) {
|
||||
System.err.println("Warning: " + notFound.getMessage());
|
||||
} else if (e instanceof StateFileFormatException format) {
|
||||
System.err.println("Warning: " + format.getMessage());
|
||||
} else {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
System.exit(3);
|
||||
}
|
||||
remove = true;
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
System.err.println("Running simulation without " + b.getName());
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add sun after states have been read from files.
|
||||
forceOnBody.put(new NamedBody("Sun", 1.989E30), new Vector3());
|
||||
|
||||
System.out.println("Starting simulation");
|
||||
long seconds = 0;
|
||||
while (true) {
|
||||
seconds++;
|
||||
|
||||
for (Massive b1 : forceOnBody.getKeys()) {
|
||||
Vector3 force = new Vector3();
|
||||
for (Massive b2 : forceOnBody.getKeys()) {
|
||||
if (b1 != b2) {
|
||||
force = force.plus(b1.gravitationalForce(b2));
|
||||
}
|
||||
}
|
||||
forceOnBody.put(b1, force);
|
||||
}
|
||||
|
||||
for (Massive body : forceOnBody.getKeys()) {
|
||||
body.move(forceOnBody.get(body));
|
||||
}
|
||||
|
||||
if ((seconds % 3600) == 0) {
|
||||
cd.clear(Color.BLACK);
|
||||
for (Massive body : forceOnBody.getKeys()) {
|
||||
body.draw(cd);
|
||||
}
|
||||
cd.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
122
src/Simulation9.java
Normal file
122
src/Simulation9.java
Normal file
@ -0,0 +1,122 @@
|
||||
import codedraw.CodeDraw;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Simulates the solar system.
|
||||
*/
|
||||
public class Simulation9 {
|
||||
|
||||
// gravitational constant
|
||||
public static final double G = 6.6743e-11;
|
||||
|
||||
// one astronomical unit (AU) is the average distance of earth to the sun.
|
||||
public static final double AU = 150e9; // meters
|
||||
|
||||
// set some system parameters
|
||||
public static final double SECTION_SIZE = 10 * AU; // the size of the square region in space
|
||||
|
||||
// all quantities are based on units of kilogram respectively second and meter.
|
||||
|
||||
// The main simulation method using instances of other classes.
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 2) {
|
||||
System.err.println("Error: wrong number of arguments.");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String statePath = args[0];
|
||||
String date;
|
||||
try {
|
||||
date = ReadDataUtil.convertDate(args[1]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("Error: State has wrong format (requires YYYY-MMM-DD), aborting.");
|
||||
System.exit(2);
|
||||
return;
|
||||
}
|
||||
|
||||
// simulation
|
||||
CodeDraw cd = new CodeDraw();
|
||||
|
||||
// create solar system with 13 bodies
|
||||
HashMap<Massive, Vector3> forceOnBody = new HashMap<>();
|
||||
|
||||
forceOnBody.put(new NamedBody("Oumuamua", 8e6), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Earth", 5.972E24), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Moon", 7.349E22), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Mars", 6.41712E23), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Deimos", 1.8E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Phobos", 1.08E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Mercury", 3.301E23), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Venus", 4.86747E24), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Vesta", 2.5908E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Pallas", 2.14E20), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Hygiea", 8.32E19), new Vector3());
|
||||
forceOnBody.put(new NamedBody("Ceres", 9.394E20), new Vector3());
|
||||
|
||||
Iterator<Massive> iter = forceOnBody.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Massive a = iter.next();
|
||||
if (a instanceof NamedBody b) {
|
||||
boolean remove = false;
|
||||
|
||||
try {
|
||||
boolean found = ReadDataUtil.readConfiguration(b, statePath + "/" + b.getName() + ".txt", date);
|
||||
if (!found) {
|
||||
System.err.println("Warning: State not available for " + b.getName() + ".");
|
||||
remove = true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (e instanceof StateFileNotFoundException notFound) {
|
||||
System.err.println("Warning: " + notFound.getMessage());
|
||||
} else if (e instanceof StateFileFormatException format) {
|
||||
System.err.println("Warning: " + format.getMessage());
|
||||
} else {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
System.exit(3);
|
||||
}
|
||||
remove = true;
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
System.err.println("Running simulation without " + b.getName());
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add sun after states have been read from files.
|
||||
forceOnBody.put(new NamedBody("Sun", 1.989E30), new Vector3());
|
||||
|
||||
System.out.println("Starting simulation");
|
||||
long seconds = 0;
|
||||
while (true) {
|
||||
seconds++;
|
||||
|
||||
for (Massive b1 : forceOnBody.keySet()) {
|
||||
Vector3 force = new Vector3();
|
||||
for (Massive b2 : forceOnBody.keySet()) {
|
||||
if (b1 != b2) {
|
||||
force = force.plus(b1.gravitationalForce(b2));
|
||||
}
|
||||
}
|
||||
forceOnBody.put(b1, force);
|
||||
}
|
||||
|
||||
for (Massive body : forceOnBody.keySet()) {
|
||||
body.move(forceOnBody.get(body));
|
||||
}
|
||||
|
||||
if ((seconds % 3600) == 0) {
|
||||
cd.clear(Color.BLACK);
|
||||
for (Massive body : forceOnBody.keySet()) {
|
||||
body.draw(cd);
|
||||
}
|
||||
cd.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
src/StateFileFormatException.java
Normal file
20
src/StateFileFormatException.java
Normal file
@ -0,0 +1,20 @@
|
||||
import java.io.IOException;
|
||||
|
||||
public class StateFileFormatException extends IOException {
|
||||
private final String fileName;
|
||||
private final long lineNum;
|
||||
|
||||
public StateFileFormatException(String fileName, long lineNum) {
|
||||
super("File " + fileName + " has illegal format (line " + lineNum + ")");
|
||||
this.fileName = fileName;
|
||||
this.lineNum = lineNum;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
public long getLineNum() {
|
||||
return this.lineNum;
|
||||
}
|
||||
}
|
14
src/StateFileNotFoundException.java
Normal file
14
src/StateFileNotFoundException.java
Normal file
@ -0,0 +1,14 @@
|
||||
import java.io.IOException;
|
||||
|
||||
public class StateFileNotFoundException extends IOException {
|
||||
private final String fileName;
|
||||
|
||||
public StateFileNotFoundException(String fileName) {
|
||||
super("File " + fileName + " not found.");
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return this.fileName;
|
||||
}
|
||||
}
|
1
states/Ceres.txt
Normal file
1
states/Ceres.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Deimos.txt
Normal file
1
states/Deimos.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Earth.txt
Normal file
1
states/Earth.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Hygiea.txt
Normal file
1
states/Hygiea.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Mars.txt
Normal file
1
states/Mars.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Mercury.txt
Normal file
1
states/Mercury.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Moon.txt
Normal file
1
states/Moon.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Oumuamua.txt
Normal file
1
states/Oumuamua.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Pallas.txt
Normal file
1
states/Pallas.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Phobos.txt
Normal file
1
states/Phobos.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Venus.txt
Normal file
1
states/Venus.txt
Normal file
File diff suppressed because one or more lines are too long
1
states/Vesta.txt
Normal file
1
states/Vesta.txt
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user