From d0fce093ef2f16fc2897baf7ddf93b6f969890bf Mon Sep 17 00:00:00 2001
From: Friedrich Beckmann
Date: Fri, 30 Jan 2026 17:59:23 +0100
Subject: initial commit
The first prototype where you can upload student data from moodle
and change the marks. In student view the results for the logged in
person can be viewed.
---
ReadMe.md | 28 +++++++
admin-addusers.php | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++
admin-show.php | 154 ++++++++++++++++++++++++++++++++++++
admin-update.php | 39 +++++++++
database.php | 138 ++++++++++++++++++++++++++++++++
index.php | 46 +++++++++++
login.php | 47 +++++++++++
logout.php | 18 +++++
setup.php | 93 ++++++++++++++++++++++
show-user.php | 133 +++++++++++++++++++++++++++++++
10 files changed, 922 insertions(+)
create mode 100644 ReadMe.md
create mode 100644 admin-addusers.php
create mode 100644 admin-show.php
create mode 100644 admin-update.php
create mode 100644 database.php
create mode 100644 index.php
create mode 100644 login.php
create mode 100644 logout.php
create mode 100644 setup.php
create mode 100644 show-user.php
diff --git a/ReadMe.md b/ReadMe.md
new file mode 100644
index 0000000..5bb50d2
--- /dev/null
+++ b/ReadMe.md
@@ -0,0 +1,28 @@
+# praktrack - Verwaltung von Portfolioprüfungen
+
+Mit diesem Webtool können die Teilleistungen von den
+Portfolioprüfungen Digitaltechnik und Technische Informatik
+verwaltet werden. Portfolioprüfungen bestehen aus
+
+ * Laborteil der bestanden/nicht bestanden sein kann
+ * Klausur mit einer Note
+
+Erst wenn beide Prüfungsteile erfolgreich absolviert sind,
+wird die Note ans Prüfungsamt gemeldet.
+
+## Ansicht der Studenten
+
+Die Studenten authentifizieren sich über ldap und können dann die eigenen Daten einsehen.
+
+## Adminansicht
+
+Als Admin kann man Studenten für ein Semester und eine Prüfung (ti/dt) anlegen und dann die Prüfungsergebnisse ändern.
+
+## Anlegen der Studentendaten
+
+Die Prüfungsteilnehmer werden über die Daten aus dem Moodlekurs
+in das Tool importiert. Dazu werden die Teilnehmerdaten des Moodlekurses als .csv exportiert und dann in praktrack importiert.
+
+## Eingabe der Prüfungsergebnisse
+
+Die Prüfungsergebnisse werden in der Listenansicht eingegeben und mit dem Knopf "update" in die Datenbank gespeichert.
diff --git a/admin-addusers.php b/admin-addusers.php
new file mode 100644
index 0000000..880a535
--- /dev/null
+++ b/admin-addusers.php
@@ -0,0 +1,226 @@
+
+
+
+
+Add Users
+
+
+ Die Teilnehmer werden aus dem Moodlekurs der Veranstaltung übernommen.
+ Dazu die Teilnehmer als csv exportieren. Die csv Datei
+ dann mit den Angaben zum Kurs und zum Semester hier hochladen. Die
+ csv Datei enthält die Namen, Matrikelnummer und die Gruppen.
+
+
+ $teilnehmerliste) {
+ if (in_array($matrikelnummer, $teilnehmerliste)) {
+ return $gname;
+ }
+ }
+}
+
+function parseuserfile($fname) {
+ global $pfach,$psemester,$newstudents,$newgroups,$students,$groups;
+ if (($fh = fopen($fname, "r")) !== FALSE) {
+ while (($line = fgetcsv($fh, 1000, ",", "\"", ""))) {
+ $vorname = $line[0];
+ $nachname = $line[1];
+ $matrikelnummer = is_numeric($line[2]) ? $line[2] : "";
+ $student = array (
+ "vorname" => $vorname,
+ "nachname" => $nachname,
+ "noten" => array (
+ $pfach => []
+ )
+ );
+ $newgruppe = "";
+ if (!empty($line[4])) {
+ $gruppen = str_getcsv($line[4],",","\"","");
+ foreach ($gruppen as $gruppe) {
+ if (preg_match("/.*-G[0-9].*/u", $gruppe) or
+ preg_match("/G[0-9].*/u", $gruppe) ) {
+ $newgruppe = trim($gruppe);
+ }
+ }
+ }
+
+ if (empty($newgruppe) or empty($matrikelnummer)) {
+ echo "WARNING: $vorname $nachname has no group or no matrikelnummer.
";
+ } elseif (!empty($groups[$psemester][$pfach]) and
+ $gname = is_student_in_any_group($matrikelnummer, $groups[$psemester][$pfach])) {
+ echo "WARNING: $matrikelnummer is already in $gname in database.
";
+ } elseif ($gname = is_student_in_any_group($matrikelnummer, $newgroups)) {
+ echo "WARNING: $matrikelnummer is already in $gname in this file
";
+ } else {
+ if (empty($students[$matrikelnummer])) {
+ //db_student_new($matrikelnummer,$student);
+ echo "Adding student $matrikelnummer
";
+ $newstudents[$matrikelnummer] = $student;
+ } elseif (!array_key_exists($pfach,$students[$matrikelnummer]["noten"])) {
+ echo "Adding $pfach to student $matrikelnummer
";
+ $newstudents[$matrikelnummer] = $student;
+ } else {
+ echo "WARNING: student $matrikelnummer is already in database.
";
+ }
+ if (empty($groups[$psemester][$pfach][$newgruppe])) {
+ if (empty($newgroups[$newgruppe])) {
+ $newgroups[$newgruppe] = [$matrikelnummer];
+ } elseif (!in_array($matrikelnummer,$newgroups[$newgruppe])) {
+ $newgroups[$newgruppe][] = $matrikelnummer;
+ } else {
+ echo "WARNING: student $matrikelnummer is already in group $newgruppe
";
+ }
+ } elseif (!in_array($matrikelnummer,$groups[$psemester][$pfach][$newgruppe])) {
+ echo "ERROR: TODO group $newgruppe without $matrikelnummer already in database but
";
+ } else {
+ echo "WARNING: group $newgruppe with $matrikelnummer already in database
";
+ }
+ }
+ //echo "",$vorname,$nachname,$matrikelnummer,$newgruppe,"
";
+ }
+ ksort($newgroups);
+ $_SESSION["newstudents"] = $newstudents;
+ $_SESSION["newgroups"] = $newgroups;
+ $_SESSION["fach"] = $pfach;
+ $_SESSION["semester"] = $psemester;
+ } else {
+ echo "Error: Could not open file
";
+ return FALSE;
+ }
+ return;
+}
+
+echo "";
+
+?>
+
+
+
\ No newline at end of file
diff --git a/admin-show.php b/admin-show.php
new file mode 100644
index 0000000..10394d8
--- /dev/null
+++ b/admin-show.php
@@ -0,0 +1,154 @@
+
+
+
+
+
+Listenansicht
+
+
+
+";
+echo "";
+
+//echo "";
+?>
+
+
+
\ No newline at end of file
diff --git a/admin-update.php b/admin-update.php
new file mode 100644
index 0000000..f0d3896
--- /dev/null
+++ b/admin-update.php
@@ -0,0 +1,39 @@
+ $pruefungen) {
+ foreach ($pruefungen as $fach => $teilpruefungen) {
+ foreach ($teilpruefungen as $teilpruefung => $semesterliste) {
+ foreach ($semesterliste as $semestername => $note) {
+ if (!array_key_exists($fach,$students[$matrikelnummer]["noten"])) {
+ var_dump($students[$matrikelnummer]);
+ echo "ERROR: Fach $fach bei $matrikelnummer existiert nicht
";
+ } else {
+ if (!empty($note) and (
+ empty($students[$matrikelnummer]["noten"][$fach][$teilpruefung]) or
+ $students[$matrikelnummer]["noten"][$fach][$teilpruefung] !== $note)) {
+ if (($teilpruefung === "klausur" and in_array($note,$notenklausur) or
+ $teilpruefung === "labor" and in_array($note,$notenlabor))) {
+ $students[$matrikelnummer]["noten"][$fach][$teilpruefung] = $note;
+ db_student_update_note($matrikelnummer,$fach,$teilpruefung,$note);
+ break;
+ } else {
+ var_dump($students[$matrikelnummer]);
+ echo "ERROR: Note $note ungueltig fuer $matrikelnummer,$fach,$teilpruefung
";
+ }
+ }
+ }
+ }
+ }
+
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/database.php b/database.php
new file mode 100644
index 0000000..9c14920
--- /dev/null
+++ b/database.php
@@ -0,0 +1,138 @@
+ date('Y-m-d H:i:s', time()),
+ "cmd" => "student_new",
+ "matrikelnummer" => $matrikelnummer,
+ "vorname" => $student["vorname"],
+ "nachname" => $student["nachname"],
+ "noten" => $student["noten"]
+ );
+ $json_string = json_encode($json_student_add, JSON_UNESCAPED_UNICODE)."\n";
+ $fh = fopen("database.json", "a");
+ fwrite($fh,$json_string);
+ fclose($fh);
+
+ //echo $json_string;
+}
+
+function db_student_add_fach($matrikelnummer,$fach) {
+ date_default_timezone_set("UTC");
+ $cmd = array (
+ "time" => date('Y-m-d H:i:s', time()),
+ "cmd" => "student_add_fach",
+ "matrikelnummer" => $matrikelnummer,
+ "fach" => $fach
+ );
+ $json_string = json_encode($cmd, JSON_UNESCAPED_UNICODE)."\n";
+ $fh = fopen("database.json", "a");
+ fwrite($fh,$json_string);
+ fclose($fh);
+}
+
+function db_student_update_note($matrikelnummer,$fach,$teilpruefung,$note) {
+ date_default_timezone_set("UTC");
+ $cmd = array (
+ "time" => date('Y-m-d H:i:s', time()),
+ "cmd" => "note_upd",
+ "fach" => $fach,
+ "teilpruefung" => $teilpruefung,
+ "note" => $note,
+ "matrikelnummer" => $matrikelnummer
+ );
+ $json_string = json_encode($cmd, JSON_UNESCAPED_UNICODE)."\n";
+ $fh = fopen("database.json", "a");
+ fwrite($fh,$json_string);
+ fclose($fh);
+}
+
+function db_group_new($semester,$fach,$gname,$teilnehmerarray) {
+ date_default_timezone_set("UTC");
+ $cmd = array (
+ "time" => date('Y-m-d H:i:s', time()),
+ "cmd" => "group_new",
+ "semester" => $semester,
+ "fach" => $fach,
+ "name" => $gname,
+ "teilnehmer" => $teilnehmerarray
+ );
+ $json_string = json_encode($cmd, JSON_UNESCAPED_UNICODE)."\n";
+ $fh = fopen("database.json", "a");
+ fwrite($fh,$json_string);
+ fclose($fh);
+ //echo $json_string;
+}
+
+function db_read () {
+ global $students,$groups,$pfp;
+ $fh = fopen("database.json", "r");
+ if ($fh === FALSE) {
+ echo "Cannot open database.json
";
+ return FALSE;
+ }
+ while ($line = fgets($fh)) {
+ $cmd = json_decode($line,JSON_UNESCAPED_UNICODE);
+ switch ($cmd["cmd"]) {
+ case "student_new" :
+ $matrikelnummer = $cmd["matrikelnummer"];
+ if (empty($students[$matrikelnummer])) {
+ $students[$matrikelnummer]["vorname"] = $cmd["vorname"];
+ $students[$matrikelnummer]["nachname"] = $cmd["nachname"];
+ $students[$matrikelnummer]["noten"] = $cmd["noten"];
+ $fach = array_key_first($cmd["noten"]);
+ $students[$matrikelnummer]["history"][] = $cmd["time"]." student new with ".$fach;
+ } else {
+ echo "ERROR: Student ",$matrikelnummer," is already in database.
";
+ }
+ break;
+ case "student_add_fach" :
+ $matrikelnummer = $cmd["matrikelnummer"];
+ $fach = $cmd["fach"];
+ if (empty($students[$matrikelnummer])) {
+ echo "ERROR: Cannot add $fach to $matrikelnummer as student is not in database.
";
+ } elseif (array_key_exists($fach,$students[$matrikelnummer]["noten"])) {
+ echo "ERROR: $fach already exists for $matrikelnummer in database.
";
+ } else {
+ $students[$matrikelnummer]["noten"][$fach] = [];
+ $students[$matrikelnummer]["history"][] = $cmd["time"]." add ".$fach;
+ }
+ break;
+ case "group_new" :
+ $semester = $cmd["semester"];
+ $fach = $cmd["fach"];
+ $gname = $cmd["name"];
+ if (empty($groups[$semester][$fach][$gname])) {
+ $groups[$semester][$fach][$gname] = $cmd["teilnehmer"];
+ } else {
+ echo "ERROR: Group $gname for $fach in $semester is already in database.
";
+ }
+ break;
+ case "note_upd":
+ $fach = $cmd["fach"];
+ $teilpruefung = $cmd["teilpruefung"];
+ $matrikelnummer = $cmd["matrikelnummer"];
+ $note = $cmd["note"];
+ $students[$matrikelnummer]["noten"][$fach][$teilpruefung] = $note;
+ $students[$matrikelnummer]["history"][] = $cmd["time"]." ".$fach."/".$teilpruefung.": ".$note;
+ break;
+ default :
+ echo "ERROR: database cmd ", $cmd["cmd"],"is unknown.
";
+ }
+ }
+ fclose($fh);
+}
+
+// Search user with name and return matrikelnummer if found
+function db_find_user($vorname,$nachname) {
+ global $students;
+ foreach ($students as $matrikelnummer => $student) {
+ if ($student["vorname"] === $vorname and $student["nachname"] === $nachname) {
+ return $matrikelnummer;
+ break;
+ }
+ }
+ return FALSE;
+}
+?>
\ No newline at end of file
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..3997484
--- /dev/null
+++ b/index.php
@@ -0,0 +1,46 @@
+
+
+
+
+ Ergebnisse der Portfolioprüfungen
+ Hier können sie die Teilleistungen der Portfolioprüfungen für
+ die Veranstaltungen „Technische Informatik für EIT/ME“ und
+ „Digitaltechnik für TI“ einsehen. Sie müssen für den Login im Netz
+ der Hochschule oder über VPN mit dem Hochschulnetz verbunden sein.
+
+
+
+Login hat funktioniert. Leider habe ich sie nicht in der
+ Datenbank gefunden.
";
+ } elseif ($login === "failed") {
+ echo "Login failed
";
+ }
+ echo "";
+ echo "";
+}
+?>
\ No newline at end of file
diff --git a/login.php b/login.php
new file mode 100644
index 0000000..a767266
--- /dev/null
+++ b/login.php
@@ -0,0 +1,47 @@
+
+ 100) {
+ return "failed";
+ }
+ if (strlen($password) < 8 or strlen($password) > 1000) {
+ return "failed";
+ }
+ $ldapserver = "ldap://ldap.hs-augsburg.de";
+ $ldapusertree = 'ou=People, dc=fh-augsburg, dc=de';
+
+ $ldapconn = ldap_connect($ldapserver)
+ or die ("Cannot connect to ldap server ".$ldapserver);
+ ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+ ldap_set_option($ldapconn, LDAP_OPT_NETWORK_TIMEOUT, 3);
+
+ $ldapbind = ldap_bind($ldapconn,"uid=$username, ".$ldapusertree,$password);
+ if ($ldapbind) {
+ // Login was successfull
+ session_regenerate_id(TRUE);
+ $sr=ldap_search($ldapconn,$ldapusertree,"uid=$username",["sn","givenname"]);
+ $info = ldap_get_entries($ldapconn,$sr);
+ ldap_unbind($ldapconn);
+ $vorname = $info[0]["givenname"][0];
+ $nachname = $info[0]["sn"][0];
+ $matrikelnummer = db_find_user($vorname,$nachname);
+ if (in_array($username,$admins)) {
+ $_SESSION["login"] = "admin";
+ return "admin";
+ } elseif ($matrikelnummer) {
+ $_SESSION["login"] = "user";
+ $_SESSION["myusername"] = $username;
+ $_SESSION["mymatrikelnummer"] = $matrikelnummer;
+ return "user";
+ } else {
+ $_SESSION["login"] = "nodb";
+ return "nodb";
+ }
+ } else {
+ $_SESSION["login"] = "failed";
+ return "failed";
+ }
+}
+?>
\ No newline at end of file
diff --git a/logout.php b/logout.php
new file mode 100644
index 0000000..5fec951
--- /dev/null
+++ b/logout.php
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/setup.php b/setup.php
new file mode 100644
index 0000000..640ee56
--- /dev/null
+++ b/setup.php
@@ -0,0 +1,93 @@
+ 1,
+ 'cookie_httponly' => 1,
+ 'cookie_secure' => $secure, // Only if using HTTPS
+ 'cookie_samesite' => 'Strict', // or 'Lax'
+ 'use_only_cookies' => 1
+ ]);
+ // Set session timeout
+ if (isset($_SESSION['LAST_ACTIVITY']) &&
+ (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) { // 30 minutes
+ session_unset();
+ session_destroy();
+ }
+ $_SESSION['LAST_ACTIVITY'] = time();
+}
+
+$pfp = array (
+ "ti" => array (
+ "name" => "Technische Informatik",
+ "pnr" => ["1710080", "3707100"],
+ "studiengang" => ["EI", "ME"]
+ ),
+ "dt" => array (
+ "name" => "Digitaltechnik",
+ "pnr" => ["3976090"],
+ "studiengang" => ["TI"]
+ )
+);
+
+$notenlabor = ["BE", "NB", "AB", "NM", "NA"];
+$notenklausur = ["100","130","170","200","230","270","300","330","370","400","500"];
+
+$students = array (
+ "12345" => array (
+ "vorname" => "Karl",
+ "nachname" => "Meier",
+ "studiengang" => "EI",
+ "noten" => array (
+ "ti" => array (
+ "klausur" => "500",
+ "labor" => "BE"
+ ),
+ "dt" => []
+ )
+ ),
+ "11111" => array (
+ "vorname" => "Claudia",
+ "nachname" => "Darbo",
+ "studiengang" => "ME",
+ "noten" => array("ti" => [],"dt" => [])
+ ),
+ "22222" => array (
+ "vorname" => "Günther",
+ "nachname" => "Kohl",
+ "studiengang" => "TI",
+ "noten" => array("ti" => [],"dt" => [])
+ )
+);
+
+$groups = array (
+ "WiSe 2025/26" => array (
+ "ti" => array (
+ "G99-AA" => ["12345", "11111"],
+ "G99-ZZ" => ["22222", "11111"]
+ )
+ ),
+ "SoSe 2025" => array (
+ "ti" => array (
+ "G99-AA" => ["11111"],
+ "G98-ZZ" => ["22222"]
+ ),
+ "dt" => array (
+ "G99-KK" => ["11111"],
+ "G37-ZZ" => ["22222","12345"]
+ )
+ )
+);
+
+db_read();
+
+} //setupdone
+?>
diff --git a/show-user.php b/show-user.php
new file mode 100644
index 0000000..f0441c7
--- /dev/null
+++ b/show-user.php
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+$nachname, $vorname ($matrikelnummer)";
+ echo "Status
";
+ echo "";
+ echo "";
+ echo "| Fach | ";
+ echo "Labor | ";
+ echo "Klausur | ";
+ echo "
";
+ foreach ($students[$matrikelnummer]["noten"] as $fach => $notenliste) {
+ $fachname = $pfp[$fach]["name"];
+ if (!empty($notenliste["klausur"])) {
+ $klausurnote = $notenliste["klausur"];
+ } else {
+ $klausurnote = "-";
+ }
+ if (!empty($notenliste["labor"])) {
+ $labornote = $notenliste["labor"];
+ } else {
+ $labornote = "-";
+ }
+ echo "";
+ echo "| $fachname | ";
+ echo "$labornote | ";
+ echo "$klausurnote | ";
+ echo "
";
+ }
+ echo "
";
+
+ echo "Gruppen
";
+ echo "";
+ echo "";
+ echo "| Semester | ";
+ echo "Fach | ";
+ echo "Gruppenname | ";
+ echo "Teilnehmer | ";
+ echo "
";
+ foreach ($groups as $semestername => $fachliste) {
+ foreach ($fachliste as $fachname => $gruppenliste) {
+ foreach ($gruppenliste as $gname => $teilnehmerliste) {
+ if (in_array($matrikelnummer, $teilnehmerliste)) {
+ $tnnamensliste = "";
+ foreach ($teilnehmerliste as $tnmat) {
+ if (empty($tnnamensliste)) {
+ $tnnamensliste = $students[$tnmat]["nachname"];
+ } else {
+ $tnnamensliste = $tnnamensliste.", ".$students[$tnmat]["nachname"];
+ }
+ }
+ echo "";
+ echo "| $semestername | ";
+ echo "$fachname | ";
+ echo "$gname | ";
+ echo "$tnnamensliste | ";
+ echo "
";
+ }
+ }
+ }
+ }
+ echo "
";
+
+ echo "Geschichte
";
+ echo "";
+ echo "";
+ echo "| Ereignisliste | ";
+ echo "
";
+ foreach ($students[$matrikelnummer]["history"] as $ereignis) {
+ echo "";
+ echo "| $ereignis | ";
+ echo "
";
+ }
+ echo "
";
+} else {
+ echo "Error
";
+}
+?>
+
+
+
\ No newline at end of file
--
cgit v1.2.3