/*
    Thema:     Datenbanken PA
    Datum:     20.02.2026

    Autor 1:   Theo Leuthardt
    MatrNr.:   77205844868
	Autor 2:   Domenik Wilhelm
    MatrNr.:   77207300494
*/

-- Tabellen löschen, falls vorhanden --
BEGIN EXECUTE IMMEDIATE 'DROP TABLE PA_RESULT CASCADE CONSTRAINTS'; EXCEPTION WHEN OTHERS THEN NULL; END;
/
BEGIN EXECUTE IMMEDIATE 'DROP TABLE PA_SATELLITEN CASCADE CONSTRAINTS'; EXCEPTION WHEN OTHERS THEN NULL; END;
/
BEGIN EXECUTE IMMEDIATE 'DROP TABLE PA_STERNE CASCADE CONSTRAINTS'; EXCEPTION WHEN OTHERS THEN NULL; END;
/
BEGIN EXECUTE IMMEDIATE 'DROP TABLE PA_REFERENZ CASCADE CONSTRAINTS'; EXCEPTION WHEN OTHERS THEN NULL; END;
/

-- Aufgabe 4: Tabellen erstellen --
CREATE TABLE PA_REFERENZ (
    EntscheidungID  INTEGER      PRIMARY KEY,
    Entscheidung    VARCHAR2(50) NOT NULL
);

CREATE TABLE PA_STERNE (
   Stern   VARCHAR2(50)    PRIMARY KEY,
   Masse   NUMBER          NOT NULL,
   Radius  NUMBER          NOT NULL
);

CREATE TABLE PA_SATELLITEN (
   Kennung         VARCHAR2(50)    PRIMARY KEY,
   Geschwindigkeit NUMBER          NOT NULL
);

CREATE TABLE PA_RESULT (
   Stern           VARCHAR2(50)    NOT NULL,
   Kennung         VARCHAR2(50)    NOT NULL,
   EntscheidungID  INTEGER         NOT NULL,
   CONSTRAINT pk_result        PRIMARY KEY (Stern, Kennung),
   CONSTRAINT fk_result_stern  FOREIGN KEY (Stern)
       REFERENCES PA_STERNE (Stern),
   CONSTRAINT fk_result_sat    FOREIGN KEY (Kennung)
       REFERENCES PA_SATELLITEN (Kennung),
   CONSTRAINT fk_result_ref    FOREIGN KEY (EntscheidungID)
       REFERENCES PA_REFERENZ (EntscheidungID)
);

COMMIT;

-- Aufgabe 4: Tabellen befüllen --
INSERT INTO PA_REFERENZ (EntscheidungID, Entscheidung) VALUES (0, 'Kreisen');
INSERT INTO PA_REFERENZ (EntscheidungID, Entscheidung) VALUES (1, 'Kollidieren');
INSERT INTO PA_REFERENZ (EntscheidungID, Entscheidung) VALUES (2, 'Weiter fliegen');
INSERT INTO PA_REFERENZ (EntscheidungID, Entscheidung) VALUES (9, 'Entscheidungsfehler');

INSERT INTO PA_STERNE (Stern, Masse, Radius) VALUES ('Aldebaran',  3.38E+30, 3.07E+10);
INSERT INTO PA_STERNE (Stern, Masse, Radius) VALUES ('Arktur',     2.19E+30, 1.77E+10);
INSERT INTO PA_STERNE (Stern, Masse, Radius) VALUES ('Betelgeuse', 3.28E+31, 6.17E+11);
INSERT INTO PA_STERNE (Stern, Masse, Radius) VALUES ('Orion',      6.20E+35, 1.67E+13);
INSERT INTO PA_STERNE (Stern, Masse, Radius) VALUES ('Polarstern', 8.70E+30, 7.78E+08);
INSERT INTO PA_STERNE (Stern, Masse, Radius) VALUES ('Sonne',      1.99E+30, 6.96E+08);
INSERT INTO PA_STERNE (Stern, Masse, Radius) VALUES ('Erde',       5.97E+24, 6.37E+06);

