├── xcode.jpg
├── ManualTextEnglish.pdf
├── ManualTextGerman.pdf
├── DuesseldorferSchuelerinventarInEnglish.pdf
├── DuesseldorferSchuelerinventarInGerman..pdf
├── deleteProfile.php
├── getProfiles.php
├── PersonalityTestApp.java
├── readNormTable.php
├── NormTableItem.java
├── User.java
├── item_norm_table.xml
├── fragment_competence_result.xml
├── AndroidManifest.xml
├── BaseActivity.java
├── activity_admin.xml
├── updateNormTable.php
├── activity_questionnaire.xml
├── fragment_question.xml
├── activity_login.xml
├── CompetenceResultFragment.java
├── saveProfile.php
├── PreferencesHelper.java
├── ProfileActivity.java
├── MainMenuActivity.java
├── register.php
├── login.php
├── Profile.java
├── ProfileAdapter.java
├── QuestionFragment.java
├── DatenbankAnlegen.sql
├── QuestionPagerAdapter.java
├── activity_profile.xml
├── README.md
├── QuestionnaireActivity.java
├── RegisterActivity.java
├── DatabaseHelper.java
├── ApiClient.java
├── NormTableAdapter.java
├── LoginActivity.java
└── ProfileListActivity.java
/xcode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pkoopongithub/duesseldorfer-schuelerinventar-android-studio/main/xcode.jpg
--------------------------------------------------------------------------------
/ManualTextEnglish.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pkoopongithub/duesseldorfer-schuelerinventar-android-studio/main/ManualTextEnglish.pdf
--------------------------------------------------------------------------------
/ManualTextGerman.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pkoopongithub/duesseldorfer-schuelerinventar-android-studio/main/ManualTextGerman.pdf
--------------------------------------------------------------------------------
/DuesseldorferSchuelerinventarInEnglish.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pkoopongithub/duesseldorfer-schuelerinventar-android-studio/main/DuesseldorferSchuelerinventarInEnglish.pdf
--------------------------------------------------------------------------------
/DuesseldorferSchuelerinventarInGerman..pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pkoopongithub/duesseldorfer-schuelerinventar-android-studio/main/DuesseldorferSchuelerinventarInGerman..pdf
--------------------------------------------------------------------------------
/deleteProfile.php:
--------------------------------------------------------------------------------
1 | connect_error) {
14 | die(json_encode(["status" => "error", "message" => "Datenbankverbindung fehlgeschlagen"]));
15 | }
16 |
17 | // Profil-ID erhalten
18 | $profileId = (int)$_GET['profile_id'];
19 |
20 | // Profil löschen
21 | $stmt = $conn->prepare("DELETE FROM profiles WHERE id = ?");
22 | $stmt->bind_param("i", $profileId);
23 |
24 | if ($stmt->execute()) {
25 | $response = ["status" => "success"];
26 | } else {
27 | $response = ["status" => "error", "message" => "Profil konnte nicht gelöscht werden"];
28 | }
29 |
30 | $stmt->close();
31 | $conn->close();
32 |
33 | echo json_encode($response);
34 | ?>
--------------------------------------------------------------------------------
/getProfiles.php:
--------------------------------------------------------------------------------
1 | connect_error) {
14 | die(json_encode(["status" => "error", "message" => "Datenbankverbindung fehlgeschlagen"]));
15 | }
16 |
17 | // Benutzer-ID erhalten
18 | $userId = (int)$_GET['user_id'];
19 |
20 | // Profile abfragen
21 | $stmt = $conn->prepare("SELECT id, name, created_at FROM profiles WHERE user_id = ? ORDER BY created_at DESC");
22 | $stmt->bind_param("i", $userId);
23 | $stmt->execute();
24 | $result = $stmt->get_result();
25 |
26 | $profiles = [];
27 | while ($row = $result->fetch_assoc()) {
28 | $profiles[] = $row;
29 | }
30 |
31 | $response = [
32 | "status" => "success",
33 | "data" => $profiles
34 | ];
35 |
36 | $stmt->close();
37 | $conn->close();
38 |
39 | echo json_encode($response);
40 | ?>
--------------------------------------------------------------------------------
/PersonalityTestApp.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest;
2 |
3 | import android.app.Application;
4 |
5 | import com.example.personalitytest.models.Profile;
6 | import com.example.personalitytest.models.User;
7 |
8 | public class PersonalityTestApp extends Application {
9 | private User currentUser;
10 | private Profile currentProfile;
11 | private double[][] normTable;
12 | private String apiBaseUrl = "https://mein-duesk.org/";
13 |
14 | @Override
15 | public void onCreate() {
16 | super.onCreate();
17 | // Hier könnten Sie Initialisierungen durchführen
18 | }
19 |
20 | // Getter und Setter
21 | public User getCurrentUser() { return currentUser; }
22 | public void setCurrentUser(User user) { this.currentUser = user; }
23 |
24 | public Profile getCurrentProfile() { return currentProfile; }
25 | public void setCurrentProfile(Profile profile) { this.currentProfile = profile; }
26 |
27 | public double[][] getNormTable() { return normTable; }
28 | public void setNormTable(double[][] normTable) { this.normTable = normTable; }
29 |
30 | public String getApiBaseUrl() { return apiBaseUrl; }
31 | }
--------------------------------------------------------------------------------
/readNormTable.php:
--------------------------------------------------------------------------------
1 | connect_error) {
14 | die(json_encode(["status" => "error", "message" => "Datenbankverbindung fehlgeschlagen"]));
15 | }
16 |
17 | // Normtabelle abfragen
18 | $query = "SELECT kompetenzID, p1, p2, p3, p4, p5 FROM normSEhs ORDER BY kompetenzID";
19 | $result = $conn->query($query);
20 |
21 | if ($result->num_rows === 0) {
22 | echo json_encode(["status" => "error", "message" => "Keine Normdaten gefunden"]);
23 | exit;
24 | }
25 |
26 | $normTable = [];
27 | while ($row = $result->fetch_assoc()) {
28 | $normTable[] = [
29 | (float)$row['p1'],
30 | (float)$row['p2'],
31 | (float)$row['p3'],
32 | (float)$row['p4'],
33 | (float)$row['p5']
34 | ];
35 | }
36 |
37 | $response = [
38 | "status" => "success",
39 | "data" => $normTable
40 | ];
41 |
42 | $conn->close();
43 | echo json_encode($response);
44 | ?>
--------------------------------------------------------------------------------
/NormTableItem.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.models;
2 |
3 | public class NormTableItem {
4 | private int id;
5 | private String competenceName;
6 | private double p1, p2, p3, p4, p5;
7 | private boolean modified;
8 |
9 | public NormTableItem(int id, String competenceName, double p1, double p2, double p3, double p4, double p5) {
10 | this.id = id;
11 | this.competenceName = competenceName;
12 | this.p1 = p1;
13 | this.p2 = p2;
14 | this.p3 = p3;
15 | this.p4 = p4;
16 | this.p5 = p5;
17 | this.modified = false;
18 | }
19 |
20 | // Getter
21 | public int getId() { return id; }
22 | public String getCompetenceName() { return competenceName; }
23 | public double getP1() { return p1; }
24 | public double getP2() { return p2; }
25 | public double getP3() { return p3; }
26 | public double getP4() { return p4; }
27 | public double getP5() { return p5; }
28 | public boolean isModified() { return modified; }
29 |
30 | // Setter mit modified-Flag
31 | public void setP1(double p1) {
32 | if (this.p1 != p1) modified = true;
33 | this.p1 = p1;
34 | }
35 | // ... gleiches für p2 bis p5
36 | }
--------------------------------------------------------------------------------
/User.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.models;
2 |
3 | import java.util.Date;
4 |
5 | public class User {
6 | private int id;
7 | private String username;
8 | private String email;
9 | private String passwordHash;
10 | private boolean isAdmin;
11 | private Date createdAt;
12 | private Date lastLogin;
13 |
14 | // Konstruktor
15 | public User(int id, String username, String email, boolean isAdmin) {
16 | this.id = id;
17 | this.username = username;
18 | this.email = email;
19 | this.isAdmin = isAdmin;
20 | this.createdAt = new Date();
21 | }
22 |
23 | // Getter und Setter
24 | public int getId() { return id; }
25 | public String getUsername() { return username; }
26 | public String getEmail() { return email; }
27 | public boolean isAdmin() { return isAdmin; }
28 | public Date getCreatedAt() { return createdAt; }
29 | public Date getLastLogin() { return lastLogin; }
30 |
31 | public void setLastLogin(Date lastLogin) { this.lastLogin = lastLogin; }
32 | public void setPasswordHash(String hash) { this.passwordHash = hash; }
33 |
34 | // Weitere Methoden
35 | public boolean checkPassword(String password) {
36 | return BCrypt.checkpw(password, this.passwordHash);
37 | }
38 | }
--------------------------------------------------------------------------------
/item_norm_table.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
21 |
22 |
27 |
28 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/fragment_competence_result.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
21 |
22 |
29 |
30 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
30 |
31 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.widget.Toast;
6 |
7 | import androidx.annotation.Nullable;
8 | import androidx.appcompat.app.AppCompatActivity;
9 |
10 | import com.example.personalitytest.utils.PreferencesHelper;
11 |
12 | public abstract class BaseActivity extends AppCompatActivity {
13 | protected PreferencesHelper preferencesHelper;
14 |
15 | @Override
16 | protected void onCreate(@Nullable Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | preferencesHelper = new PreferencesHelper(this);
19 | }
20 |
21 | @Override
22 | protected void onStart() {
23 | super.onStart();
24 | checkAuthentication();
25 | }
26 |
27 | protected void checkAuthentication() {
28 | if (!(this instanceof LoginActivity || this instanceof RegisterActivity)) {
29 | if (!preferencesHelper.isLoggedIn()) {
30 | redirectToLogin();
31 | }
32 | }
33 | }
34 |
35 | protected void redirectToLogin() {
36 | Intent intent = new Intent(this, LoginActivity.class);
37 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
38 | startActivity(intent);
39 | finish();
40 | }
41 |
42 | protected void showToast(String message) {
43 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
44 | }
45 |
46 | protected void showLongToast(String message) {
47 | Toast.makeText(this, message, Toast.LENGTH_LONG).show();
48 | }
49 | }
--------------------------------------------------------------------------------
/activity_admin.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
22 |
23 |
28 |
29 |
35 |
36 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/updateNormTable.php:
--------------------------------------------------------------------------------
1 | connect_error) {
14 | die(json_encode(["status" => "error", "message" => "Datenbankverbindung fehlgeschlagen"]));
15 | }
16 |
17 | // Eingabedaten erhalten
18 | $json = file_get_contents('php://input');
19 | $data = json_decode($json, true);
20 |
21 | if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
22 | echo json_encode(["status" => "error", "message" => "Ungültige Eingabedaten"]);
23 | exit;
24 | }
25 |
26 | // Transaktion beginnen für atomare Updates
27 | $conn->begin_transaction();
28 |
29 | try {
30 | foreach ($data as $item) {
31 | $kompetenzID = (int)$item['kompetenzID'];
32 | $p1 = (float)$item['p1'];
33 | $p2 = (float)$item['p2'];
34 | $p3 = (float)$item['p3'];
35 | $p4 = (float)$item['p4'];
36 | $p5 = (float)$item['p5'];
37 |
38 | $stmt = $conn->prepare("UPDATE normSEhs SET p1 = ?, p2 = ?, p3 = ?, p4 = ?, p5 = ? WHERE kompetenzID = ?");
39 | $stmt->bind_param("dddddi", $p1, $p2, $p3, $p4, $p5, $kompetenzID);
40 | $stmt->execute();
41 | $stmt->close();
42 | }
43 |
44 | $conn->commit();
45 | echo json_encode(["status" => "success"]);
46 | } catch (Exception $e) {
47 | $conn->rollback();
48 | echo json_encode(["status" => "error", "message" => $e->getMessage()]);
49 | }
50 |
51 | $conn->close();
52 | ?>
--------------------------------------------------------------------------------
/activity_questionnaire.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
21 |
22 |
27 |
28 |
33 |
34 |
40 |
41 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/fragment_question.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
20 |
21 |
27 |
28 |
34 |
35 |
41 |
42 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
22 |
23 |
30 |
31 |
37 |
38 |
45 |
46 |
53 |
54 |
--------------------------------------------------------------------------------
/CompetenceResultFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.fragments;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ProgressBar;
8 | import android.widget.TextView;
9 |
10 | import androidx.annotation.NonNull;
11 | import androidx.annotation.Nullable;
12 | import androidx.fragment.app.Fragment;
13 |
14 | import com.example.personalitytest.R;
15 |
16 | public class CompetenceResultFragment extends Fragment {
17 | private static final String ARG_TITLE = "title";
18 | private static final String ARG_SCORE = "score";
19 |
20 | private String title;
21 | private int score;
22 |
23 | public static CompetenceResultFragment newInstance(String title, int score) {
24 | CompetenceResultFragment fragment = new CompetenceResultFragment();
25 | Bundle args = new Bundle();
26 | args.putString(ARG_TITLE, title);
27 | args.putInt(ARG_SCORE, score);
28 | fragment.setArguments(args);
29 | return fragment;
30 | }
31 |
32 | @Override
33 | public void onCreate(@Nullable Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | if (getArguments() != null) {
36 | title = getArguments().getString(ARG_TITLE);
37 | score = getArguments().getInt(ARG_SCORE);
38 | }
39 | }
40 |
41 | @Nullable
42 | @Override
43 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
44 | View view = inflater.inflate(R.layout.fragment_competence_result, container, false);
45 |
46 | TextView tvTitle = view.findViewById(R.id.tvTitle);
47 | ProgressBar progressBar = view.findViewById(R.id.progressBar);
48 | TextView tvScore = view.findViewById(R.id.tvScore);
49 |
50 | tvTitle.setText(title);
51 | progressBar.setProgress(score * 20); // 1-5 zu 20-100%
52 | tvScore.setText(String.valueOf(score));
53 |
54 | return view;
55 | }
56 | }
--------------------------------------------------------------------------------
/saveProfile.php:
--------------------------------------------------------------------------------
1 | connect_error) {
14 | die(json_encode(["status" => "error", "message" => "Datenbankverbindung fehlgeschlagen"]));
15 | }
16 |
17 | // Eingaben erhalten
18 | $data = json_decode(file_get_contents('php://input'), true);
19 | $userId = (int)$data['user_id'];
20 | $answers = $data['answers'];
21 |
22 | // Profil speichern oder aktualisieren
23 | if (isset($data['profile_id']) && $data['profile_id'] > 0) {
24 | // Vorhandenes Profil aktualisieren
25 | $profileId = (int)$data['profile_id'];
26 | $query = "UPDATE profiles SET modified_at = NOW()";
27 |
28 | for ($i = 0; $i < 36; $i++) {
29 | $query .= ", item" . ($i + 1) . " = " . (int)$answers[$i];
30 | }
31 |
32 | $query .= " WHERE id = ? AND user_id = ?";
33 | $stmt = $conn->prepare($query);
34 | $stmt->bind_param("ii", $profileId, $userId);
35 | } else {
36 | // Neues Profil erstellen
37 | $query = "INSERT INTO profiles (user_id, created_at, modified_at";
38 | $values = "VALUES (?, NOW(), NOW()";
39 |
40 | for ($i = 0; $i < 36; $i++) {
41 | $query .= ", item" . ($i + 1);
42 | $values .= ", ?";
43 | }
44 |
45 | $query .= ") " . $values . ")";
46 | $stmt = $conn->prepare($query);
47 |
48 | $params = array_merge([$userId], $answers);
49 | $types = str_repeat("i", 37); // user_id + 36 items
50 | $stmt->bind_param($types, ...$params);
51 | }
52 |
53 | if ($stmt->execute()) {
54 | $profileId = isset($profileId) ? $profileId : $stmt->insert_id;
55 | $response = [
56 | "status" => "success",
57 | "profile_id" => $profileId
58 | ];
59 | } else {
60 | $response = [
61 | "status" => "error",
62 | "message" => "Profil konnte nicht gespeichert werden"
63 | ];
64 | }
65 |
66 | $stmt->close();
67 | $conn->close();
68 |
69 | echo json_encode($response);
70 | ?>
--------------------------------------------------------------------------------
/PreferencesHelper.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import com.example.personalitytest.models.User;
7 |
8 | public class PreferencesHelper {
9 | private static final String PREFS_NAME = "PersonalityTestPrefs";
10 | private static final String KEY_IS_LOGGED_IN = "is_logged_in";
11 | private static final String KEY_USER_ID = "user_id";
12 | private static final String KEY_USERNAME = "username";
13 | private static final String KEY_EMAIL = "email";
14 | private static final String KEY_IS_ADMIN = "is_admin";
15 |
16 | private final SharedPreferences preferences;
17 |
18 | public PreferencesHelper(Context context) {
19 | preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
20 | }
21 |
22 | public void saveLoginState(User user) {
23 | SharedPreferences.Editor editor = preferences.edit();
24 | editor.putBoolean(KEY_IS_LOGGED_IN, true);
25 | editor.putInt(KEY_USER_ID, user.getId());
26 | editor.putString(KEY_USERNAME, user.getUsername());
27 | editor.putString(KEY_EMAIL, user.getEmail());
28 | editor.putBoolean(KEY_IS_ADMIN, user.isAdmin());
29 | editor.apply();
30 | }
31 |
32 | public void clearLoginState() {
33 | SharedPreferences.Editor editor = preferences.edit();
34 | editor.remove(KEY_IS_LOGGED_IN);
35 | editor.remove(KEY_USER_ID);
36 | editor.remove(KEY_USERNAME);
37 | editor.remove(KEY_EMAIL);
38 | editor.remove(KEY_IS_ADMIN);
39 | editor.apply();
40 | }
41 |
42 | public boolean isLoggedIn() {
43 | return preferences.getBoolean(KEY_IS_LOGGED_IN, false);
44 | }
45 |
46 | public User getSavedUser() {
47 | if (!isLoggedIn()) {
48 | return null;
49 | }
50 |
51 | return new User(
52 | preferences.getInt(KEY_USER_ID, 0),
53 | preferences.getString(KEY_USERNAME, ""),
54 | preferences.getString(KEY_EMAIL, ""),
55 | preferences.getBoolean(KEY_IS_ADMIN, false)
56 | );
57 | }
58 | }
--------------------------------------------------------------------------------
/ProfileActivity.java:
--------------------------------------------------------------------------------
1 | public class ProfileActivity extends AppCompatActivity {
2 | private int profileId;
3 | private Profile currentProfile;
4 | private ProgressBar[] competenceBars = new ProgressBar[6];
5 |
6 | @Override
7 | protected void onCreate(Bundle savedInstanceState) {
8 | super.onCreate(savedInstanceState);
9 | setContentView(R.layout.activity_profile);
10 |
11 | profileId = getIntent().getIntExtra("profile_id", 0);
12 | if (profileId == 0) {
13 | finish();
14 | return;
15 | }
16 |
17 | setupUI();
18 | loadProfileData();
19 | }
20 |
21 | private void setupUI() {
22 | competenceBars[0] = findViewById(R.id.progressBarKompetenz1);
23 | competenceBars[1] = findViewById(R.id.progressBarKompetenz2);
24 | competenceBars[2] = findViewById(R.id.progressBarKompetenz3);
25 | competenceBars[3] = findViewById(R.id.progressBarKompetenz4);
26 | competenceBars[4] = findViewById(R.id.progressBarKompetenz5);
27 | competenceBars[5] = findViewById(R.id.progressBarKompetenz6);
28 |
29 | Button btnEdit = findViewById(R.id.btnEdit);
30 | btnEdit.setOnClickListener(v ->
31 | startActivity(new Intent(this, QuestionnaireActivity.class)
32 | .putExtra("profile_id", profileId)));
33 | }
34 |
35 | private void loadProfileData() {
36 | // Profildaten laden (vom Server oder lokal)
37 | // Normtabelle laden
38 | // Ergebnisse berechnen und anzeigen
39 | }
40 | private void loadProfileData() {
41 | Profile profile = ((PersonalityTestApp) getApplication()).getCurrentProfile();
42 | if (profile != null) {
43 | int[] scores = profile.getCompetenceScores();
44 |
45 | for (int i = 0; i < competenceBars.length; i++) {
46 | competenceBars[i].setProgress(scores[i] * 20); // 1-5 zu 20-100%
47 | }
48 |
49 | // Optional: TextViews für Score-Anzeige
50 | //TextView tvScore1 = findViewById(R.id.tvScore1);
51 | //tvScore1.setText(String.valueOf(scores[0]));
52 | // ... für alle 6 Kompetenzen
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/MainMenuActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 |
8 | import androidx.appcompat.app.AppCompatActivity;
9 |
10 | public class MainMenuActivity extends AppCompatActivity {
11 |
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | setContentView(R.layout.activity_main_menu);
16 |
17 | Button btnNewTest = findViewById(R.id.btnNewTest);
18 | Button btnViewProfiles = findViewById(R.id.btnViewProfiles);
19 | Button btnAdmin = findViewById(R.id.btnAdmin);
20 | Button btnLogout = findViewById(R.id.btnLogout);
21 |
22 | // Admin-Button nur anzeigen, wenn Benutzer Admin ist
23 | btnAdmin.setVisibility(
24 | ((PersonalityTestApp) getApplication()).getCurrentUser().isAdmin()
25 | ? View.VISIBLE : View.GONE
26 | );
27 |
28 | btnNewTest.setOnClickListener(v -> startNewQuestionnaire());
29 | btnViewProfiles.setOnClickListener(v -> viewProfiles());
30 | btnAdmin.setOnClickListener(v -> startAdminPanel());
31 | btnLogout.setOnClickListener(v -> logout());
32 | }
33 |
34 | private void startNewQuestionnaire() {
35 | Profile newProfile = new Profile();
36 | newProfile.setUserId(((PersonalityTestApp) getApplication()).getCurrentUser().getId());
37 | ((PersonalityTestApp) getApplication()).setCurrentProfile(newProfile);
38 |
39 | Intent intent = new Intent(this, QuestionnaireActivity.class);
40 | intent.putExtra("is_new_profile", true);
41 | startActivity(intent);
42 | }
43 |
44 | private void viewProfiles() {
45 | startActivity(new Intent(this, ProfileListActivity.class));
46 | }
47 |
48 | private void startAdminPanel() {
49 | startActivity(new Intent(this, AdminActivity.class));
50 | }
51 |
52 | private void logout() {
53 | ((PersonalityTestApp) getApplication()).setCurrentUser(null);
54 | startActivity(new Intent(this, LoginActivity.class));
55 | finish();
56 | }
57 | }
--------------------------------------------------------------------------------
/register.php:
--------------------------------------------------------------------------------
1 | connect_error) {
14 | die(json_encode(["status" => "error", "message" => "Datenbankverbindung fehlgeschlagen"]));
15 | }
16 |
17 | // Eingabedaten erhalten
18 | $json = file_get_contents('php://input');
19 | $data = json_decode($json, true);
20 |
21 | if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
22 | echo json_encode(["status" => "error", "message" => "Ungültige Eingabedaten"]);
23 | exit;
24 | }
25 |
26 | $username = $conn->real_escape_string($data['username']);
27 | $email = $conn->real_escape_string($data['email']);
28 | $password = $data['password'];
29 |
30 | // Überprüfen, ob Benutzername oder E-Mail bereits existieren
31 | $checkStmt = $conn->prepare("SELECT id FROM users WHERE username = ? OR email = ?");
32 | $checkStmt->bind_param("ss", $username, $email);
33 | $checkStmt->execute();
34 | $checkResult = $checkStmt->get_result();
35 |
36 | if ($checkResult->num_rows > 0) {
37 | echo json_encode(["status" => "error", "message" => "Benutzername oder E-Mail bereits vergeben"]);
38 | $checkStmt->close();
39 | $conn->close();
40 | exit;
41 | }
42 |
43 | $checkStmt->close();
44 |
45 | // Passwort hashen
46 | $passwordHash = password_hash($password, PASSWORD_DEFAULT);
47 |
48 | // Neuen Benutzer erstellen
49 | $insertStmt = $conn->prepare("INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)");
50 | $insertStmt->bind_param("sss", $username, $email, $passwordHash);
51 |
52 | if ($insertStmt->execute()) {
53 | $userId = $conn->insert_id;
54 | $response = [
55 | "status" => "success",
56 | "user_id" => $userId,
57 | "message" => "Benutzer erfolgreich registriert"
58 | ];
59 | } else {
60 | $response = [
61 | "status" => "error",
62 | "message" => "Registrierung fehlgeschlagen"
63 | ];
64 | }
65 |
66 | $insertStmt->close();
67 | $conn->close();
68 |
69 | echo json_encode($response);
70 | ?>
--------------------------------------------------------------------------------
/login.php:
--------------------------------------------------------------------------------
1 | prepare("SELECT id, password FROM users WHERE username = ?");
14 | $stmt->bind_param("s", $username);
15 | $stmt->execute();
16 | $result = $stmt->get_result();
17 |
18 | if ($result->num_rows > 0) {
19 | $user = $result->fetch_assoc();
20 | if (password_verify($password, $user['password'])) {
21 | echo json_encode(['status' => 'success', 'user_id' => $user['id']]);
22 | } else {
23 | echo json_encode(['status' => 'error', 'message' => 'Invalid password']);
24 | }
25 | } else {
26 | echo json_encode(['status' => 'error', 'message' => 'User not found']);
27 | }
28 |
29 | $conn->close();
30 | ?>connect_error) {
43 | die(json_encode(["status" => "error", "message" => "Datenbankverbindung fehlgeschlagen"]));
44 | }
45 |
46 | // Eingaben erhalten
47 | $username = $conn->real_escape_string($_GET['username']);
48 | $password = $_GET['password'];
49 |
50 | // Benutzer abfragen
51 | $stmt = $conn->prepare("SELECT id, username, email, password_hash, is_admin FROM users WHERE username = ?");
52 | $stmt->bind_param("s", $username);
53 | $stmt->execute();
54 | $result = $stmt->get_result();
55 |
56 | if ($result->num_rows === 0) {
57 | echo json_encode(["status" => "error", "message" => "Benutzer nicht gefunden"]);
58 | exit;
59 | }
60 |
61 | $user = $result->fetch_assoc();
62 |
63 | // Passwort überprüfen
64 | if (password_verify($password, $user['password_hash'])) {
65 | // Login erfolgreich
66 | $response = [
67 | "status" => "success",
68 | "user_id" => $user['id'],
69 | "username" => $user['username'],
70 | "email" => $user['email'],
71 | "is_admin" => (bool)$user['is_admin']
72 | ];
73 |
74 | // Letzten Login aktualisieren
75 | $updateStmt = $conn->prepare("UPDATE users SET last_login = NOW() WHERE id = ?");
76 | $updateStmt->bind_param("i", $user['id']);
77 | $updateStmt->execute();
78 | } else {
79 | $response = ["status" => "error", "message" => "Falsches Passwort"];
80 | }
81 |
82 | $stmt->close();
83 | $conn->close();
84 |
85 | echo json_encode($response);
86 | ?>
--------------------------------------------------------------------------------
/Profile.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.models;
2 |
3 | import java.util.Date;
4 |
5 | public class Profile {
6 | private int id;
7 | private int userId;
8 | private String name;
9 | private Date createdAt;
10 | private Date modifiedAt;
11 | private int[] answers;
12 | private int[] competenceScores;
13 |
14 | public Profile() {
15 | this.answers = new int[36];
16 | this.competenceScores = new int[6];
17 | }
18 |
19 | // Getter und Setter
20 | public int getId() { return id; }
21 | public int getUserId() { return userId; }
22 | public String getName() { return name; }
23 | public Date getCreatedAt() { return createdAt; }
24 | public Date getModifiedAt() { return modifiedAt; }
25 | public int[] getAnswers() { return answers; }
26 | public int[] getCompetenceScores() { return competenceScores; }
27 |
28 | public void setId(int id) { this.id = id; }
29 | public void setUserId(int userId) { this.userId = userId; }
30 | public void setName(String name) { this.name = name; }
31 | public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }
32 | public void setModifiedAt(Date modifiedAt) { this.modifiedAt = modifiedAt; }
33 |
34 | // Methoden zur Berechnung der Kompetenzwerte
35 | public void calculateScores(double[][] normTable) {
36 | // Arbeitsverhalten (Items 1-10)
37 | competenceScores[0] = calculateCompetence(0, new int[]{0,1,2,3,4,5,6,7,8,9}, normTable[0]);
38 |
39 | // Lernverhalten (Items 11-20)
40 | competenceScores[1] = calculateCompetence(1, new int[]{10,11,12,13,14,15,16,17,18,19}, normTable[1]);
41 |
42 | // Sozialverhalten (Items 21-28 + 8,9)
43 | competenceScores[2] = calculateCompetence(2, new int[]{20,21,22,23,24,25,26,27,8,9}, normTable[2]);
44 |
45 | // Fachkompetenz (Items 29-36)
46 | competenceScores[3] = calculateCompetence(3, new int[]{28,29,30,31,32,33,34,35}, normTable[3]);
47 |
48 | // Personale Kompetenz
49 | competenceScores[4] = calculateCompetence(4, new int[]{0,1,5,6,7,8,9,10,11,13,14}, normTable[4]);
50 |
51 | // Methodenkompetenz
52 | competenceScores[5] = calculateCompetence(5, new int[]{2,3,4,8,9,10,16,17}, normTable[5]);
53 | }
54 |
55 | private int calculateCompetence(int index, int[] itemIndices, double[] normValues) {
56 | int sum = 0;
57 | for (int i : itemIndices) {
58 | sum += answers[i];
59 | }
60 |
61 | for (int i = 0; i < normValues.length; i++) {
62 | if (sum < normValues[i]) {
63 | return i + 1;
64 | }
65 | }
66 | return normValues.length;
67 | }
68 | }
--------------------------------------------------------------------------------
/ProfileAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.adapters;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.ImageButton;
7 | import android.widget.TextView;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.recyclerview.widget.RecyclerView;
11 |
12 | import com.example.personalitytest.R;
13 | import com.example.personalitytest.models.Profile;
14 |
15 | import java.text.SimpleDateFormat;
16 | import java.util.List;
17 | import java.util.Locale;
18 |
19 | public class ProfileAdapter extends RecyclerView.Adapter {
20 | public interface OnProfileClickListener {
21 | void onProfileClick(Profile profile);
22 | void onProfileDelete(Profile profile);
23 | }
24 |
25 | private final List profiles;
26 | private final OnProfileClickListener listener;
27 |
28 | public ProfileAdapter(List profiles, OnProfileClickListener listener) {
29 | this.profiles = profiles;
30 | this.listener = listener;
31 | }
32 |
33 | @NonNull
34 | @Override
35 | public ProfileViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
36 | View view = LayoutInflater.from(parent.getContext())
37 | .inflate(R.layout.item_profile, parent, false);
38 | return new ProfileViewHolder(view);
39 | }
40 |
41 | @Override
42 | public void onBindViewHolder(@NonNull ProfileViewHolder holder, int position) {
43 | Profile profile = profiles.get(position);
44 | holder.bind(profile, listener);
45 | }
46 |
47 | @Override
48 | public int getItemCount() {
49 | return profiles.size();
50 | }
51 |
52 | static class ProfileViewHolder extends RecyclerView.ViewHolder {
53 | private final TextView tvProfileName, tvCreatedAt;
54 | private final ImageButton btnDelete;
55 |
56 | public ProfileViewHolder(@NonNull View itemView) {
57 | super(itemView);
58 | tvProfileName = itemView.findViewById(R.id.tvProfileName);
59 | tvCreatedAt = itemView.findViewById(R.id.tvCreatedAt);
60 | btnDelete = itemView.findViewById(R.id.btnDeleteProfile);
61 | }
62 |
63 | public void bind(Profile profile, OnProfileClickListener listener) {
64 | tvProfileName.setText(profile.getName() != null ? profile.getName() : "Unbenanntes Profil");
65 |
66 | SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
67 | tvCreatedAt.setText(dateFormat.format(profile.getCreatedAt()));
68 |
69 | itemView.setOnClickListener(v -> listener.onProfileClick(profile));
70 | btnDelete.setOnClickListener(v -> listener.onProfileDelete(profile));
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/QuestionFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.fragments;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.RadioButton;
8 | import android.widget.RadioGroup;
9 | import android.widget.TextView;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.annotation.Nullable;
13 | import androidx.fragment.app.Fragment;
14 |
15 | import com.example.personalitytest.QuestionnaireActivity;
16 | import com.example.personalitytest.R;
17 |
18 | public class QuestionFragment extends Fragment {
19 | private static final String ARG_QUESTION = "question";
20 | private static final String ARG_POSITION = "position";
21 |
22 | private String question;
23 | private int position;
24 |
25 | public static QuestionFragment newInstance(String question, int position) {
26 | QuestionFragment fragment = new QuestionFragment();
27 | Bundle args = new Bundle();
28 | args.putString(ARG_QUESTION, question);
29 | args.putInt(ARG_POSITION, position);
30 | fragment.setArguments(args);
31 | return fragment;
32 | }
33 |
34 | @Override
35 | public void onCreate(@Nullable Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | if (getArguments() != null) {
38 | question = getArguments().getString(ARG_QUESTION);
39 | position = getArguments().getInt(ARG_POSITION);
40 | }
41 | }
42 |
43 | @Nullable
44 | @Override
45 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
46 | View view = inflater.inflate(R.layout.fragment_question, container, false);
47 |
48 | TextView tvQuestion = view.findViewById(R.id.tvQuestion);
49 | RadioGroup rgAnswers = view.findViewById(R.id.rgAnswers);
50 | RadioButton rbAlways = view.findViewById(R.id.rbAlways);
51 | RadioButton rbOften = view.findViewById(R.id.rbOften);
52 | RadioButton rbRarely = view.findViewById(R.id.rbRarely);
53 | RadioButton rbNever = view.findViewById(R.id.rbNever);
54 |
55 | tvQuestion.setText(question);
56 |
57 | // Vorauswahl wiederherstellen
58 | int answer = ((QuestionnaireActivity) requireActivity()).getCurrentAnswer(position);
59 | switch (answer) {
60 | case 4: rbAlways.setChecked(true); break;
61 | case 3: rbOften.setChecked(true); break;
62 | case 2: rbRarely.setChecked(true); break;
63 | case 1: rbNever.setChecked(true); break;
64 | }
65 |
66 | rgAnswers.setOnCheckedChangeListener((group, checkedId) -> {
67 | int selectedAnswer = 0;
68 | if (checkedId == R.id.rbAlways) selectedAnswer = 4;
69 | else if (checkedId == R.id.rbOften) selectedAnswer = 3;
70 | else if (checkedId == R.id.rbRarely) selectedAnswer = 2;
71 | else if (checkedId == R.id.rbNever) selectedAnswer = 1;
72 |
73 | ((QuestionnaireActivity) requireActivity()).saveAnswer(position, selectedAnswer);
74 | });
75 |
76 | return view;
77 | }
78 | }
--------------------------------------------------------------------------------
/DatenbankAnlegen.sql:
--------------------------------------------------------------------------------
1 | CREATE DATABASE personality_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2 |
3 | CREATE TABLE users (
4 | id INT AUTO_INCREMENT PRIMARY KEY,
5 | username VARCHAR(50) NOT NULL UNIQUE,
6 | email VARCHAR(100) NOT NULL UNIQUE,
7 | password_hash VARCHAR(255) NOT NULL,
8 | is_admin BOOLEAN DEFAULT FALSE,
9 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
10 | last_login TIMESTAMP NULL,
11 | INDEX idx_username (username),
12 | INDEX idx_email (email)
13 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
14 |
15 | CREATE TABLE profiles (
16 | id INT AUTO_INCREMENT PRIMARY KEY,
17 | user_id INT NOT NULL,
18 | name VARCHAR(100),
19 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
20 | modified_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
21 | item1 TINYINT DEFAULT 2,
22 | item2 TINYINT DEFAULT 2,
23 | item3 TINYINT DEFAULT 2,
24 | item4 TINYINT DEFAULT 2,
25 | item5 TINYINT DEFAULT 2,
26 | item6 TINYINT DEFAULT 2,
27 | item7 TINYINT DEFAULT 2,
28 | item8 TINYINT DEFAULT 2,
29 | item9 TINYINT DEFAULT 2,
30 | item10 TINYINT DEFAULT 2,
31 | item11 TINYINT DEFAULT 2,
32 | item12 TINYINT DEFAULT 2,
33 | item13 TINYINT DEFAULT 2,
34 | item14 TINYINT DEFAULT 2,
35 | item15 TINYINT DEFAULT 2,
36 | item16 TINYINT DEFAULT 2,
37 | item17 TINYINT DEFAULT 2,
38 | item18 TINYINT DEFAULT 2,
39 | item19 TINYINT DEFAULT 2,
40 | item20 TINYINT DEFAULT 2,
41 | item21 TINYINT DEFAULT 2,
42 | item22 TINYINT DEFAULT 2,
43 | item23 TINYINT DEFAULT 2,
44 | item24 TINYINT DEFAULT 2,
45 | item25 TINYINT DEFAULT 2,
46 | item26 TINYINT DEFAULT 2,
47 | item27 TINYINT DEFAULT 2,
48 | item28 TINYINT DEFAULT 2,
49 | item29 TINYINT DEFAULT 2,
50 | item30 TINYINT DEFAULT 2,
51 | item31 TINYINT DEFAULT 2,
52 | item32 TINYINT DEFAULT 2,
53 | item33 TINYINT DEFAULT 2,
54 | item34 TINYINT DEFAULT 2,
55 | item35 TINYINT DEFAULT 2,
56 | item36 TINYINT DEFAULT 2,
57 | FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
58 | INDEX idx_user (user_id)
59 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
60 |
61 | CREATE TABLE normSEhs (
62 | kompetenzID TINYINT PRIMARY KEY,
63 | kompetenzName VARCHAR(50) NOT NULL,
64 | p1 DECIMAL(5,2) NOT NULL,
65 | p2 DECIMAL(5,2) NOT NULL,
66 | p3 DECIMAL(5,2) NOT NULL,
67 | p4 DECIMAL(5,2) NOT NULL,
68 | p5 DECIMAL(5,2) NOT NULL
69 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
70 |
71 | INSERT INTO normSEhs (kompetenzID, kompetenzName, p1, p2, p3, p4, p5) VALUES
72 | (1, 'Arbeitsverhalten', 21.33, 25.33, 29.33, 33.32, 37.32),
73 | (2, 'Lernverhalten', 20.87, 24.95, 29.03, 33.10, 37.18),
74 | (3, 'Sozialverhalten', 17.93, 21.37, 24.80, 28.23, 31.67),
75 | (4, 'Fachkompetenz', 13.98, 17.71, 21.44, 25.17, 28.90),
76 | (5, 'Personale Kompetenz', 24.06, 28.55, 33.04, 37.53, 42.01),
77 | (6, 'Methodenkompetenz', 15.53, 18.97, 22.40, 25.83, 29.27);
78 |
79 | -- Test-User (Passwort: "test1234")
80 | INSERT INTO users (username, email, password_hash, is_admin) VALUES
81 | ('testuser', 'test@example.com', '$2$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 1);
82 |
83 | -- Test-Profil
84 | INSERT INTO profiles (user_id, name) VALUES
85 | (1, 'Mein erstes Profil');
86 |
87 |
--------------------------------------------------------------------------------
/QuestionPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.adapters;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.RadioButton;
8 | import android.widget.RadioGroup;
9 | import android.widget.TextView;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.recyclerview.widget.RecyclerView;
13 |
14 | import com.example.personalitytest.QuestionnaireActivity;
15 | import com.example.personalitytest.R;
16 |
17 | public class QuestionPagerAdapter extends RecyclerView.Adapter {
18 | private final Context context;
19 | private final String[] questions;
20 |
21 | public QuestionPagerAdapter(Context context, String[] questions) {
22 | this.context = context;
23 | this.questions = questions;
24 | }
25 |
26 | @NonNull
27 | @Override
28 | public QuestionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
29 | View view = LayoutInflater.from(context).inflate(R.layout.item_question, parent, false);
30 | return new QuestionViewHolder(view);
31 | }
32 |
33 | @Override
34 | public void onBindViewHolder(@NonNull QuestionViewHolder holder, int position) {
35 | holder.bind(questions[position], position);
36 | }
37 |
38 | @Override
39 | public int getItemCount() {
40 | return questions.length;
41 | }
42 |
43 | class QuestionViewHolder extends RecyclerView.ViewHolder {
44 | private final TextView tvQuestion;
45 | private final RadioGroup rgAnswers;
46 | private final RadioButton rbAlways, rbOften, rbRarely, rbNever;
47 |
48 | public QuestionViewHolder(@NonNull View itemView) {
49 | super(itemView);
50 | tvQuestion = itemView.findViewById(R.id.tvQuestion);
51 | rgAnswers = itemView.findViewById(R.id.rgAnswers);
52 | rbAlways = itemView.findViewById(R.id.rbAlways);
53 | rbOften = itemView.findViewById(R.id.rbOften);
54 | rbRarely = itemView.findViewById(R.id.rbRarely);
55 | rbNever = itemView.findViewById(R.id.rbNever);
56 | }
57 |
58 | public void bind(String question, int position) {
59 | tvQuestion.setText(question);
60 |
61 | // Antwort wiederherstellen, falls vorhanden
62 | int answer = ((QuestionnaireActivity) context).getCurrentAnswer(position);
63 | switch (answer) {
64 | case 4: rbAlways.setChecked(true); break;
65 | case 3: rbOften.setChecked(true); break;
66 | case 2: rbRarely.setChecked(true); break;
67 | case 1: rbNever.setChecked(true); break;
68 | default: rgAnswers.clearCheck();
69 | }
70 |
71 | rgAnswers.setOnCheckedChangeListener((group, checkedId) -> {
72 | int selectedAnswer = 0;
73 | if (checkedId == R.id.rbAlways) selectedAnswer = 4;
74 | else if (checkedId == R.id.rbOften) selectedAnswer = 3;
75 | else if (checkedId == R.id.rbRarely) selectedAnswer = 2;
76 | else if (checkedId == R.id.rbNever) selectedAnswer = 1;
77 |
78 | ((QuestionnaireActivity) context).saveAnswer(position, selectedAnswer);
79 | });
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/activity_profile.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
20 |
21 |
22 |
27 |
28 |
33 |
34 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
60 |
61 |
66 |
67 |
73 |
74 |
81 |
82 |
83 |
84 |
85 |
90 |
91 |
97 |
98 |
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # duesseldorfer-schuelerinventar
4 | GERMAN
5 | Quelloffenes Persönlichkeitsinventar
6 |
7 | Seit 2012 dient das quelloffene Düsseldorfer Schülerinventar als Lernumgebung für Studenten der Sozialwissenschaften und Auszubildende der
8 | Markt- und Sozialforschung, der Anwendungsentwicklung und der Daten- und Prozessanalyse.
9 |
10 | Das Düsseldorfer Schülerinventar ist ein offenes, gültiges, genaues und unabhängiges Persönlichkeitsinventar für Schüler
11 | der Übergangsklassen (valide, reliabel, objektiv). Das Düsseldorfer Schülerinventar ist entwicklungsoffen.
12 | Wenn Sie an einem Open-Source-Projekt mitwirken, kennen Sie das intensive, persönliche Engagement, das zum Gelingen beiträgt.
13 | Viele Nutzer wissen und schätzen das. Aus der eigenen Kraft der Entwickler gelingt aber nicht alles,
14 | zumal vielfach nur das pure Interesse am Thema oder der Umgang mit Technologien die Basis abgibt.
15 | Nicht jeder Nutzer verfügt jedoch über die Fähigkeiten und die Zeit, um ein Projekt zu unterstützen.
16 | Verbales Feedback in Form von Fehlermeldungen ist sehr hilfreich. Für andere kann eine materielle Unterstützung die einzige Möglichkeit sein,
17 | sich an Open Source zu beteiligen. Gerne spreche ich mit Ihnen über Ihre Art der Unterstützung.
18 |
19 | Ich freue mich über wissenschaftliche Reanalysen und weitere Entwicklungsteams. Gerne stelle ich zu wissenschaftlichen
20 | Zwecken die SPSS- und R-Dateien zur Verfügung. Zur Weiterentwicklung stelle ich gerne die Quellcodes der Programme zur Verfügung
21 | (PHP, MySQL, Xcode, Android Studio, Xamarin, Lazarus).
22 |
23 | /app/
24 | ├── src/
25 | │ ├── main/
26 | │ │ ├── java/com/example/personalitytest/
27 | │ │ │ ├── activities/ (Login, MainMenu, Questionnaire, Profile, Admin)
28 | │ │ │ ├── adapters/ (QuestionPager, NormTable, Profile)
29 | │ │ │ ├── fragments/ (Question, CompetenceResult)
30 | │ │ │ ├── models/ (User, Profile, NormTableItem)
31 | │ │ │ ├── utils/ (ApiClient, DatabaseHelper, PreferencesHelper)
32 | │ │ ├── res/
33 | │ │ │ ├── layout/ (alle .xml-Dateien)
34 | │ │ │ ├── values/ (strings.xml, colors.xml)
35 |
36 |
37 |
38 |
39 | +---php
40 | | deleteProfile.php
41 | | getProfiles.php
42 | | login.php
43 | | readNormTable.php
44 | | register.php
45 | | saveProfile.php
46 | | updateNormTable.php
47 |
48 |
49 |
50 |
51 | ENGLISH
52 | Open source personality inventory Since 2012, the Düsseldorf school inventory, which is open source, has served as a learning environment for social science students and trainees at Market and social research, application development and data and process analysis. The Düsseldorf student inventory is an open, valid, precise and independent personality inventory for students of the transition classes (valid, reliable, objective). The Düsseldorf student inventory is open to development. If you are involved in an open source project, you know the intense, personal commitment that makes it a pleasure to succeed. Many users know and appreciate this. However, not everything can be achieved using the developers' own strength. especially since only the pure interest in the topic or the handling of technologies provides the basis. However, not every user has the skills and the time to support a project. Verbal feedback in the form of error messages is very helpful. For others, material support can be the only option participate in open source. I would be happy to talk to you about your type of support. I look forward to scientific reanalyses and further development teams. I am happy to provide scientific Purpose of the SPSS and R files available. I am happy to provide the source code of the program for further development (PHP, MySQL, Xcode, Android Studio, Xamarin, Lazarus).
53 |
54 | #The calibration sample is made up of students from the German education system with German language skills. A translation of the items formulated in German into another language only makes sense if a new calibration sample is drawn for this language and the educational system there.
55 | Das Düsseldorfer Schülerinventar ist das einzige mir bekannte quelloffene, valide, reliable und objektive Verfahren, dessen Quellen und Quellcodes überschaubar und nachvollziehbar nachprogrammierbar sind.
56 |
57 | Ich freue mich über Erben, die die Verfahren aufgreifen, nachprogrammieren und/oder für Eigenentwicklungen davon inspirieren lassen.
58 |
59 |
60 | The Düsseldorf student inventory is the only open-source, valid, reliable and objective method that I know of, whose sources and source codes are clear and understandable and can be reprogrammed.
61 |
62 | I am happy about heirs who take up the process, reprogram it and/or let it inspire them for their own developments.
63 |
--------------------------------------------------------------------------------
/QuestionnaireActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.ProgressBar;
8 | import android.widget.TextView;
9 |
10 | import androidx.appcompat.app.AppCompatActivity;
11 | import androidx.viewpager2.widget.ViewPager2;
12 |
13 | import com.example.personalitytest.adapters.QuestionPagerAdapter;
14 | import com.example.personalitytest.models.Profile;
15 |
16 | public class QuestionnaireActivity extends AppCompatActivity {
17 | private ViewPager2 viewPager;
18 | private QuestionPagerAdapter adapter;
19 | private Button btnPrevious, btnNext;
20 | private TextView tvQuestionCounter;
21 | private ProgressBar progressBar;
22 |
23 | private static final String[] QUESTIONS = {
24 | "Zuverlaessigkeit",
25 | "Arbeitstempo",
26 | "Arbeitsplanung",
27 | "Organisationsfähigkeit",
28 | "Geschicklichkeit",
29 | "Ordnung",
30 | "Sorgfalt",
31 | "Kreativitaet",
32 | "Problemlosefaehigkeit",
33 | "Abstarktionsvermoegen",
34 | "Selbststaendigkeit",
35 | "Belastbarkeit",
36 | "Konzentrationsfaehigkeit",
37 | "Verantwortungsbewusstsein",
38 | "Eigeninitiative",
39 | "Leistungsbereitschaft",
40 | "Auffassungsgabe",
41 | "Merkfaehigkeit",
42 | "Motivationsfaehigkeit",
43 | "Reflektionsfaehigkeit",
44 | "Teamfaehigkeit",
45 | "Hilfsbereitschaft",
46 | "Kontaktfaehigkeit",
47 | "RespektvollerUmgang",
48 | "Kommunikationsfaehigkeit",
49 | "Einfuehlungsvermoegen",
50 | "Konfliktfaehigkeit",
51 | "Kritikfaehigkeit",
52 | "Schreiben",
53 | "Lesen",
54 | "Mathematik",
55 | "Naturwissenschaften",
56 | "Fremdsprachen",
57 | "Praesentationsfaehigkeit",
58 | "PC-Kenntnisse",
59 | "FaecheruebergreifendesDenken"
60 | };
61 |
62 | @Override
63 | protected void onCreate(Bundle savedInstanceState) {
64 | super.onCreate(savedInstanceState);
65 | setContentView(R.layout.activity_questionnaire);
66 |
67 | viewPager = findViewById(R.id.viewPager);
68 | btnPrevious = findViewById(R.id.btnPrevious);
69 | btnNext = findViewById(R.id.btnNext);
70 | tvQuestionCounter = findViewById(R.id.tvQuestionCounter);
71 | progressBar = findViewById(R.id.progressBar);
72 |
73 | adapter = new QuestionPagerAdapter(this, QUESTIONS);
74 | viewPager.setAdapter(adapter);
75 |
76 | setupListeners();
77 | updateUI();
78 | }
79 |
80 | private void setupListeners() {
81 | btnPrevious.setOnClickListener(v -> {
82 | if (viewPager.getCurrentItem() > 0) {
83 | viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
84 | }
85 | });
86 |
87 | btnNext.setOnClickListener(v -> {
88 | if (viewPager.getCurrentItem() < QUESTIONS.length - 1) {
89 | viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
90 | } else {
91 | finishQuestionnaire();
92 | }
93 | });
94 |
95 | viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
96 | @Override
97 | public void onPageSelected(int position) {
98 | super.onPageSelected(position);
99 | updateUI();
100 | }
101 | });
102 | }
103 |
104 | private void updateUI() {
105 | int current = viewPager.getCurrentItem() + 1;
106 | int total = QUESTIONS.length;
107 |
108 | tvQuestionCounter.setText(String.format("%d/%d", current, total));
109 | progressBar.setProgress((int) (((float) current / total) * 100));
110 |
111 | btnPrevious.setVisibility(current > 1 ? View.VISIBLE : View.INVISIBLE);
112 | btnNext.setText(current == total ? "Fertigstellen" : "Weiter");
113 | }
114 |
115 | public void saveAnswer(int questionIndex, int answer) {
116 | Profile profile = ((PersonalityTestApp) getApplication()).getCurrentProfile();
117 | if (profile != null) {
118 | profile.getAnswers()[questionIndex] = answer;
119 | }
120 | }
121 |
122 | private void finishQuestionnaire() {
123 | Profile profile = ((PersonalityTestApp) getApplication()).getCurrentProfile();
124 | if (profile != null) {
125 | profile.calculateScores(((PersonalityTestApp) getApplication()).getNormTable());
126 |
127 | new AsyncTask() {
128 | protected Boolean doInBackground(Void... params) {
129 | return saveProfileToServer(profile);
130 | }
131 | protected void onPostExecute(Boolean success) {
132 | if (success) {
133 | startActivity(new Intent(QuestionnaireActivity.this, ProfileActivity.class)
134 | .putExtra("profile_id", profile.getId()));
135 | finish();
136 | }
137 | }
138 | }.execute();
139 |
140 | Intent intent = new Intent(this, ProfileActivity.class);
141 | intent.putExtra("profile_id", profile.getId());
142 | startActivity(intent);
143 | finish();
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/RegisterActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest;
2 |
3 | import android.os.AsyncTask;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.EditText;
8 | import android.widget.ProgressBar;
9 | import android.widget.Toast;
10 |
11 | import androidx.appcompat.app.AppCompatActivity;
12 |
13 | import org.json.JSONException;
14 | import org.json.JSONObject;
15 |
16 | import java.io.BufferedReader;
17 | import java.io.IOException;
18 | import java.io.InputStreamReader;
19 | import java.io.OutputStream;
20 | import java.net.HttpURLConnection;
21 | import java.net.URL;
22 | import java.nio.charset.StandardCharsets;
23 |
24 | public class RegisterActivity extends AppCompatActivity {
25 | private EditText etUsername, etEmail, etPassword, etConfirmPassword;
26 | private Button btnRegister;
27 | private ProgressBar progressBar;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_register);
33 |
34 | etUsername = findViewById(R.id.etUsername);
35 | etEmail = findViewById(R.id.etEmail);
36 | etPassword = findViewById(R.id.etPassword);
37 | etConfirmPassword = findViewById(R.id.etConfirmPassword);
38 | btnRegister = findViewById(R.id.btnRegister);
39 | progressBar = findViewById(R.id.progressBar);
40 |
41 | btnRegister.setOnClickListener(v -> attemptRegistration());
42 | }
43 |
44 | private void attemptRegistration() {
45 | String username = etUsername.getText().toString().trim();
46 | String email = etEmail.getText().toString().trim();
47 | String password = etPassword.getText().toString();
48 | String confirmPassword = etConfirmPassword.getText().toString();
49 |
50 | if (validateInputs(username, email, password, confirmPassword)) {
51 | progressBar.setVisibility(View.VISIBLE);
52 | btnRegister.setEnabled(false);
53 |
54 | new RegisterTask().execute(username, email, password);
55 | }
56 | }
57 |
58 | private boolean validateInputs(String username, String email, String password, String confirmPassword) {
59 | if (username.isEmpty()) {
60 | etUsername.setError("Benutzername erforderlich");
61 | return false;
62 | }
63 | if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
64 | etEmail.setError("Gültige E-Mail erforderlich");
65 | return false;
66 | }
67 | if (password.isEmpty() || password.length() < 6) {
68 | etPassword.setError("Mindestens 6 Zeichen erforderlich");
69 | return false;
70 | }
71 | if (!password.equals(confirmPassword)) {
72 | etConfirmPassword.setError("Passwörter stimmen nicht überein");
73 | return false;
74 | }
75 | return true;
76 | }
77 |
78 | private class RegisterTask extends AsyncTask {
79 | private String errorMessage;
80 | private int userId;
81 |
82 | @Override
83 | protected Boolean doInBackground(String... credentials) {
84 | String username = credentials[0];
85 | String email = credentials[1];
86 | String password = credentials[2];
87 |
88 | try {
89 | String urlStr = ((PersonalityTestApp) getApplication()).getApiBaseUrl() + "register.php";
90 | URL url = new URL(urlStr);
91 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
92 | conn.setRequestMethod("POST");
93 | conn.setRequestProperty("Content-Type", "application/json");
94 | conn.setDoOutput(true);
95 |
96 | JSONObject jsonInput = new JSONObject();
97 | jsonInput.put("username", username);
98 | jsonInput.put("email", email);
99 | jsonInput.put("password", password);
100 |
101 | OutputStream os = conn.getOutputStream();
102 | os.write(jsonInput.toString().getBytes(StandardCharsets.UTF_8));
103 | os.close();
104 |
105 | int responseCode = conn.getResponseCode();
106 | if (responseCode == HttpURLConnection.HTTP_OK) {
107 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
108 | String inputLine;
109 | StringBuilder response = new StringBuilder();
110 |
111 | while ((inputLine = in.readLine()) != null) {
112 | response.append(inputLine);
113 | }
114 | in.close();
115 |
116 | JSONObject jsonResponse = new JSONObject(response.toString());
117 | if (jsonResponse.getString("status").equals("success")) {
118 | userId = jsonResponse.getInt("user_id");
119 | return true;
120 | } else {
121 | errorMessage = jsonResponse.getString("message");
122 | }
123 | }
124 | } catch (IOException | JSONException e) {
125 | errorMessage = "Verbindungsfehler: " + e.getMessage();
126 | }
127 | return false;
128 | }
129 |
130 | @Override
131 | protected void onPostExecute(Boolean success) {
132 | progressBar.setVisibility(View.GONE);
133 | btnRegister.setEnabled(true);
134 |
135 | if (success) {
136 | Toast.makeText(RegisterActivity.this,
137 | "Registrierung erfolgreich", Toast.LENGTH_SHORT).show();
138 | finish(); // Zurück zur Login-Activity
139 | } else {
140 | Toast.makeText(RegisterActivity.this,
141 | errorMessage != null ? errorMessage : "Registrierung fehlgeschlagen",
142 | Toast.LENGTH_LONG).show();
143 | }
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/DatabaseHelper.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.utils;
2 |
3 | import android.content.ContentValues;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.database.sqlite.SQLiteDatabase;
7 | import android.database.sqlite.SQLiteOpenHelper;
8 |
9 | import com.example.personalitytest.models.Profile;
10 | import com.example.personalitytest.models.User;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | public class DatabaseHelper extends SQLiteOpenHelper {
16 | private static final String DATABASE_NAME = "personality_test.db";
17 | private static final int DATABASE_VERSION = 1;
18 |
19 | // Tabellennamen
20 | private static final String TABLE_USERS = "users";
21 | private static final String TABLE_PROFILES = "profiles";
22 |
23 | // Spalten für users
24 | private static final String KEY_USER_ID = "id";
25 | private static final String KEY_USERNAME = "username";
26 | private static final String KEY_EMAIL = "email";
27 | private static final String KEY_PASSWORD_HASH = "password_hash";
28 | private static final String KEY_IS_ADMIN = "is_admin";
29 | private static final String KEY_LAST_LOGIN = "last_login";
30 |
31 | // Spalten für profiles
32 | private static final String KEY_PROFILE_ID = "id";
33 | private static final String KEY_USER_ID_FK = "user_id";
34 | private static final String KEY_PROFILE_NAME = "name";
35 | private static final String KEY_CREATED_AT = "created_at";
36 | private static final String KEY_MODIFIED_AT = "modified_at";
37 |
38 | public DatabaseHelper(Context context) {
39 | super(context, DATABASE_NAME, null, DATABASE_VERSION);
40 | }
41 |
42 | @Override
43 | public void onCreate(SQLiteDatabase db) {
44 | String CREATE_USERS_TABLE = "CREATE TABLE " + TABLE_USERS + "("
45 | + KEY_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
46 | + KEY_USERNAME + " TEXT UNIQUE,"
47 | + KEY_EMAIL + " TEXT UNIQUE,"
48 | + KEY_PASSWORD_HASH + " TEXT,"
49 | + KEY_IS_ADMIN + " INTEGER DEFAULT 0,"
50 | + KEY_LAST_LOGIN + " DATETIME"
51 | + ")";
52 |
53 | String CREATE_PROFILES_TABLE = "CREATE TABLE " + TABLE_PROFILES + "("
54 | + KEY_PROFILE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
55 | + KEY_USER_ID_FK + " INTEGER,"
56 | + KEY_PROFILE_NAME + " TEXT,"
57 | + KEY_CREATED_AT + " DATETIME,"
58 | + KEY_MODIFIED_AT + " DATETIME,"
59 | + "FOREIGN KEY(" + KEY_USER_ID_FK + ") REFERENCES " + TABLE_USERS + "(" + KEY_USER_ID + ")"
60 | + ")";
61 |
62 | db.execSQL(CREATE_USERS_TABLE);
63 | db.execSQL(CREATE_PROFILES_TABLE);
64 | }
65 |
66 | @Override
67 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
68 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_PROFILES);
69 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_USERS);
70 | onCreate(db);
71 | }
72 |
73 | // User-Methoden
74 | public long addUser(User user) {
75 | SQLiteDatabase db = this.getWritableDatabase();
76 |
77 | ContentValues values = new ContentValues();
78 | values.put(KEY_USERNAME, user.getUsername());
79 | values.put(KEY_EMAIL, user.getEmail());
80 | values.put(KEY_PASSWORD_HASH, user.getPasswordHash());
81 | values.put(KEY_IS_ADMIN, user.isAdmin() ? 1 : 0);
82 |
83 | long id = db.insert(TABLE_USERS, null, values);
84 | db.close();
85 | return id;
86 | }
87 |
88 | public User getUser(String username) {
89 | SQLiteDatabase db = this.getReadableDatabase();
90 |
91 | Cursor cursor = db.query(TABLE_USERS,
92 | new String[]{KEY_USER_ID, KEY_USERNAME, KEY_EMAIL, KEY_IS_ADMIN, KEY_LAST_LOGIN},
93 | KEY_USERNAME + "=?",
94 | new String[]{username}, null, null, null, null);
95 |
96 | if (cursor != null && cursor.moveToFirst()) {
97 | User user = new User(
98 | cursor.getInt(0),
99 | cursor.getString(1),
100 | cursor.getString(2),
101 | cursor.getInt(3) == 1
102 | );
103 | cursor.close();
104 | db.close();
105 | return user;
106 | }
107 | db.close();
108 | return null;
109 | }
110 |
111 | // Profile-Methoden
112 | public long addProfile(Profile profile) {
113 | SQLiteDatabase db = this.getWritableDatabase();
114 |
115 | ContentValues values = new ContentValues();
116 | values.put(KEY_USER_ID_FK, profile.getUserId());
117 | values.put(KEY_PROFILE_NAME, profile.getName());
118 | values.put(KEY_CREATED_AT, System.currentTimeMillis());
119 | values.put(KEY_MODIFIED_AT, System.currentTimeMillis());
120 |
121 | long id = db.insert(TABLE_PROFILES, null, values);
122 | db.close();
123 | return id;
124 | }
125 |
126 | public List getUserProfiles(int userId) {
127 | List profileList = new ArrayList<>();
128 | SQLiteDatabase db = this.getReadableDatabase();
129 |
130 | Cursor cursor = db.query(TABLE_PROFILES,
131 | new String[]{KEY_PROFILE_ID, KEY_PROFILE_NAME, KEY_CREATED_AT, KEY_MODIFIED_AT},
132 | KEY_USER_ID_FK + "=?",
133 | new String[]{String.valueOf(userId)}, null, null, KEY_CREATED_AT + " DESC", null);
134 |
135 | if (cursor.moveToFirst()) {
136 | do {
137 | Profile profile = new Profile();
138 | profile.setId(cursor.getInt(0));
139 | profile.setName(cursor.getString(1));
140 | profile.setCreatedAt(new java.util.Date(cursor.getLong(2)));
141 | profile.setModifiedAt(new java.util.Date(cursor.getLong(3)));
142 | profile.setUserId(userId);
143 |
144 | profileList.add(profile);
145 | } while (cursor.moveToNext());
146 | }
147 |
148 | cursor.close();
149 | db.close();
150 | return profileList;
151 | }
152 |
153 | // Weitere Methoden für Update, Delete, etc.
154 | }
--------------------------------------------------------------------------------
/ApiClient.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.utils;
2 |
3 | import android.content.Context;
4 | import android.net.ConnectivityManager;
5 | import android.net.NetworkInfo;
6 |
7 | import com.example.personalitytest.models.Profile;
8 | import com.example.personalitytest.models.User;
9 |
10 | import org.json.JSONException;
11 | import org.json.JSONObject;
12 |
13 | import java.io.BufferedReader;
14 | import java.io.IOException;
15 | import java.io.InputStream;
16 | import java.io.InputStreamReader;
17 | import java.io.OutputStream;
18 | import java.net.HttpURLConnection;
19 | import java.net.URL;
20 | import java.nio.charset.StandardCharsets;
21 | import java.util.Map;
22 |
23 | public class ApiClient {
24 | private static final int CONNECT_TIMEOUT = 15000; // 15 Sekunden
25 | private static final int READ_TIMEOUT = 10000; // 10 Sekunden
26 |
27 | private final Context context;
28 | private final String baseUrl;
29 |
30 | public ApiClient(Context context, String baseUrl) {
31 | this.context = context;
32 | this.baseUrl = baseUrl;
33 | }
34 |
35 | public boolean isNetworkAvailable() {
36 | ConnectivityManager connectivityManager =
37 | (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
38 | NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
39 | return activeNetworkInfo != null && activeNetworkInfo.isConnected();
40 | }
41 |
42 | public JSONObject login(String username, String password) throws IOException, JSONException {
43 | String url = baseUrl + "login.php?username=" + username + "&password=" + password;
44 | return getJsonFromUrl(url);
45 | }
46 |
47 | public JSONObject register(User user) throws IOException, JSONException {
48 | String url = baseUrl + "register.php";
49 | JSONObject jsonInput = new JSONObject();
50 | jsonInput.put("username", user.getUsername());
51 | jsonInput.put("email", user.getEmail());
52 | jsonInput.put("password", user.getPasswordHash());
53 |
54 | return postJsonToUrl(url, jsonInput);
55 | }
56 |
57 | public JSONObject saveProfile(Profile profile) throws IOException, JSONException {
58 | String url = baseUrl + "saveProfile.php";
59 | JSONObject jsonInput = new JSONObject();
60 | jsonInput.put("user_id", profile.getUserId());
61 | jsonInput.put("answers", profile.getAnswers());
62 |
63 | if (profile.getId() > 0) {
64 | jsonInput.put("profile_id", profile.getId());
65 | }
66 |
67 | return postJsonToUrl(url, jsonInput);
68 | }
69 |
70 | public JSONObject getNormTable() throws IOException, JSONException {
71 | String url = baseUrl + "readNormTable.php";
72 | return getJsonFromUrl(url);
73 | }
74 |
75 | public JSONObject getUserProfiles(int userId) throws IOException, JSONException {
76 | String url = baseUrl + "getProfiles.php?user_id=" + userId;
77 | return getJsonFromUrl(url);
78 | }
79 |
80 | private JSONObject getJsonFromUrl(String urlString) throws IOException, JSONException {
81 | HttpURLConnection conn = null;
82 | BufferedReader reader = null;
83 |
84 | try {
85 | URL url = new URL(urlString);
86 | conn = (HttpURLConnection) url.openConnection();
87 | conn.setRequestMethod("GET");
88 | conn.setConnectTimeout(CONNECT_TIMEOUT);
89 | conn.setReadTimeout(READ_TIMEOUT);
90 |
91 | int responseCode = conn.getResponseCode();
92 | if (responseCode == HttpURLConnection.HTTP_OK) {
93 | InputStream inputStream = conn.getInputStream();
94 | reader = new BufferedReader(new InputStreamReader(inputStream));
95 |
96 | StringBuilder response = new StringBuilder();
97 | String line;
98 | while ((line = reader.readLine()) != null) {
99 | response.append(line);
100 | }
101 |
102 | return new JSONObject(response.toString());
103 | } else {
104 | throw new IOException("HTTP error code: " + responseCode);
105 | }
106 | } finally {
107 | if (reader != null) {
108 | reader.close();
109 | }
110 | if (conn != null) {
111 | conn.disconnect();
112 | }
113 | }
114 | }
115 |
116 | private JSONObject postJsonToUrl(String urlString, JSONObject jsonInput) throws IOException, JSONException {
117 | HttpURLConnection conn = null;
118 | OutputStream os = null;
119 | BufferedReader reader = null;
120 |
121 | try {
122 | URL url = new URL(urlString);
123 | conn = (HttpURLConnection) url.openConnection();
124 | conn.setRequestMethod("POST");
125 | conn.setConnectTimeout(CONNECT_TIMEOUT);
126 | conn.setReadTimeout(READ_TIMEOUT);
127 | conn.setRequestProperty("Content-Type", "application/json");
128 | conn.setDoOutput(true);
129 |
130 | os = conn.getOutputStream();
131 | os.write(jsonInput.toString().getBytes(StandardCharsets.UTF_8));
132 | os.flush();
133 |
134 | int responseCode = conn.getResponseCode();
135 | if (responseCode == HttpURLConnection.HTTP_OK) {
136 | InputStream inputStream = conn.getInputStream();
137 | reader = new BufferedReader(new InputStreamReader(inputStream));
138 |
139 | StringBuilder response = new StringBuilder();
140 | String line;
141 | while ((line = reader.readLine()) != null) {
142 | response.append(line);
143 | }
144 |
145 | return new JSONObject(response.toString());
146 | } else {
147 | throw new IOException("HTTP error code: " + responseCode);
148 | }
149 | } finally {
150 | if (os != null) {
151 | os.close();
152 | }
153 | if (reader != null) {
154 | reader.close();
155 | }
156 | if (conn != null) {
157 | conn.disconnect();
158 | }
159 | }
160 | }
161 | }
--------------------------------------------------------------------------------
/NormTableAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest.adapters;
2 |
3 | import android.text.TextWatcher;
4 | import android.text.Editable;
5 |
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.EditText;
10 | import android.widget.TextView;
11 |
12 | import androidx.annotation.NonNull;
13 | import androidx.recyclerview.widget.RecyclerView;
14 |
15 | import com.example.personalitytest.models.NormTableItem;
16 | import com.example.personalitytest.R;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | public class NormTableAdapter extends RecyclerView.Adapter {
22 | private final List items;
23 | private final List modifiedItems = new ArrayList<>();
24 |
25 | public NormTableAdapter(List items) {
26 | this.items = items;
27 | }
28 |
29 | @NonNull
30 | @Override
31 | public NormTableViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
32 | View view = LayoutInflater.from(parent.getContext())
33 | .inflate(R.layout.item_norm_table, parent, false);
34 | return new NormTableViewHolder(view);
35 | }
36 |
37 | @Override
38 | public void onBindViewHolder(@NonNull NormTableViewHolder holder, int position) {
39 | NormTableItem item = items.get(position);
40 | holder.bind(item);
41 | }
42 |
43 | @Override
44 | public int getItemCount() {
45 | return items.size();
46 | }
47 |
48 | public List getModifiedItems() {
49 | return modifiedItems;
50 | }
51 |
52 | public void clearModifiedItems() {
53 | modifiedItems.clear();
54 | for (NormTableItem item : items) {
55 | item.setModified(false);
56 | }
57 | notifyDataSetChanged();
58 | }
59 |
60 | class NormTableViewHolder extends RecyclerView.ViewHolder {
61 | private final TextView tvCompetenceName;
62 | private final EditText etP1, etP2, etP3, etP4, etP5;
63 |
64 | public NormTableViewHolder(@NonNull View itemView) {
65 | super(itemView);
66 | tvCompetenceName = itemView.findViewById(R.id.tvCompetenceName);
67 | etP1 = itemView.findViewById(R.id.etP1);
68 | etP2 = itemView.findViewById(R.id.etP2);
69 | etP3 = itemView.findViewById(R.id.etP3);
70 | etP4 = itemView.findViewById(R.id.etP4);
71 | etP5 = itemView.findViewById(R.id.etP5);
72 | }
73 |
74 | public void bind(NormTableItem item) {
75 | tvCompetenceName.setText(item.getCompetenceName());
76 | etP1.setText(String.valueOf(item.getP1()));
77 | etP2.setText(String.valueOf(item.getP2()));
78 | etP3.setText(String.valueOf(item.getP3()));
79 | etP4.setText(String.valueOf(item.getP4()));
80 | etP5.setText(String.valueOf(item.getP5()));
81 |
82 | // TextWatcher für Änderungen
83 | etP1.addTextChangedListener(new SimpleTextWatcher() {
84 | @Override
85 | public void onTextChanged(CharSequence s, int start, int before, int count) {
86 | try {
87 | item.setP1(Double.parseDouble(s.toString()));
88 | if (!modifiedItems.contains(item)) {
89 | modifiedItems.add(item);
90 | }
91 | } catch (NumberFormatException e) {
92 | // Ungültige Eingabe
93 | }
94 | }
95 | });
96 |
97 |
98 | // TextWatcher für Änderungen
99 | etP2.addTextChangedListener(new SimpleTextWatcher() {
100 | @Override
101 | public void onTextChanged(CharSequence s, int start, int before, int count) {
102 | try {
103 | item.setP2(Double.parseDouble(s.toString()));
104 | if (!modifiedItems.contains(item)) {
105 | modifiedItems.add(item);
106 | }
107 | } catch (NumberFormatException e) {
108 | // Ungültige Eingabe
109 | }
110 | }
111 | });
112 |
113 |
114 | // TextWatcher für Änderungen
115 | etP3.addTextChangedListener(new SimpleTextWatcher() {
116 | @Override
117 | public void onTextChanged(CharSequence s, int start, int before, int count) {
118 | try {
119 | item.setP3(Double.parseDouble(s.toString()));
120 | if (!modifiedItems.contains(item)) {
121 | modifiedItems.add(item);
122 | }
123 | } catch (NumberFormatException e) {
124 | // Ungültige Eingabe
125 | }
126 | }
127 | });
128 |
129 |
130 | // TextWatcher für Änderungen
131 | etP4.addTextChangedListener(new SimpleTextWatcher() {
132 | @Override
133 | public void onTextChanged(CharSequence s, int start, int before, int count) {
134 | try {
135 | item.setP4(Double.parseDouble(s.toString()));
136 | if (!modifiedItems.contains(item)) {
137 | modifiedItems.add(item);
138 | }
139 | } catch (NumberFormatException e) {
140 | // Ungültige Eingabe
141 | }
142 | }
143 | });
144 |
145 |
146 | // TextWatcher für Änderungen
147 | etP5.addTextChangedListener(new SimpleTextWatcher() {
148 | @Override
149 | public void onTextChanged(CharSequence s, int start, int before, int count) {
150 | try {
151 | item.setP5(Double.parseDouble(s.toString()));
152 | if (!modifiedItems.contains(item)) {
153 | modifiedItems.add(item);
154 | }
155 | } catch (NumberFormatException e) {
156 | // Ungültige Eingabe
157 | }
158 | }
159 | });
160 |
161 |
162 | }
163 | }
164 |
165 | abstract class SimpleTextWatcher implements TextWatcher {
166 | @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
167 | @Override public void afterTextChanged(Editable s) {}
168 | }
169 | }
--------------------------------------------------------------------------------
/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest;
2 |
3 | import android.content.Intent;
4 | import android.os.AsyncTask;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.Button;
8 | import android.widget.EditText;
9 | import android.widget.ProgressBar;
10 | import android.widget.Toast;
11 |
12 | import androidx.appcompat.app.AppCompatActivity;
13 |
14 | import com.example.personalitytest.models.User;
15 |
16 | import org.json.JSONException;
17 | import org.json.JSONObject;
18 |
19 | import java.io.BufferedReader;
20 | import java.io.IOException;
21 | import java.io.InputStreamReader;
22 | import java.net.HttpURLConnection;
23 | import java.net.URL;
24 |
25 | public class LoginActivity extends AppCompatActivity {
26 | private EditText etUsername, etPassword;
27 | private Button btnLogin, btnRegister;
28 | private ProgressBar progressBar;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_login);
34 |
35 | etUsername = findViewById(R.id.etUsername);
36 | etPassword = findViewById(R.id.etPassword);
37 | btnLogin = findViewById(R.id.btnLogin);
38 | btnRegister = findViewById(R.id.btnRegister);
39 | progressBar = findViewById(R.id.progressBar);
40 |
41 | btnLogin.setOnClickListener(v -> attemptLogin());
42 | btnRegister.setOnClickListener(v -> {
43 | startActivity(new Intent(this, RegisterActivity.class));
44 | });
45 | }
46 |
47 | private void attemptLogin() {
48 | String username = etUsername.getText().toString().trim();
49 | String password = etPassword.getText().toString().trim();
50 |
51 | if (validateInputs(username, password)) {
52 | progressBar.setVisibility(View.VISIBLE);
53 | btnLogin.setEnabled(false);
54 |
55 | new LoginTask().execute(username, password);
56 | }
57 | }
58 |
59 | private boolean validateInputs(String username, String password) {
60 | if (username.isEmpty()) {
61 | etUsername.setError("Benutzername erforderlich");
62 | return false;
63 | }
64 | if (password.isEmpty()) {
65 | etPassword.setError("Passwort erforderlich");
66 | return false;
67 | }
68 | return true;
69 | }
70 |
71 | private class LoginTask extends AsyncTask {
72 | private String errorMessage;
73 |
74 | @Override
75 | protected User doInBackground(String... credentials) {
76 | String username = credentials[0];
77 | String password = credentials[1];
78 |
79 | try {
80 | String urlStr = ((PersonalityTestApp) getApplication()).getApiBaseUrl() +
81 | "login.php?username=" + username + "&password=" + password;
82 |
83 | URL url = new URL(urlStr);
84 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
85 | conn.setRequestMethod("GET");
86 |
87 | int responseCode = conn.getResponseCode();
88 | if (responseCode == HttpURLConnection.HTTP_OK) {
89 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
90 | String inputLine;
91 | StringBuilder response = new StringBuilder();
92 |
93 | while ((inputLine = in.readLine()) != null) {
94 | response.append(inputLine);
95 | }
96 | in.close();
97 |
98 | JSONObject jsonResponse = new JSONObject(response.toString());
99 | if (jsonResponse.getString("status").equals("success")) {
100 | int userId = jsonResponse.getInt("user_id");
101 | String email = jsonResponse.getString("email");
102 | boolean isAdmin = jsonResponse.getBoolean("is_admin");
103 | return new User(userId, username, email, isAdmin);
104 | } else {
105 | errorMessage = jsonResponse.getString("message");
106 | }
107 | }
108 | } catch (IOException | JSONException e) {
109 | errorMessage = "Verbindungsfehler: " + e.getMessage();
110 | }
111 | return null;
112 | }
113 |
114 | @Override
115 | protected void onPostExecute(User user) {
116 | progressBar.setVisibility(View.GONE);
117 | btnLogin.setEnabled(true);
118 |
119 | if (user != null) {
120 | onLoginSuccess(user);
121 | } else {
122 | Toast.makeText(LoginActivity.this,
123 | errorMessage != null ? errorMessage : "Login fehlgeschlagen",
124 | Toast.LENGTH_LONG).show();
125 | }
126 | }
127 | }
128 |
129 | private void onLoginSuccess(User user) {
130 | ((PersonalityTestApp) getApplication()).setCurrentUser(user);
131 |
132 | // Normtabelle laden
133 | new LoadNormTableTask().execute();
134 | }
135 |
136 | private class LoadNormTableTask extends AsyncTask {
137 | @Override
138 | protected double[][] doInBackground(Void... voids) {
139 | try {
140 | String urlStr = ((PersonalityTestApp) getApplication()).getApiBaseUrl() + "readNormTable.php";
141 | URL url = new URL(urlStr);
142 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
143 | conn.setRequestMethod("GET");
144 |
145 | int responseCode = conn.getResponseCode();
146 | if (responseCode == HttpURLConnection.HTTP_OK) {
147 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
148 | String inputLine;
149 | StringBuilder response = new StringBuilder();
150 |
151 | while ((inputLine = in.readLine()) != null) {
152 | response.append(inputLine);
153 | }
154 | in.close();
155 |
156 | JSONObject jsonResponse = new JSONObject(response.toString());
157 | if (jsonResponse.getString("status").equals("success")) {
158 | JSONArray data = jsonResponse.getJSONArray("data");
159 | double[][] normTable = new double[6][5];
160 | for (int i = 0; i < data.length(); i++) {
161 | JSONArray row = data.getJSONArray(i);
162 | for (int j = 0; j < row.length(); j++) {
163 | normTable[i][j] = row.getDouble(j);
164 | }
165 | }
166 | return normTable;
167 | }
168 | }
169 | } catch (Exception e) {
170 | e.printStackTrace();
171 | }
172 | return null;
173 | }
174 |
175 | @Override
176 | protected void onPostExecute(double[][] normTable) {
177 | if (normTable != null) {
178 | ((PersonalityTestApp) getApplication()).setNormTable(normTable);
179 | startActivity(new Intent(LoginActivity.this, MainMenuActivity.class));
180 | finish();
181 | } else {
182 | Toast.makeText(LoginActivity.this,
183 | "Normtabelle konnte nicht geladen werden",
184 | Toast.LENGTH_LONG).show();
185 | }
186 | }
187 | }
188 | }
--------------------------------------------------------------------------------
/ProfileListActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.personalitytest;
2 |
3 | import android.content.Intent;
4 | import android.os.AsyncTask;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.ProgressBar;
8 | import android.widget.Toast;
9 |
10 | import androidx.appcompat.app.AppCompatActivity;
11 | import androidx.recyclerview.widget.LinearLayoutManager;
12 | import androidx.recyclerview.widget.RecyclerView;
13 |
14 | import com.example.personalitytest.adapters.ProfileAdapter;
15 | import com.example.personalitytest.models.Profile;
16 |
17 | import org.json.JSONArray;
18 | import org.json.JSONException;
19 | import org.json.JSONObject;
20 |
21 | import java.io.BufferedReader;
22 | import java.io.IOException;
23 | import java.io.InputStreamReader;
24 | import java.net.HttpURLConnection;
25 | import java.net.URL;
26 | import java.text.SimpleDateFormat;
27 | import java.util.ArrayList;
28 | import java.util.Date;
29 | import java.util.List;
30 | import java.util.Locale;
31 |
32 | public class ProfileListActivity extends AppCompatActivity implements ProfileAdapter.OnProfileClickListener {
33 | private RecyclerView rvProfiles;
34 | private ProgressBar progressBar;
35 | private ProfileAdapter adapter;
36 | private List profiles = new ArrayList<>();
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(R.layout.activity_profile_list);
42 |
43 | rvProfiles = findViewById(R.id.rvProfiles);
44 | progressBar = findViewById(R.id.progressBar);
45 |
46 | rvProfiles.setLayoutManager(new LinearLayoutManager(this));
47 | adapter = new ProfileAdapter(profiles, this);
48 | rvProfiles.setAdapter(adapter);
49 |
50 | loadProfiles();
51 | }
52 |
53 | private void loadProfiles() {
54 | int userId = ((PersonalityTestApp) getApplication()).getCurrentUser().getId();
55 | new LoadProfilesTask().execute(userId);
56 | }
57 |
58 | @Override
59 | public void onProfileClick(Profile profile) {
60 | ((PersonalityTestApp) getApplication()).setCurrentProfile(profile);
61 | startActivity(new Intent(this, ProfileActivity.class)
62 | .putExtra("profile_id", profile.getId()));
63 | }
64 |
65 | @Override
66 | public void onProfileDelete(Profile profile) {
67 | new DeleteProfileTask().execute(profile.getId());
68 | }
69 |
70 | private class LoadProfilesTask extends AsyncTask> {
71 | private String errorMessage;
72 |
73 | @Override
74 | protected void onPreExecute() {
75 | progressBar.setVisibility(View.VISIBLE);
76 | }
77 |
78 | @Override
79 | protected List doInBackground(Integer... userIds) {
80 | int userId = userIds[0];
81 | List result = new ArrayList<>();
82 |
83 | try {
84 | String urlStr = ((PersonalityTestApp) getApplication()).getApiBaseUrl() +
85 | "getProfiles.php?user_id=" + userId;
86 | URL url = new URL(urlStr);
87 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
88 | conn.setRequestMethod("GET");
89 |
90 | int responseCode = conn.getResponseCode();
91 | if (responseCode == HttpURLConnection.HTTP_OK) {
92 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
93 | String inputLine;
94 | StringBuilder response = new StringBuilder();
95 |
96 | while ((inputLine = in.readLine()) != null) {
97 | response.append(inputLine);
98 | }
99 | in.close();
100 |
101 | JSONObject jsonResponse = new JSONObject(response.toString());
102 | if (jsonResponse.getString("status").equals("success")) {
103 | JSONArray data = jsonResponse.getJSONArray("data");
104 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
105 |
106 | for (int i = 0; i < data.length(); i++) {
107 | JSONObject item = data.getJSONObject(i);
108 | Profile profile = new Profile();
109 | profile.setId(item.getInt("id"));
110 | profile.setName(item.getString("name"));
111 |
112 | Date createdAt = dateFormat.parse(item.getString("created_at"));
113 | profile.setCreatedAt(createdAt);
114 |
115 | result.add(profile);
116 | }
117 | }
118 | }
119 | } catch (IOException | JSONException | java.text.ParseException e) {
120 | errorMessage = e.getMessage();
121 | }
122 | return result;
123 | }
124 |
125 | @Override
126 | protected void onPostExecute(List result) {
127 | progressBar.setVisibility(View.GONE);
128 |
129 | if (!result.isEmpty()) {
130 | profiles.clear();
131 | profiles.addAll(result);
132 | adapter.notifyDataSetChanged();
133 | } else if (errorMessage != null) {
134 | Toast.makeText(ProfileListActivity.this,
135 | "Fehler beim Laden: " + errorMessage, Toast.LENGTH_LONG).show();
136 | }
137 | }
138 | }
139 |
140 | private class DeleteProfileTask extends AsyncTask {
141 | private String errorMessage;
142 | private int deletedProfileId;
143 |
144 | @Override
145 | protected Boolean doInBackground(Integer... profileIds) {
146 | deletedProfileId = profileIds[0];
147 |
148 | try {
149 | String urlStr = ((PersonalityTestApp) getApplication()).getApiBaseUrl() +
150 | "deleteProfile.php?profile_id=" + deletedProfileId;
151 | URL url = new URL(urlStr);
152 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
153 | conn.setRequestMethod("DELETE");
154 |
155 | int responseCode = conn.getResponseCode();
156 | if (responseCode == HttpURLConnection.HTTP_OK) {
157 | BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
158 | String inputLine;
159 | StringBuilder response = new StringBuilder();
160 |
161 | while ((inputLine = in.readLine()) != null) {
162 | response.append(inputLine);
163 | }
164 | in.close();
165 |
166 | JSONObject jsonResponse = new JSONObject(response.toString());
167 | return jsonResponse.getString("status").equals("success");
168 | }
169 | } catch (IOException | JSONException e) {
170 | errorMessage = e.getMessage();
171 | }
172 | return false;
173 | }
174 |
175 | @Override
176 | protected void onPostExecute(Boolean success) {
177 | if (success) {
178 | // Profil aus der Liste entfernen
179 | for (int i = 0; i < profiles.size(); i++) {
180 | if (profiles.get(i).getId() == deletedProfileId) {
181 | profiles.remove(i);
182 | adapter.notifyItemRemoved(i);
183 | break;
184 | }
185 | }
186 | Toast.makeText(ProfileListActivity.this,
187 | "Profil gelöscht", Toast.LENGTH_SHORT).show();
188 | } else {
189 | Toast.makeText(ProfileListActivity.this,
190 | errorMessage != null ? "Fehler: " + errorMessage : "Löschen fehlgeschlagen",
191 | Toast.LENGTH_LONG).show();
192 | }
193 | }
194 | }
195 | }
--------------------------------------------------------------------------------