INSERT INTO PA_SATELLITEN (Kennung, Geschwindigkeit) VALUES ('Bohr',       9.90E+04);
INSERT INTO PA_SATELLITEN (Kennung, Geschwindigkeit) VALUES ('Galileo',    5.00E+05);
INSERT INTO PA_SATELLITEN (Kennung, Geschwindigkeit) VALUES ('Higgs',      1.28E+14);
INSERT INTO PA_SATELLITEN (Kennung, Geschwindigkeit) VALUES ('Kopernikus', 1.31E+08);
INSERT INTO PA_SATELLITEN (Kennung, Geschwindigkeit) VALUES ('Newton',     9.10E+03);
INSERT INTO PA_SATELLITEN (Kennung, Geschwindigkeit) VALUES ('Plank',      7.77E+78);

COMMIT;

-- Aufgabe 5: PL/SQL Paket SAT --
CREATE OR REPLACE PACKAGE SAT AS
    C_GRAVITATIONSKONSTANTE CONSTANT NUMBER := 6.67E-11;
    C_WURZEL_ZWEI           CONSTANT NUMBER := 1.41421356237;

    PROCEDURE Action;
END SAT;
/

-- Aufgabe 6: PL/SQL Prozedur GetVelocity --
CREATE OR REPLACE PACKAGE BODY SAT AS

    PROCEDURE GetVelocity(
        p_EKG    OUT NUMBER,
        p_ZKG    OUT NUMBER,
        p_Masse  IN  NUMBER,
        p_Radius IN  NUMBER
    ) IS
    BEGIN
        p_EKG := SQRT(C_GRAVITATIONSKONSTANTE * p_Masse / p_Radius);
        p_ZKG := p_EKG * C_WURZEL_ZWEI;
    END GetVelocity;

-- Aufgabe 7: PL/SQL Prozedur Action --

    PROCEDURE Action IS
        v_EKG           NUMBER;
        v_ZKG           NUMBER;
        v_EntscheidungID INTEGER;

        CURSOR c_Sterne IS
            SELECT Stern, Masse, Radius
            FROM PA_STERNE;

        CURSOR c_Satelliten IS
            SELECT Kennung, Geschwindigkeit
            FROM PA_SATELLITEN;
    BEGIN
        FOR r_Stern IN c_Sterne LOOP
            FOR r_Satellit IN c_Satelliten LOOP
                GetVelocity(v_EKG, v_ZKG, r_Stern.Masse, r_Stern.Radius);

                IF r_Satellit.Geschwindigkeit < v_EKG THEN
                    v_EntscheidungID := 1;
                ELSIF r_Satellit.Geschwindigkeit <= v_ZKG THEN
                    v_EntscheidungID := 0;
                ELSIF r_Satellit.Geschwindigkeit > v_ZKG THEN
                    v_EntscheidungID := 2;
                ELSE
                    v_EntscheidungID := 9;
                END IF;

                INSERT INTO PA_RESULT (Stern, Kennung, EntscheidungID)
                VALUES (r_Stern.Stern, r_Satellit.Kennung, v_EntscheidungID);
            END LOOP;
        END LOOP;
    END Action;

END SAT;
/

-- Aufgabe 8: PL/SQL Anonymer Block --
DECLARE
    CURSOR c_Ergebnis IS
        SELECT r.Stern, r.Kennung, ref.Entscheidung
        FROM PA_RESULT r
        JOIN PA_REFERENZ ref ON r.EntscheidungID = ref.EntscheidungID
        ORDER BY r.Stern, r.Kennung;

    r_Ergebnis c_Ergebnis%ROWTYPE;
BEGIN
    DELETE FROM PA_RESULT;

    SAT.Action;

    OPEN c_Ergebnis;
    LOOP
        FETCH c_Ergebnis INTO r_Ergebnis;
        EXIT WHEN c_Ergebnis%NOTFOUND;

        DBMS_OUTPUT.PUT_LINE(
            'Stern: ' || RPAD(r_Ergebnis.Stern, 12) ||
            ' | Satellit: ' || RPAD(r_Ergebnis.Kennung, 12) ||
            ' | Entscheidung: ' || r_Ergebnis.Entscheidung
        );
    END LOOP;
    CLOSE c_Ergebnis;
END;
/
COMMIT;