<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
- <groupId>com.triathlon-coaching.product</groupId>
- <artifactId>athletik.athletik-db</artifactId>
- <version>0.0.1-SNAPSHOT</version>
+ <artifactId>athletik.db</artifactId>
<packaging>pom</packaging>
- <name>${product.artifactId}</name>
+ <name>${project.artifactId}</name>
<description>Athletik Training DB</description>
<parent>
- <groupId>de.laktatnebel.maven</groupId>
- <artifactId>laktatnebelscript</artifactId>
- <version>2.1.9</version>
+ <groupId>com.triathlon-coaching.product</groupId>
+ <artifactId>athletik</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
</parent>
+
</project>
--- /dev/null
+insert into athletik.users values
+(default, 'oleb', 'Ole', 'training@ole-b-rosentreter.de', 'xyz'),
+(default, 'lasse', 'Lasse', 'email@lasse-gehrmann.de', 'xyz')
+;
+
+insert into athletik.tools values
+(default, 'none', 'kein', 0, 0, 0, ''),
+(default, 'Bodyweight', 'Körpergewicht', 0, 0, 0, ''),
+(default, 'Barbell', 'Langhantel', 20, 2.5, 200, 'Scheiben auf der Langhantel immer mit Klammern sichern !!!'),
+(default, 'Bumbbell', 'Kurzhantel', 10, 2.5, 70, ''),
+(default, 'Mini Dumbbell', 'Minihantel', 1, 1, 20, ''),
+(default, 'Cable', 'Kabelzug', 3.75, 2.5, 100, ''),
+(default, 'Cable', 'Seilzug', 3.75, 2.5, 100, ''),
+(default, 'Cable Row', 'Rudermaschine/Seilzug', 15, 10, 95, ''),
+(default, 'Cable Lat', 'Latzug', 15, 10, 95, ''),
+(default, 'Easy Bar', 'Curlhantel', 20, 2.5, 200, 'Scheiben auf der Curlhantel immer mit Klammern sichern !!!')
+;
+
+insert into athletik.musclegroup values
+(default, 'Upper Arms', 'Oberarme'),
+(default, 'Shoulder', 'Schultern'),
+(default, 'Chest', 'Brust'),
+(default, 'Back', 'Rücken'),
+(default, 'Waist', 'Rumpf'),
+(default, 'Hips', 'Hüfte'),
+(default, 'Tights', 'Ober-/Unterschenkel'),
+(default, 'Calves', 'Wade'),
+(default, 'Neck', 'Hals'),
+(default, 'other', 'Sonstiges')
+;
+
+insert into athletik.muscle values
+(default, 'Triceps Brachii', 'Trizeps', 'Triceps', '', 'Armstreckung', (select id from athletik.musclegroup where name_english='Upper Arms')),
+(default, 'Biceps Brachii', 'Bizeps', 'Biceps', '', 'Armbeugung', (select id from athletik.musclegroup where name_english='Upper Arms')),
+(default, 'Brachialis', '', '', '', 'Armbeugung', (select id from athletik.musclegroup where name_english='Upper Arms')),
+(default, 'Anterior Deltoid', '', '', '', 'Deltamuskel vorne', (select id from athletik.musclegroup where name_english='Shoulder')),
+(default, 'Posterior Deltoid', '', '', '', 'Deltamuskel hinten', (select id from athletik.musclegroup where name_english='Shoulder')),
+(default, 'Lateral Deltoid', '', '', '', 'Deltamuskel seitlich', (select id from athletik.musclegroup where name_english='Shoulder')),
+(default, 'Supraspinatus', '', '', '', '', (select id from athletik.musclegroup where name_english='Shoulder')),
+(default, 'Pectoralis Major Sternal', '', '', '', 'Brustmuskel groß, Ansatz am Brustbein', (select id from athletik.musclegroup where name_english='Chest')),
+(default, 'Pectoralis Major Clavicular', '', '', '', 'Brustmuskel groß, Ansatz am Schlüsselbein', (select id from athletik.musclegroup where name_english='Chest')),
+(default, 'Pectoralis Minor', '', '', '', 'Brustmuskel klein', (select id from athletik.musclegroup where name_english='Chest')),
+(default, 'Serratus Anterior', '', '', '', 'Sägemuskel', (select id from athletik.musclegroup where name_english='Chest'))
+;
+
+
+
+insert into athletik.exercise values
+(default, 'Dumbbell Lying Triceps Extension', '', '', '', 'https://exrx.net/WeightExercises/Triceps/DBLyingTriExt', (select id from athletik.tools where toolname_german='Kurzhantel')),
+(default, 'Cable Pushdown', '', '', '', 'https://exrx.net/WeightExercises/Triceps/CBPushdown', (select id from athletik.tools where toolname_german='Seilzug')),
+(default, 'Barbell Curl', '', '', '', 'https://exrx.net/WeightExercises/Biceps/BBCurl', (select id from athletik.tools where toolname_german='Curlhantel')),
+(default, 'Dumbbell Curl', '', '', '', 'https://exrx.net/WeightExercises/Biceps/DBCurl', (select id from athletik.tools where toolname_german='Kurzhantel')),
+(default, 'Cable Curl', '', '', '', 'https://exrx.net/WeightExercises/Biceps/CBCurl', (select id from athletik.tools where toolname_german='Seilzug')),
+(default, 'Dumbbell Preacher Curl', '', '', '', 'https://exrx.net/WeightExercises/Brachialis/DBPreacherCurl', (select id from athletik.tools where toolname_german='Kurzhantel')),
+(default, 'Dumbbell Shoulder Press', '', '', '', 'https://exrx.net/WeightExercises/DeltoidAnterior/DBShoulderPress', (select id from athletik.tools where toolname_german='Kurzhantel')),
+(default, 'Cable Reverse Fly', '', '', '', 'https://exrx.net/WeightExercises/DeltoidPosterior/CBStandingReverseFly', (select id from athletik.tools where toolname_german='Langhantel')),
+(default, 'Barbell Upright Row', '', '', '', 'https://exrx.net/WeightExercises/DeltoidLateral/BBUprightRow', (select id from athletik.tools where toolname_german='Langhantel')),
+(default, 'Dumbbell Front Lateral Raise', '', '', '', 'https://exrx.net/WeightExercises/Supraspinatus/DBFrontLateralRaise', (select id from athletik.tools where toolname_german='Kurzhantel')),
+(default, 'Dumbbell Bench Press', '', '', '', 'https://exrx.net/WeightExercises/PectoralSternal/DBBenchPress', (select id from athletik.tools where toolname_german='Kurzhantel')),
+(default, 'Barbell Bench Press', '', '', '', 'https://exrx.net/WeightExercises/PectoralSternal/BBBenchPress', (select id from athletik.tools where toolname_german='Langhantel')),
+(default, 'Dumbbell Incline Bench Press', '', '', '', 'https://exrx.net/WeightExercises/PectoralClavicular/DBInclineBenchPress', (select id from athletik.tools where toolname_german='Kurzhantel')),
+(default, 'Barbell Incline Bench Press', '', '', '', 'https://exrx.net/WeightExercises/PectoralClavicular/BBInclineBenchPress', (select id from athletik.tools where toolname_german='Langhantel')),
+(default, 'Cable Incline Fly', '', '', '', 'https://exrx.net/WeightExercises/PectoralClavicular/CBInclineFly', (select id from athletik.tools where toolname_german='Seilzug')),
+(default, 'Cable Standing Fly', '', '', '', 'https://exrx.net/WeightExercises/PectoralSternal/CBStandingFly', (select id from athletik.tools where toolname_german='Seilzug')),
+(default, 'Barbell Incline Shoulder Raise', '', '', '', 'https://exrx.net/WeightExercises/SerratusAnterior/BBInclineShoulderRaise', (select id from athletik.tools where toolname_german='Langhantel')),
+(default, 'Dumbbell Incline Shoulder Raise', '', '', '', 'https://exrx.net/WeightExercises/SerratusAnterior/DBInclineShoulderRaise', (select id from athletik.tools where toolname_german='Kurzhantel'))
+;
+
+
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Lying Triceps Extension'), (select id from athletik.muscle where name_latin='Triceps Brachii'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Cable Pushdown'), (select id from athletik.muscle where name_latin='Triceps Brachii'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Barbell Curl'), (select id from athletik.muscle where name_latin='Biceps Brachii'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Curl'), (select id from athletik.muscle where name_latin='Biceps Brachii'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Cable Curl'), (select id from athletik.muscle where name_latin='Biceps Brachii'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Preacher Curl'), (select id from athletik.muscle where name_latin='Brachialis'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Shoulder Press'), (select id from athletik.muscle where name_latin='Anterior Deltoid'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Cable Reverse Fly'), (select id from athletik.muscle where name_latin='Posterior Deltoid'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Barbell Upright Row'), (select id from athletik.muscle where name_latin='Lateral Deltoid'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Front Lateral Raise'), (select id from athletik.muscle where name_latin='Supraspinatus'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Bench Press'), (select id from athletik.muscle where name_latin='Pectoralis Major Sternal'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Barbell Bench Press'), (select id from athletik.muscle where name_latin='Pectoralis Major Sternal'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Incline Bench Press'), (select id from athletik.muscle where name_latin='Pectoralis Major Clavicular'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Barbell Incline Bench Press'), (select id from athletik.muscle where name_latin='Pectoralis Major Clavicular'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Cable Incline Fly'), (select id from athletik.muscle where name_latin='Pectoralis Major Clavicular'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Cable Standing Fly'), (select id from athletik.muscle where name_latin='Pectoralis Minor'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Barbell Incline Shoulder Raise'), (select id from athletik.muscle where name_latin='Serratus Anterior'));
+insert into athletik.exercise_muscle values
+((select id from athletik.exercise where name_english='Dumbbell Incline Shoulder Raise'), (select id from athletik.muscle where name_latin='Serratus Anterior'));
\ No newline at end of file
+DROP SCHEMA athletik CASCADE;
+
CREATE SCHEMA athletik;
--- Athleten
-CREATE TABLE athletik.users (
- id SERIAL not null,
- username varchar not null,
- name_user varchar not null,
- email varchar not null,
- pass varchar not null
+ALTER SCHEMA athletik OWNER TO oleb;
+
+-- athletik.tool definition
+-- Definition des Geräts, ab dem trainiert wird.
+
+CREATE TABLE athletik.tool (
+ id serial4 NOT NULL,
+ toolname_english varchar NOT NULL,
+ toolname_german varchar NOT NULL,
+ min_weight numeric(5, 2) DEFAULT 0 NOT NULL,
+ steps_weight numeric(5, 2) DEFAULT 0 NOT NULL,
+ max_weight numeric(5, 2) DEFAULT 0 NOT NULL,
+ description varchar NULL,
+ CONSTRAINT tool_pkey PRIMARY KEY (id)
);
-ALTER TABLE athletik.users ADD CONSTRAINT users_pkey PRIMARY KEY (id);
-ALTER TABLE athletik.users ADD CONSTRAINT users_ukey UNIQUE (username);
-
--- Geräte
-CREATE TABLE athletik.tools (
- id SERIAL not null,
- toolname_english varchar not null,
- toolname_german varchar not null,
- min_weight int4 not null default 0,
- steps_weight int4 not null default 0,
- description varchar default null
+-- Permissions
+
+ALTER TABLE athletik.tool OWNER TO oleb;
+GRANT ALL ON TABLE athletik.tool TO oleb;
+
+
+-- athletik.gym definition
+-- Bezeichnung des Fitnessstudios
+
+CREATE TABLE athletik.gym (
+ id serial4 NOT NULL,
+ gymname varchar NOT NULL,
+ gymlocation varchar DEFAULT NULL,
+ CONSTRAINT gym_pkey PRIMARY KEY (id)
);
-ALTER TABLE athletik.tools ADD CONSTRAINT tools_pkey PRIMARY KEY (id);
+-- Permissions
--- Muskeln
-CREATE TABLE athletik.muscle (
- id SERIAL not null,
- name_latin varchar not null,
- name_english varchar default null,
- name_german varchar default null,
- movement varchar not null
+ALTER TABLE athletik.gym OWNER TO oleb;
+GRANT ALL ON TABLE athletik.gym TO oleb;
+
+
+-- athletik.goal definition
+-- Bezeichnung des Trainingsziels
+
+CREATE TABLE athletik.goal (
+ id serial4 NOT NULL,
+ goalname varchar NOT NULL,
+ description text DEFAULT NULL,
+ CONSTRAINT goal_pkey PRIMARY KEY (id)
+);
+
+-- Permissions
+
+ALTER TABLE athletik.goal OWNER TO oleb;
+GRANT ALL ON TABLE athletik.goal TO oleb;
+
+
+-- athletik.gymtool definition
+-- Kreuztabelle aus Fitnessstudio und Gerät, da jedes Fitnessstudio andere Geräte mit anderen Gewichtsabstufungen haben kann.
+
+CREATE TABLE athletik.gymtool (
+ fk_tool int4 NOT NULL,
+ fk_gym int4 NOT NULL,
+ CONSTRAINT gymtool_ukey UNIQUE (fk_tool, fk_gym),
+ CONSTRAINT gymtool_tool_fkey FOREIGN KEY (fk_tool) REFERENCES athletik.tool(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT gymtool_gym_fkey FOREIGN KEY (fk_gym) REFERENCES athletik.gym(id) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- Permissions
+
+ALTER TABLE athletik.gymtool OWNER TO oleb;
+GRANT ALL ON TABLE athletik.gymtool TO oleb;
+
+
+
+-- athletik.athlet definition
+-- Der Athlet
+
+CREATE TABLE athletik.athlet (
+ id serial4 NOT NULL,
+ username varchar NOT NULL,
+ fullname varchar NOT NULL,
+ email varchar NOT NULL,
+ pass varchar NOT NULL,
+ CONSTRAINT athlet_pkey PRIMARY KEY (id),
+ CONSTRAINT athlet_ukey UNIQUE (username)
+);
+
+-- Permissions
+
+ALTER TABLE athletik.athlet OWNER TO oleb;
+GRANT ALL ON TABLE athletik.athlet TO oleb;
+
+
+-- athletik.athletgym definition
+-- Kreuztabelle aus Athlet und Fitnessstudio, da ein Athlet in mehreren Fitnessstudios trainieren könnte
+
+CREATE TABLE athletik.athletgym (
+ fk_athlet int4 NOT NULL,
+ fk_gym int4 NOT NULL,
+ CONSTRAINT athletgym_ukey UNIQUE (fk_athlet, fk_gym),
+ CONSTRAINT athlet_athlet_fkey FOREIGN KEY (fk_athlet) REFERENCES athletik.athlet(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT athlet_gym_fkey FOREIGN KEY (fk_gym) REFERENCES athletik.gym(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-ALTER TABLE athletik.muscle ADD CONSTRAINT muscle_pkey PRIMARY KEY (id);
+-- Permissions
+
+ALTER TABLE athletik.athletgym OWNER TO oleb;
+GRANT ALL ON TABLE athletik.athletgym TO oleb;
+
+
+
+-- athletik.exercise definition
+-- Die Übung bestehend aus Namen, Beschreibung einer Video-URL und einem Verweis, an welchem Gerät diese durchgeführt werden soll.
--- Übungen
CREATE TABLE athletik.exercise (
- id SERIAL not null,
- name_english varchar not null,
- description_english varchar default null,
- name_german varchar default null,
- description_german varchar default null,
- url_video varchar default null,
-
- fk_tool int4 not null
+ id serial4 NOT NULL,
+ name_english varchar NOT NULL,
+ description_english varchar NULL,
+ name_german varchar NULL,
+ description_german varchar NULL,
+ url_video varchar NULL,
+ fk_tool int4 NOT NULL,
+ CONSTRAINT exercise_pkey PRIMARY KEY (id),
+ CONSTRAINT exercise_tool_fkey FOREIGN KEY (fk_tool) REFERENCES athletik.tool(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-ALTER TABLE athletik.exercise ADD CONSTRAINT exercise_pkey PRIMARY KEY (id);
-ALTER TABLE athletik.exercise ADD CONSTRAINT exercise_tool_fkey FOREIGN KEY (fk_tool) REFERENCES athletik.tools(id) ON UPDATE CASCADE ON DELETE CASCADE;
-
--- Test
-CREATE TABLE athletik.test (
- fk_user int4 not null,
- fk_exercise int4 not null,
- testdate timestamp not null default now(),
- fmax decimal default 0
+-- Permissions
+
+ALTER TABLE athletik.exercise OWNER TO oleb;
+GRANT ALL ON TABLE athletik.exercise TO oleb;
+
+
+-- athletik.muscle definition
+-- Name und Beschreibung der Muskeln
+
+CREATE TABLE athletik.muscle (
+ id serial4 NOT NULL,
+ muscle_name_latin varchar NOT NULL,
+ muscle_name_english varchar NULL,
+ muscle_name_german varchar NULL,
+ movement_english varchar NOT NULL,
+ movement_german varchar NOT NULL,
+ musclegroup_name_english varchar NULL,
+ musclegroup_name_german varchar NULL,
+ CONSTRAINT muscle_pkey PRIMARY KEY (id)
);
-ALTER TABLE athletik.test ADD CONSTRAINT test_ukey UNIQUE (fk_exercise, fk_user, testdate);
+-- Permissions
+
+ALTER TABLE athletik.muscle OWNER TO oleb;
+GRANT ALL ON TABLE athletik.muscle TO oleb;
-ALTER TABLE athletik.test ADD CONSTRAINT test_exercise_fkey FOREIGN KEY (fk_exercise) REFERENCES athletik.exercise(id) ON UPDATE CASCADE ON DELETE CASCADE;
-ALTER TABLE athletik.test ADD CONSTRAINT test_user_fkey FOREIGN KEY (fk_user) REFERENCES athletik.users(id) ON UPDATE CASCADE ON DELETE CASCADE;
--- Protokoll
+-- athletik.protokoll definition
+-- In dieser Tabelle werden die Test- und Trainingsaktivitäten persistiert. Je nach Modus (Test oder Training) werden Spalten leergelassen.
+
CREATE TABLE athletik.protokoll (
- fk_user int4 not null,
- fk_exercise int4 not null,
- trainingdate timestamp not null default now(),
- number_of_set int4 default 1,
- repetitions int4 default 1,
- weight int4 default 0
+ fk_athlet int4 NOT NULL,
+ fk_exercise int4 NOT NULL,
+ trainingdate timestamp DEFAULT now() NOT NULL,
+ number_of_set int4 DEFAULT 1,
+ repetitions int4 DEFAULT 1,
+ weight numeric(5, 2) DEFAULT 0,
+ is_test boolean DEFAULT FALSE,
+ CONSTRAINT protokoll_ukey UNIQUE (fk_exercise, fk_athlet, trainingdate, number_of_set),
+ CONSTRAINT protokoll_exercise_fkey FOREIGN KEY (fk_exercise) REFERENCES athletik.exercise(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT protokoll_athlet_fkey FOREIGN KEY (fk_athlet) REFERENCES athletik.athlet(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-ALTER TABLE athletik.protokoll ADD CONSTRAINT protokoll_ukey UNIQUE (fk_exercise, fk_user, trainingdate, number_of_set);
+-- Permissions
-ALTER TABLE athletik.protokoll ADD CONSTRAINT protokoll_exercise_fkey FOREIGN KEY (fk_exercise) REFERENCES athletik.exercise(id) ON UPDATE CASCADE ON DELETE CASCADE;
-ALTER TABLE athletik.protokoll ADD CONSTRAINT protokoll_user_fkey FOREIGN KEY (fk_user) REFERENCES athletik.users(id) ON UPDATE CASCADE ON DELETE CASCADE;
+ALTER TABLE athletik.protokoll OWNER TO oleb;
+GRANT ALL ON TABLE athletik.protokoll TO oleb;
+
+
+-- athletik.log definition
+-- In der Logtabelle werden die Aktivitäten der Software gespeichert
+
+CREATE TABLE athletik.log (
+ id serial4 NOT NULL,
+ created timestamp DEFAULT now() NOT NULL,
+ logdata text NOT NULL,
+ fk_athlet int4 NOT NULL,
+ sid text NOT NULL,
+ script varchar NOT NULL,
+ CONSTRAINT sqllog_pkey PRIMARY KEY (id),
+ CONSTRAINT sqllog_athlet_fkey FOREIGN KEY (fk_athlet) REFERENCES athletik.athlet(id) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- Permissions
+
+ALTER TABLE athletik.log OWNER TO oleb;
+GRANT ALL ON TABLE athletik.log TO oleb;
+
+
+-- athletik.training definition
+-- Diese Tabelle verknüpft den Athleten, die Übungen und das Trainingsziel, die er durchführen kann und stellt damit ein Trainingsprogramm dar.
+-- Dabei werden Gewicht, Sätze und Wiederholungen ergänzt.
+-- Die Zeitstempel versionieren das Ganze.
--- Trainingspläne
CREATE TABLE athletik.training (
- id SERIAL not null,
- title varchar not null,
- description text default null,
- fk_user int4 not null,
- fk_exercise int4 not null,
- repetitions_of_set int4 default 1,
- repetitions int4 default 1,
- factor_of_fmax int4 default 0,
- created timestamp not null default now(),
- valid_since timestamp not null default now()
+ id serial4 NOT NULL,
+ title varchar NOT NULL,
+ fk_goal int4 NOT NULL, -- Zweck des Trainings. Kraftausdauer, Schnellkraft, ...
+ description text NULL,
+ fk_athlet int4 NOT NULL,
+ fk_exercise int4 NOT NULL,
+ repetitions_of_set int4 DEFAULT 1 NULL,
+ repetitions int4 DEFAULT 1 NULL,
+ factor_of_fmax numeric(5, 2) DEFAULT 0 NULL,
+ created timestamp DEFAULT now() NOT NULL,
+ valid_since timestamp DEFAULT now() NOT NULL,
+ CONSTRAINT training_ukey UNIQUE (fk_exercise, fk_athlet, repetitions_of_set, repetitions, factor_of_fmax),
+ CONSTRAINT training_goal_fkey FOREIGN KEY (fk_goal) REFERENCES athletik.goal(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT training_exercise_fkey FOREIGN KEY (fk_exercise) REFERENCES athletik.exercise(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT training_athlet_fkey FOREIGN KEY (fk_athlet) REFERENCES athletik.athlet(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-ALTER TABLE athletik.training ADD CONSTRAINT training_ukey UNIQUE (fk_exercise, fk_user, repetitions_of_set, repetitions, factor_of_fmax);
+-- Permissions
+
+ALTER TABLE athletik.training OWNER TO oleb;
+GRANT ALL ON TABLE athletik.training TO oleb;
+
-ALTER TABLE athletik.training ADD CONSTRAINT training_exercise_fkey FOREIGN KEY (fk_exercise) REFERENCES athletik.exercise(id) ON UPDATE CASCADE ON DELETE CASCADE;
-ALTER TABLE athletik.training ADD CONSTRAINT training_user_fkey FOREIGN KEY (fk_user) REFERENCES athletik.users(id) ON UPDATE CASCADE ON DELETE CASCADE;
+-- athletik.exercise_muscle definition
+-- Eine Kreuztabelle, die Übungen und Muskeln zusammenführt.
+-- Eine Übung ist meistens für mehrere Muskeln geeinet, aber für wenige primär.
--- Log
-CREATE TABLE athletik.sqllog (
- id SERIAL not null,
- created timestamp not null default now(),
- sql text not null,
- fk_user int4 not null,
- sid text not null,
- script varchar not null
+CREATE TABLE athletik.exercise_muscle (
+ fk_exercise int4 NOT NULL,
+ fk_muscle int4 NOT NULL,
+ isprimary boolean DEFAULT false,
+ CONSTRAINT exercise_muscle_ukey UNIQUE (fk_exercise, fk_muscle),
+ CONSTRAINT exercise_muscle_exercise_fkey FOREIGN KEY (fk_exercise) REFERENCES athletik.exercise(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT exercise_muscle_muscle_fkey FOREIGN KEY (fk_muscle) REFERENCES athletik.muscle(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-ALTER TABLE athletik.sqllog ADD CONSTRAINT sqllog_pkey PRIMARY KEY (id);
-
-ALTER TABLE athletik.sqllog ADD CONSTRAINT sqllog_user_fkey FOREIGN KEY (fk_user) REFERENCES athletik.users(id) ON UPDATE CASCADE ON DELETE CASCADE;
+-- Permissions
+ALTER TABLE athletik.exercise_muscle OWNER TO oleb;
+GRANT ALL ON TABLE athletik.exercise_muscle TO oleb;
+-- athletik.view_allexercises source
--- ALTER SCHEMA athletik OWNER TO laktatnebel;
+CREATE OR REPLACE VIEW athletik.view_allexercises
+AS SELECT e.id AS id_exercise,
+ e.name_english,
+ e.description_english,
+ e.name_german,
+ e.description_german,
+ e.url_video,
+ t.id AS id_tool,
+ t.toolname_english,
+ t.toolname_german,
+ t.min_weight,
+ t.max_weight,
+ t.steps_weight,
+ t.description,
+ em.isprimary,
+ m.id,
+ m.muscle_name_latin,
+ m.muscle_name_english,
+ m.muscle_name_german,
+ m.movement_english,
+ m.movement_german,
+ m.musclegroup_name_english,
+ m.musclegroup_name_german
+ FROM athletik.exercise_muscle em
+ JOIN athletik.muscle m ON m.id = em.fk_muscle
+ JOIN athletik.exercise e ON e.id = em.fk_exercise
+ JOIN athletik.tool t ON t.id = e.fk_tool;
--- ALTER TABLE athletik.users OWNER TO laktatnebel;
--- ALTER TABLE athletik.tools OWNER TO laktatnebel;
--- ALTER TABLE athletik.muscle OWNER TO laktatnebel;
--- ALTER TABLE athletik.exercise OWNER TO laktatnebel;
--- ALTER TABLE athletik.test OWNER TO laktatnebel;
--- ALTER TABLE athletik.protokoll OWNER TO laktatnebel;
--- ALTER TABLE athletik.training OWNER TO laktatnebel;
--- ALTER TABLE athletik.sqllog OWNER TO laktatnebel;
+-- Permissions
--- GRANT ALL ON SCHEMA athletik TO laktatnebel;
+ALTER TABLE athletik.view_allexercises OWNER TO oleb;
+GRANT ALL ON TABLE athletik.view_allexercises TO oleb;
-ALTER SCHEMA athletik OWNER TO oleb;
+-- athletik.view_musclegroups source
-ALTER TABLE athletik.users OWNER TO oleb;
-ALTER TABLE athletik.tools OWNER TO oleb;
-ALTER TABLE athletik.muscle OWNER TO oleb;
-ALTER TABLE athletik.exercise OWNER TO oleb;
-ALTER TABLE athletik.test OWNER TO oleb;
-ALTER TABLE athletik.protokoll OWNER TO oleb;
-ALTER TABLE athletik.training OWNER TO oleb;
-ALTER TABLE athletik.sqllog OWNER TO oleb;
+CREATE OR REPLACE VIEW athletik.view_musclegroups
+AS SELECT DISTINCT
+ m.musclegroup_name_english,
+ m.musclegroup_name_german
+ FROM athletik.muscle m;
+
+-- Permissions
+
+ALTER TABLE athletik.view_musclegroups OWNER TO oleb;
+GRANT ALL ON TABLE athletik.view_musclegroups TO oleb;
+
+
+-- athletik.view_muscles source
+
+CREATE OR REPLACE VIEW athletik.view_muscles
+AS SELECT m.id,
+ m.muscle_name_latin,
+ m.muscle_name_english,
+ m.muscle_name_german,
+ m.movement_english,
+ m.movement_german,
+ m.musclegroup_name_english,
+ m.musclegroup_name_german
+ FROM athletik.muscle m;
+
+-- Permissions
+
+ALTER TABLE athletik.view_muscles OWNER TO oleb;
+GRANT ALL ON TABLE athletik.view_muscles TO oleb;
+
+
+-- athletik.view_protokollsetsoftoday source
+
+CREATE OR REPLACE VIEW athletik.view_protokollsetsoftoday
+AS SELECT fk_athlet,
+ fk_exercise,
+ trainingdate,
+ number_of_set
+ FROM athletik.protokoll p;
+
+-- Permissions
+
+ALTER TABLE athletik.view_protokollsetsoftoday OWNER TO oleb;
+GRANT ALL ON TABLE athletik.view_protokollsetsoftoday TO oleb;
+
+
+-- athletik.view_tool source
+
+CREATE OR REPLACE VIEW athletik.view_tool
+AS SELECT id,
+ toolname_english,
+ toolname_german,
+ min_weight,
+ steps_weight,
+ max_weight,
+ description
+ FROM athletik.tool t;
+
+-- Permissions
+
+ALTER TABLE athletik.view_tool OWNER TO oleb;
+GRANT ALL ON TABLE athletik.view_tool TO oleb;
+
+
+-- athletik.view_toolweights source
+
+CREATE OR REPLACE VIEW athletik.view_toolweights
+AS SELECT id,
+ min_weight,
+ steps_weight,
+ max_weight
+ FROM athletik.tool t;
+
+-- Permissions
+
+ALTER TABLE athletik.view_toolweights OWNER TO oleb;
+GRANT ALL ON TABLE athletik.view_toolweights TO oleb;
+
+
+-- athletik.view_athlet source
+
+CREATE OR REPLACE VIEW athletik.view_athlet
+AS SELECT id,
+ username,
+ fullname,
+ email,
+ pass
+ FROM athletik.athlet u;
+
+-- Permissions
+
+ALTER TABLE athletik.view_athlet OWNER TO oleb;
+GRANT ALL ON TABLE athletik.view_athlet TO oleb;
GRANT ALL ON SCHEMA athletik TO oleb;
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>athletik.service</artifactId>
+
+ <name>${project.artifactId}</name>
+ <description>Athletik Training Sevice</description>
+
+ <parent>
+ <groupId>com.triathlon-coaching.product</groupId>
+ <artifactId>athletik</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </parent>
+
+ <dependencyManagement>
+ <dependencies>
+ <!-- Spring Boot -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <!-- Common Dependencies -->
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>${postgresql.version}</version>
+ </dependency>
+
+ <!-- JEE -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${javax.servlet-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${hibernate-core.version}</version>
+ </dependency>
+
+ <!-- Mail -->
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>javax.mail-api</artifactId>
+ <version>${javax.mail.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.mail</groupId>
+ <artifactId>javax.mail</artifactId>
+ <version>${javax.mail.version}</version>
+ </dependency>
+
+ <!-- Spring -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ <version>${springframework.version}</version>
+ </dependency>
+
+ <!-- JPA -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ <version>${spring-boot.version}</version>
+ </dependency>
+
+ <!-- Lombok -->
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>${lombok.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Validation -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ <version>${spring-boot.version}</version>
+ </dependency>
+
+ <!-- Security -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ <version>${spring-boot.version}</version>
+ </dependency>
+
+ <!-- Email -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-mail</artifactId>
+ <version>${spring-boot.version}</version>
+ </dependency>
+
+ <!-- Thymeleaf -->
+ <!-- WebUI-->
+ <dependency>
+ <groupId>org.thymeleaf</groupId>
+ <artifactId>thymeleaf-spring5</artifactId>
+ <version>${thymeleaf.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>de.laktatnebel.libs</groupId>
+ <artifactId>utillib</artifactId>
+ <version>${utillib.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+
+ <dependencies>
+
+ <!-- Common Dependencies -->
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ </dependency>
+
+ <!-- JEE -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ </dependency>
+
+ <!-- Servlet API (provided by Tomcat) -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Mail -->
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>javax.mail-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.mail</groupId>
+ <artifactId>javax.mail</artifactId>
+ </dependency>
+
+ <!-- Spring -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ </dependency>
+
+ <!-- JPA -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+
+ <!-- Lombok -->
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ </dependency>
+
+ <!-- Validation -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+
+ <!-- Security -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ </dependency>
+
+ <!-- Email -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-mail</artifactId>
+ </dependency>
+
+ <!-- Test -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- Thymeleaf -->
+ <!-- WebUI-->
+ <dependency>
+ <groupId>org.thymeleaf</groupId>
+ <artifactId>thymeleaf-spring5</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>de.laktatnebel.libs</groupId>
+ <artifactId>utillib</artifactId>
+ </dependency>
+ </dependencies>
+
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <configuration>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>${maven-javadoc-plugin.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <version>${maven-enforcer-plugin.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>${maven-source-plugin.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>${maven-deploy-plugin.version}</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>${maven-release-plugin.version}</version>
+ <configuration>
+ <branchName>develop</branchName>
+ <pushChanges>false</pushChanges>
+ <localCheckout>true</localCheckout>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>${maven-site-plugin.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>site</goal>
+ </goals>
+ <configuration>
+ <!--
+ <reportPlugins>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ </plugin>
+ </reportPlugins>
+ -->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalparam>${javadoc.opts}</additionalparam>
+ <doclint>none</doclint>
+ </configuration>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <additionalparam>${javadoc.opts}</additionalparam>
+ <doclint>none</doclint>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <release>${java.version}</release>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-versions</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <!--
+ http://maven.apache.org/enforcer/enforcer-rules/versionRanges.html
+ -->
+ <rules>
+ <requireMavenVersion>
+ <version>[3.0,)</version>
+ </requireMavenVersion>
+ <requireJavaVersion>
+ <version>${java.version}</version>
+ </requireJavaVersion>
+ </rules>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.tomcat.maven</groupId>
+ <artifactId>tomcat7-maven-plugin</artifactId>
+ <version>2.0</version>
+ <configuration>
+ <server>localtomcat</server>
+ <url>http://localhost:8080/manager/text</url>
+ <!-- path>/${project.build.finalName}</path -->
+ <update>true</update>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>
+ ${project.groupId}.${project.artifactId}.AthletikBackendApplication</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
+
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@EntityScan("com.triathlon_coaching.product.athletik.models")
+@EnableJpaRepositories("com.triathlon_coaching.product.athletik.backend.repositories")
+@ComponentScan({"com.triathlon_coaching.product.athletik.backend", "com.triathlon_coaching.product.athletik.services"})
+public class AthletikBackendApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(AthletikBackendApplication.class, args);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.config;
+
+import com.triathlon_coaching.product.athletik.backend.service.AthletService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+
+import javax.sql.DataSource;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Autowired
+ private AthletService athletService;
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new PasswordEncoder() {
+ @Override
+ public String encode(CharSequence rawPassword) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-512");
+ byte[] hash = digest.digest(rawPassword.toString().getBytes());
+ StringBuilder hexString = new StringBuilder();
+ for (byte b : hash) {
+ String hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1)
+ hexString.append('0');
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("SHA-512 Algorithmus nicht verfügbar", e);
+ }
+ }
+
+ @Override
+ public boolean matches(CharSequence rawPassword, String encodedPassword) {
+ return encode(rawPassword).equals(encodedPassword);
+ }
+ };
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.jdbcAuthentication().dataSource(dataSource)
+ .usersByUsernameQuery("SELECT username, pass, true FROM athletik.athlet WHERE username = ?")
+ .authoritiesByUsernameQuery("SELECT username, 'USER' FROM athletik.athlet WHERE username = ?")
+ .passwordEncoder(passwordEncoder());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests().antMatchers("/", "/home", "/api/auth/register", "/css/**", "/js/**", "/img/**")
+ .permitAll().anyRequest().authenticated().and().formLogin().loginPage("/login")
+ .defaultSuccessUrl("/training", true).permitAll().and().logout()
+ .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login?logout")
+ .permitAll().and().csrf().ignoringAntMatchers("/api/**") // CSRF für API-Endpunkte deaktivieren
+ .and().sessionManagement().sessionFixation().migrateSession();
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Athlet;
+import com.triathlon_coaching.product.athletik.backend.service.AthletService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpSession;
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/athleten")
+public class AthletController {
+
+ @Autowired
+ private AthletService athletService;
+
+ @GetMapping
+ public ResponseEntity<List<Athlet>> getAllAthleten() {
+ List<Athlet> athleten = athletService.findAllAthleten();
+ return ResponseEntity.ok(athleten);
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity<Athlet> getAthletById(@PathVariable Long id) {
+ Optional<Athlet> athlet = athletService.findAthletById(id);
+ return athlet.map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/username/{username}")
+ public ResponseEntity<Athlet> getAthletByUsername(@PathVariable String username) {
+ Optional<Athlet> athlet = athletService.findAthletByUsername(username);
+ return athlet.map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/email/{email}")
+ public ResponseEntity<Athlet> getAthletByEmail(@PathVariable String email) {
+ Optional<Athlet> athlet = athletService.findAthletByEmail(email);
+ return athlet.map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/gym/{gymId}")
+ public ResponseEntity<List<Athlet>> getAthletenByGymId(@PathVariable Long gymId) {
+ List<Athlet> athleten = athletService.findAthletenByGymId(gymId);
+ return ResponseEntity.ok(athleten);
+ }
+
+ @PostMapping
+ public ResponseEntity<?> createAthlet(@Valid @RequestBody Athlet athlet) {
+ if (athletService.existsByUsername(athlet.getUsername())) {
+ return ResponseEntity.badRequest().body("Username already exists");
+ }
+ if (athletService.existsByEmail(athlet.getEmail())) {
+ return ResponseEntity.badRequest().body("Email already exists");
+ }
+
+ Athlet savedAthlet = athletService.saveAthlet(athlet);
+ return ResponseEntity.ok(savedAthlet);
+ }
+
+ @PutMapping("/{id}")
+ public ResponseEntity<Athlet> updateAthlet(@PathVariable Long id, @Valid @RequestBody Athlet athletDetails) {
+ Optional<Athlet> athletOptional = athletService.findAthletById(id);
+ if (!athletOptional.isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+
+ Athlet athlet = athletOptional.get();
+ athlet.setFullname(athletDetails.getFullname());
+ athlet.setEmail(athletDetails.getEmail());
+ // Passwort sollte separat geupdated werden
+
+ Athlet updatedAthlet = athletService.saveAthlet(athlet);
+ return ResponseEntity.ok(updatedAthlet);
+ }
+
+ @PutMapping("/{id}/password")
+ public ResponseEntity<?> updatePassword(@PathVariable Long id,
+ @RequestParam String currentPassword,
+ @RequestParam String newPassword) {
+ Optional<Athlet> athletOptional = athletService.findAthletById(id);
+ if (!athletOptional.isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+
+ boolean success = athletService.updatePassword(id, currentPassword, newPassword);
+ if (success) {
+ return ResponseEntity.ok().build();
+ } else {
+ return ResponseEntity.badRequest().body("Current password is incorrect");
+ }
+ }
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity<Void> deleteAthlet(@PathVariable Long id) {
+ if (!athletService.findAthletById(id).isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+ athletService.deleteAthlet(id);
+ return ResponseEntity.noContent().build();
+ }
+
+ @PostMapping("/{id}/deactivate")
+ public ResponseEntity<Void> deactivateAthlet(@PathVariable Long id) {
+ athletService.deactivateAthlet(id);
+ return ResponseEntity.ok().build();
+ }
+
+ @PostMapping("/{id}/activate")
+ public ResponseEntity<Void> activateAthlet(@PathVariable Long id) {
+ athletService.activateAthlet(id);
+ return ResponseEntity.ok().build();
+ }
+
+ @GetMapping("/profile")
+ public ResponseEntity<Athlet> getProfile(HttpSession session) {
+ Athlet athlet = (Athlet) session.getAttribute("athlet");
+ if (athlet == null) {
+ return ResponseEntity.status(401).build();
+ }
+ return ResponseEntity.ok(athlet);
+ }
+
+ @PutMapping("/profile")
+ public ResponseEntity<Athlet> updateProfile(@Valid @RequestBody Athlet athletDetails, HttpSession session) {
+ Athlet currentAthlet = (Athlet) session.getAttribute("athlet");
+ if (currentAthlet == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ currentAthlet.setFullname(athletDetails.getFullname());
+ currentAthlet.setEmail(athletDetails.getEmail());
+
+ Athlet updatedAthlet = athletService.saveAthlet(currentAthlet);
+ session.setAttribute("athlet", updatedAthlet);
+ return ResponseEntity.ok(updatedAthlet);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Athlet;
+import com.triathlon_coaching.product.athletik.backend.service.AthletService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpSession;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+ @Autowired
+ private AthletService athletService;
+
+ @PostMapping("/login")
+ public ResponseEntity<?> login(@RequestParam String username,
+ @RequestParam String password,
+ HttpSession session) {
+ Optional<Athlet> athlet = athletService.authenticate(username, password);
+ if (athlet.isPresent()) {
+ session.setAttribute("athlet", athlet.get());
+ return ResponseEntity.ok(athlet.get());
+ }
+ return ResponseEntity.status(401).body("Ungültige Anmeldedaten");
+ }
+
+ @PostMapping("/register")
+ public ResponseEntity<?> register(@RequestBody Athlet athlet) {
+ Optional<Athlet> newAthlet = athletService.registerAthlet(athlet);
+ if (newAthlet.isPresent()) {
+ return ResponseEntity.ok(newAthlet.get());
+ }
+ return ResponseEntity.badRequest().body("Benutzername oder E-Mail bereits vergeben");
+ }
+
+ @PostMapping("/logout")
+ public ResponseEntity<?> logout(HttpSession session) {
+ session.invalidate();
+ return ResponseEntity.ok("Abgemeldet");
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Exercise;
+import com.triathlon_coaching.product.athletik.backend.model.Muscle;
+import com.triathlon_coaching.product.athletik.backend.service.ExerciseService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/api/exercises")
+public class ExerciseController {
+
+ @Autowired
+ private ExerciseService exerciseService;
+
+ @GetMapping
+ public ResponseEntity<List<Exercise>> getAllExercises() {
+ List<Exercise> exercises = exerciseService.findAllExercises();
+ return ResponseEntity.ok(exercises);
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity<Exercise> getExerciseById(@PathVariable Long id) {
+ return exerciseService.findExerciseById(id)
+ .map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/musclegroup/{muscleGroup}")
+ public ResponseEntity<List<Exercise>> getExercisesByMuscleGroup(@PathVariable String muscleGroup) {
+ List<Exercise> exercises = exerciseService.findExercisesByMuscleGroup(muscleGroup);
+ return ResponseEntity.ok(exercises);
+ }
+
+ @GetMapping("/muscle/{muscleId}")
+ public ResponseEntity<List<Exercise>> getExercisesByMuscleId(@PathVariable Long muscleId) {
+ List<Exercise> exercises = exerciseService.findExercisesByMuscleId(muscleId);
+ return ResponseEntity.ok(exercises);
+ }
+
+ @GetMapping("/musclegroups")
+ public ResponseEntity<List<String>> getAllMuscleGroups() {
+ List<String> muscleGroups = exerciseService.findAllMuscleGroups();
+ return ResponseEntity.ok(muscleGroups);
+ }
+
+ @GetMapping("/muscles")
+ public ResponseEntity<List<Muscle>> getAllMuscles() {
+ List<Muscle> muscles = exerciseService.findAllMuscles();
+ return ResponseEntity.ok(muscles);
+ }
+
+ @GetMapping("/muscles/group/{muscleGroup}")
+ public ResponseEntity<List<Muscle>> getMusclesByGroup(@PathVariable String muscleGroup) {
+ List<Muscle> muscles = exerciseService.findMusclesByGroup(muscleGroup);
+ return ResponseEntity.ok(muscles);
+ }
+
+ @GetMapping("/tools/weights/{toolId}")
+ public ResponseEntity<List<Double>> getWeightsForTool(@PathVariable Long toolId) {
+ List<Double> weights = exerciseService.getWeightsForTool(toolId);
+ return ResponseEntity.ok(weights);
+ }
+
+ @GetMapping("/summary")
+ public ResponseEntity<Map<String, Object>> getExerciseSummary() {
+ Map<String, Object> summary = exerciseService.getExerciseSummary();
+ return ResponseEntity.ok(summary);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Goal;
+import com.triathlon_coaching.product.athletik.backend.service.GoalService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/goals")
+public class GoalController {
+
+ @Autowired
+ private GoalService goalService;
+
+ @GetMapping
+ public ResponseEntity<List<Goal>> getAllGoals() {
+ List<Goal> goals = goalService.findAllGoals();
+ return ResponseEntity.ok(goals);
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity<Goal> getGoalById(@PathVariable Long id) {
+ Optional<Goal> goal = goalService.findGoalById(id);
+ return goal.map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/name/{goalname}")
+ public ResponseEntity<Goal> getGoalByName(@PathVariable String goalname) {
+ Optional<Goal> goal = goalService.findGoalByName(goalname);
+ return goal.map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/athlet/{athletId}")
+ public ResponseEntity<List<Goal>> getGoalsByAthletId(@PathVariable Long athletId) {
+ List<Goal> goals = goalService.findGoalsByAthletId(athletId);
+ return ResponseEntity.ok(goals);
+ }
+
+ @GetMapping("/exercise/{exerciseId}")
+ public ResponseEntity<List<Goal>> getGoalsByExerciseId(@PathVariable Long exerciseId) {
+ List<Goal> goals = goalService.findGoalsByExerciseId(exerciseId);
+ return ResponseEntity.ok(goals);
+ }
+
+ @GetMapping("/available/athlet/{athletId}")
+ public ResponseEntity<List<Goal>> getAvailableGoalsForAthlet(@PathVariable Long athletId) {
+ List<Goal> goals = goalService.findAvailableGoalsForAthlet(athletId);
+ return ResponseEntity.ok(goals);
+ }
+
+ @GetMapping("/search")
+ public ResponseEntity<List<Goal>> searchGoals(@RequestParam String q) {
+ List<Goal> goals = goalService.searchGoals(q);
+ return ResponseEntity.ok(goals);
+ }
+
+ @PostMapping
+ public ResponseEntity<Goal> createGoal(@Valid @RequestBody Goal goal) {
+ if (goalService.existsByName(goal.getGoalname())) {
+ return ResponseEntity.badRequest().build();
+ }
+ Goal savedGoal = goalService.saveGoal(goal);
+ return ResponseEntity.ok(savedGoal);
+ }
+
+ @PutMapping("/{id}")
+ public ResponseEntity<Goal> updateGoal(@PathVariable Long id, @Valid @RequestBody Goal goalDetails) {
+ Optional<Goal> goalOptional = goalService.findGoalById(id);
+ if (!goalOptional.isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+
+ Goal goal = goalOptional.get();
+ goal.setGoalname(goalDetails.getGoalname());
+ goal.setDescription(goalDetails.getDescription());
+
+ Goal updatedGoal = goalService.saveGoal(goal);
+ return ResponseEntity.ok(updatedGoal);
+ }
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity<Void> deleteGoal(@PathVariable Long id) {
+ if (!goalService.findGoalById(id).isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+ goalService.deleteGoal(id);
+ return ResponseEntity.noContent().build();
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import java.util.List;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.triathlon_coaching.product.athletik.backend.model.Gym;
+import com.triathlon_coaching.product.athletik.backend.service.GymService;
+
+@RestController
+@RequestMapping("/api/gyms")
+public class GymController {
+
+ @Autowired
+ private GymService gymService;
+
+ @GetMapping
+ public ResponseEntity<List<Gym>> getAllGyms() {
+ List<Gym> gyms = gymService.findAllGyms();
+ return ResponseEntity.ok(gyms);
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity<Gym> getGymById(@PathVariable Long id) {
+ return gymService.findGymById(id)
+ .map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/athlet/{athletId}")
+ public ResponseEntity<List<Gym>> getGymsByAthletId(@PathVariable Long athletId) {
+ List<Gym> gyms = gymService.findGymsByAthletId(athletId);
+ return ResponseEntity.ok(gyms);
+ }
+
+ @PostMapping("/{gymId}/select")
+ public ResponseEntity<?> selectGym(@PathVariable Long gymId, HttpSession session) {
+ // Setzt das ausgewählte Gym in der Session
+ gymService.findGymById(gymId).ifPresent(gym -> {
+ session.setAttribute("selectedGym", gym);
+ });
+ return ResponseEntity.ok().build();
+ }
+
+ @GetMapping("/selected")
+ public ResponseEntity<Gym> getSelectedGym(HttpSession session) {
+ Gym selectedGym = (Gym) session.getAttribute("selectedGym");
+ return ResponseEntity.ok(selectedGym);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Log;
+import com.triathlon_coaching.product.athletik.backend.service.LogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpSession;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/logs")
+public class LogController {
+
+ @Autowired
+ private LogService logService;
+
+ @GetMapping
+ public ResponseEntity<List<Log>> getAllLogs(HttpSession session) {
+ // Nur Admin-Zugriff erlauben
+ // Hier vereinfacht - in Produktion sollte eine richtige Autorisierung implementiert werden
+ return ResponseEntity.ok(logService.findAllLogs());
+ }
+
+ @GetMapping("/my-logs")
+ public ResponseEntity<List<Log>> getMyLogs(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Log> logs = logService.findByAthletId(athletId);
+ return ResponseEntity.ok(logs);
+ }
+
+ @GetMapping("/my-logs/paged")
+ public ResponseEntity<Page<Log>> getMyLogsPaged(
+ HttpSession session,
+ @RequestParam(defaultValue = "0") int page,
+ @RequestParam(defaultValue = "20") int size) {
+
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ Pageable pageable = PageRequest.of(page, size, Sort.by("created").descending());
+ Page<Log> logs = logService.findByAthletId(athletId, pageable);
+ return ResponseEntity.ok(logs);
+ }
+
+ @GetMapping("/search")
+ public ResponseEntity<List<Log>> searchLogs(
+ HttpSession session,
+ @RequestParam(required = false) String level,
+ @RequestParam(required = false) String searchTerm,
+ @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
+ @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate) {
+
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Log> logs;
+ if (level != null) {
+ logs = logService.findByAthletIdAndLogLevel(athletId, level);
+ } else if (searchTerm != null) {
+ logs = logService.searchByAthletIdAndLogdata(athletId, searchTerm);
+ } else if (startDate != null && endDate != null) {
+ logs = logService.findByAthletIdAndDateRange(athletId, startDate, endDate);
+ } else {
+ logs = logService.findByAthletId(athletId);
+ }
+
+ return ResponseEntity.ok(logs);
+ }
+
+ @GetMapping("/stats")
+ public ResponseEntity<?> getLogStats(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ LocalDateTime last24Hours = LocalDateTime.now().minusHours(24);
+ Long countLast24Hours = logService.getLogCountSince(athletId, last24Hours);
+
+ List<String> scripts = logService.getDistinctScripts(athletId);
+ List<String> levels = logService.getDistinctLogLevels(athletId);
+ Log latestLog = logService.getLatestLog(athletId);
+
+ return ResponseEntity.ok(new LogStats(countLast24Hours, scripts, levels, latestLog));
+ }
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity<Void> deleteLog(@PathVariable Long id, HttpSession session) {
+ // Prüfen, ob der Benutzer berechtigt ist, diesen Log zu löschen
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ // Hier sollte zusätzlich geprüft werden, ob der Log zum Benutzer gehört
+ logService.deleteLog(id);
+ return ResponseEntity.noContent().build();
+ }
+
+ // Hilfsmethode zur Extraktion der Athlet-ID aus der Session
+ private Long getAthletIdFromSession(HttpSession session) {
+ Object athletObj = session.getAttribute("athlet");
+ if (athletObj instanceof com.triathlon_coaching.product.athletik.backend.model.Athlet) {
+ return ((com.triathlon_coaching.product.athletik.backend.model.Athlet) athletObj).getId();
+ }
+ return null;
+ }
+
+ // DTO für Log-Statistiken
+ private static class LogStats {
+ private Long countLast24Hours;
+ private List<String> scripts;
+ private List<String> levels;
+ private Log latestLog;
+
+ public LogStats(Long countLast24Hours, List<String> scripts, List<String> levels, Log latestLog) {
+ this.countLast24Hours = countLast24Hours;
+ this.scripts = scripts;
+ this.levels = levels;
+ this.latestLog = latestLog;
+ }
+
+ // Getter
+ public Long getCountLast24Hours() { return countLast24Hours; }
+ public List<String> getScripts() { return scripts; }
+ public List<String> getLevels() { return levels; }
+ public Log getLatestLog() { return latestLog; }
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Muscle;
+import com.triathlon_coaching.product.athletik.backend.service.MuscleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/muscles")
+public class MuscleController {
+
+ @Autowired
+ private MuscleService muscleService;
+
+ @GetMapping
+ public ResponseEntity<List<Muscle>> getAllMuscles() {
+ List<Muscle> muscles = muscleService.findAllMuscles();
+ return ResponseEntity.ok(muscles);
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity<Muscle> getMuscleById(@PathVariable Long id) {
+ return muscleService.findMuscleById(id)
+ .map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/group/{muscleGroup}")
+ public ResponseEntity<List<Muscle>> getMusclesByGroup(@PathVariable String muscleGroup) {
+ List<Muscle> muscles = muscleService.findMusclesByGroup(muscleGroup);
+ return ResponseEntity.ok(muscles);
+ }
+
+ @GetMapping("/groups")
+ public ResponseEntity<List<String>> getAllMuscleGroups() {
+ List<String> muscleGroups = muscleService.findAllMuscleGroups();
+ return ResponseEntity.ok(muscleGroups);
+ }
+
+ @GetMapping("/exercise/{exerciseId}")
+ public ResponseEntity<List<Muscle>> getMusclesByExerciseId(@PathVariable Long exerciseId) {
+ List<Muscle> muscles = muscleService.findMusclesByExerciseId(exerciseId);
+ return ResponseEntity.ok(muscles);
+ }
+
+ @GetMapping("/primary/exercise/{exerciseId}")
+ public ResponseEntity<List<Muscle>> getPrimaryMusclesByExerciseId(@PathVariable Long exerciseId) {
+ List<Muscle> muscles = muscleService.findPrimaryMusclesByExerciseId(exerciseId);
+ return ResponseEntity.ok(muscles);
+ }
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Protokoll;
+import com.triathlon_coaching.product.athletik.backend.service.ProtokollService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpSession;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/protokoll")
+public class ProtokollController {
+
+ @Autowired
+ private ProtokollService protokollService;
+
+ @GetMapping
+ public ResponseEntity<List<Protokoll>> getAllProtokolls() {
+ List<Protokoll> protokolls = protokollService.findAllProtokolls();
+ return ResponseEntity.ok(protokolls);
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity<Protokoll> getProtokollById(@PathVariable Long id) {
+ Optional<Protokoll> protokoll = protokollService.findProtokollById(id);
+ return protokoll.map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/my-protokolls")
+ public ResponseEntity<List<Protokoll>> getMyProtokolls(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Protokoll> protokolls = protokollService.findByAthletId(athletId);
+ return ResponseEntity.ok(protokolls);
+ }
+
+ @GetMapping("/exercise/{exerciseId}")
+ public ResponseEntity<List<Protokoll>> getProtokollsByExercise(
+ @PathVariable Long exerciseId, HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Protokoll> protokolls = protokollService.findByAthletIdAndExerciseId(athletId, exerciseId);
+ return ResponseEntity.ok(protokolls);
+ }
+
+ @GetMapping("/exercise/{exerciseId}/paged")
+ public ResponseEntity<Page<Protokoll>> getProtokollsByExercisePaged(
+ @PathVariable Long exerciseId,
+ @RequestParam(defaultValue = "0") int page,
+ @RequestParam(defaultValue = "10") int size,
+ HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ Pageable pageable = PageRequest.of(page, size, Sort.by("trainingDate").descending());
+ Page<Protokoll> protokolls = protokollService.findByAthletIdAndExerciseIdPaged(athletId, exerciseId, pageable);
+ return ResponseEntity.ok(protokolls);
+ }
+
+ @GetMapping("/today")
+ public ResponseEntity<List<Protokoll>> getTodaySessions(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Protokoll> todaySessions = protokollService.findTodaySessionsByAthletId(athletId);
+ return ResponseEntity.ok(todaySessions);
+ }
+
+ @GetMapping("/date-range")
+ public ResponseEntity<List<Protokoll>> getProtokollsByDateRange(
+ @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start,
+ @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime end,
+ HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Protokoll> protokolls = protokollService.findByAthletIdAndDateRange(athletId, start, end);
+ return ResponseEntity.ok(protokolls);
+ }
+
+ @GetMapping("/tests")
+ public ResponseEntity<List<Protokoll>> getMyTests(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Protokoll> tests = protokollService.findTestsByAthletId(athletId);
+ return ResponseEntity.ok(tests);
+ }
+
+ @GetMapping("/tests/exercise/{exerciseId}")
+ public ResponseEntity<List<Protokoll>> getTestsByExercise(
+ @PathVariable Long exerciseId, HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Protokoll> tests = protokollService.findLatestTestsByAthletAndExercise(athletId, exerciseId);
+ return ResponseEntity.ok(tests);
+ }
+
+ @GetMapping("/personal-records")
+ public ResponseEntity<List<Protokoll>> getPersonalRecords(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ List<Protokoll> records = protokollService.findPersonalRecords(athletId);
+ return ResponseEntity.ok(records);
+ }
+
+ @GetMapping("/stats/volume")
+ public ResponseEntity<VolumeStats> getVolumeStats(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ Double dailyVolume = protokollService.calculateDailyVolume(athletId);
+ Double weeklyVolume = protokollService.calculateWeeklyVolume(athletId);
+
+ return ResponseEntity.ok(new VolumeStats(dailyVolume, weeklyVolume));
+ }
+
+ @PostMapping
+ public ResponseEntity<Protokoll> createProtokoll(@RequestBody Protokoll protokoll, HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ // Stellen Sie sicher, dass der Protokoll-Eintrag zum eingeloggten Athleten gehört
+ if (protokoll.getAthlet() == null || !protokoll.getAthlet().getId().equals(athletId)) {
+ return ResponseEntity.status(403).build();
+ }
+
+ Protokoll savedProtokoll = protokollService.saveProtokoll(protokoll);
+ return ResponseEntity.ok(savedProtokoll);
+ }
+
+ @PutMapping("/{id}")
+ public ResponseEntity<Protokoll> updateProtokoll(@PathVariable Long id, @RequestBody Protokoll protokollDetails, HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ Optional<Protokoll> protokollOptional = protokollService.findProtokollById(id);
+ if (!protokollOptional.isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+
+ Protokoll protokoll = protokollOptional.get();
+ // Prüfen, ob der Protokoll-Eintrag zum eingeloggten Athleten gehört
+ if (!protokoll.getAthlet().getId().equals(athletId)) {
+ return ResponseEntity.status(403).build();
+ }
+
+ // Aktualisieren der Felder
+ protokoll.setTrainingDate(protokollDetails.getTrainingDate());
+ protokoll.setNumberOfSet(protokollDetails.getNumberOfSet());
+ protokoll.setRepetitions(protokollDetails.getRepetitions());
+ protokoll.setWeight(protokollDetails.getWeight());
+ protokoll.setIsTest(protokollDetails.getIsTest());
+ protokoll.setNotes(protokollDetails.getNotes());
+ protokoll.setRpe(protokollDetails.getRpe());
+ protokoll.setRestTime(protokollDetails.getRestTime());
+
+ Protokoll updatedProtokoll = protokollService.saveProtokoll(protokoll);
+ return ResponseEntity.ok(updatedProtokoll);
+ }
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity<Void> deleteProtokoll(@PathVariable Long id, HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ Optional<Protokoll> protokollOptional = protokollService.findProtokollById(id);
+ if (!protokollOptional.isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+
+ // Prüfen, ob der Protokoll-Eintrag zum eingeloggten Athleten gehört
+ if (!protokollOptional.get().getAthlet().getId().equals(athletId)) {
+ return ResponseEntity.status(403).build();
+ }
+
+ protokollService.deleteProtokoll(id);
+ return ResponseEntity.noContent().build();
+ }
+
+ @PostMapping("/send-summary")
+ public ResponseEntity<Void> sendTrainingSummary(HttpSession session) {
+ Long athletId = getAthletIdFromSession(session);
+ if (athletId == null) {
+ return ResponseEntity.status(401).build();
+ }
+
+ protokollService.sendTrainingSummaryEmail(athletId);
+ return ResponseEntity.ok().build();
+ }
+
+ // Hilfsmethode zur Extraktion der Athlet-ID aus der Session
+ private Long getAthletIdFromSession(HttpSession session) {
+ Object athletObj = session.getAttribute("athlet");
+ if (athletObj instanceof com.triathlon_coaching.product.athletik.backend.model.Athlet) {
+ return ((com.triathlon_coaching.product.athletik.backend.model.Athlet) athletObj).getId();
+ }
+ return null;
+ }
+
+ // DTO für Volumen-Statistiken
+ private static class VolumeStats {
+ private Double dailyVolume;
+ private Double weeklyVolume;
+
+ public VolumeStats(Double dailyVolume, Double weeklyVolume) {
+ this.dailyVolume = dailyVolume;
+ this.weeklyVolume = weeklyVolume;
+ }
+
+ public Double getDailyVolume() { return dailyVolume; }
+ public Double getWeeklyVolume() { return weeklyVolume; }
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import com.triathlon_coaching.product.athletik.backend.model.Tool;
+import com.triathlon_coaching.product.athletik.backend.service.ToolService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Set;
+
+@RestController
+@RequestMapping("/api/tools")
+public class ToolController {
+
+ @Autowired
+ private ToolService toolService;
+
+ @GetMapping
+ public ResponseEntity<List<Tool>> getAllTools() {
+ List<Tool> tools = toolService.findAllTools();
+ return ResponseEntity.ok(tools);
+ }
+
+ @GetMapping("/{id}")
+ public ResponseEntity<Tool> getToolById(@PathVariable Long id) {
+ return toolService.findToolById(id)
+ .map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/gym/{gymId}")
+ public ResponseEntity<List<Tool>> getToolsByGymId(@PathVariable Long gymId) {
+ List<Tool> tools = toolService.findToolsByGymId(gymId);
+ return ResponseEntity.ok(tools);
+ }
+
+ @GetMapping("/{id}/weights")
+ public ResponseEntity<Set<Double>> getAvailableWeights(@PathVariable Long id) {
+ return toolService.findToolById(id)
+ .map(tool -> ResponseEntity.ok(tool.getAvailableWeights()))
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/search")
+ public ResponseEntity<List<Tool>> searchTools(
+ @RequestParam(required = false) String name,
+ @RequestParam(required = false) String language) {
+
+ List<Tool> tools;
+ if (name != null && !name.trim().isEmpty()) {
+ if ("german".equalsIgnoreCase(language)) {
+ tools = toolService.findByToolnameGermanContainingIgnoreCase(name);
+ } else {
+ tools = toolService.findByToolnameEnglishContainingIgnoreCase(name);
+ }
+ } else {
+ tools = toolService.findAllTools();
+ }
+
+ return ResponseEntity.ok(tools);
+ }
+
+ @PostMapping
+ public ResponseEntity<Tool> createTool(@RequestBody Tool tool) {
+ Tool savedTool = toolService.saveTool(tool);
+ return ResponseEntity.ok(savedTool);
+ }
+
+ @PutMapping("/{id}")
+ public ResponseEntity<Tool> updateTool(@PathVariable Long id, @RequestBody Tool tool) {
+ if (!toolService.findToolById(id).isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+ tool.setId(id);
+ Tool updatedTool = toolService.saveTool(tool);
+ return ResponseEntity.ok(updatedTool);
+ }
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity<Void> deleteTool(@PathVariable Long id) {
+ if (!toolService.findToolById(id).isPresent()) {
+ return ResponseEntity.notFound().build();
+ }
+ toolService.deleteTool(id);
+ return ResponseEntity.noContent().build();
+ }
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.contoller;
+
+import javax.servlet.http.HttpSession;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.triathlon_coaching.product.athletik.backend.model.Athlet;
+import com.triathlon_coaching.product.athletik.backend.service.TrainingService;
+
+@RestController
+@RequestMapping("/api/training")
+public class TrainingController {
+
+ @Autowired
+ private TrainingService trainingService;
+
+
+ @PostMapping("/send-summary")
+ public ResponseEntity<?> sendTrainingSummary(HttpSession session) {
+ Athlet athlet = (Athlet) session.getAttribute("athlet");
+ if (athlet == null) {
+ return ResponseEntity.status(401).build();
+ }
+ trainingService.sendTrainingSummaryEmail(athlet.getId());
+ return ResponseEntity.ok("Zusammenfassung wurde per E-Mail versendet");
+ }
+
+ @GetMapping("/calculate-orm")
+ public ResponseEntity<Double> calculateOneRepMax(@RequestParam double weight,
+ @RequestParam int repetitions) {
+ double oneRepMax = trainingService.calculateOneRepMax(weight, repetitions);
+ return ResponseEntity.ok(oneRepMax);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.time.LocalDateTime;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinTable;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "athlet", schema = "athletik")
+public class Athlet {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(nullable = false, unique = true, length = 50)
+ private String username;
+
+ @Column(name = "fullname", nullable = false, length = 100)
+ private String fullname;
+
+ @Column(nullable = false, unique = true, length = 100)
+ private String email;
+
+ @Column(nullable = false, length = 128)
+ private String pass;
+
+ @Column(name = "created_at", updatable = false)
+ private LocalDateTime createdAt;
+
+ @Column(name = "last_login")
+ private LocalDateTime lastLogin;
+
+ @Column(name = "is_active")
+ private Boolean isActive = true;
+
+ @ManyToMany
+ @JoinTable(
+ name = "athletgym",
+ schema = "athletik",
+ joinColumns = @JoinColumn(name = "fk_athlet"),
+ inverseJoinColumns = @JoinColumn(name = "fk_gym")
+ )
+ private Set<Gym> gyms = new HashSet<>();
+
+ @OneToMany(mappedBy = "athlet", cascade = CascadeType.ALL, orphanRemoval = true)
+ private Set<Protokoll> protokolls = new HashSet<>();
+
+ @OneToMany(mappedBy = "athlet", cascade = CascadeType.ALL, orphanRemoval = true)
+ private Set<Training> trainings = new HashSet<>();
+
+ @OneToMany(mappedBy = "athlet", cascade = CascadeType.ALL, orphanRemoval = true)
+ private Set<Log> logs = new HashSet<>();
+
+ public Athlet() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public Athlet(Long id, String username, String fullname, String email, String pass, LocalDateTime createdAt,
+ LocalDateTime lastLogin, Boolean isActive, Set<Gym> gyms, Set<Protokoll> protokolls,
+ Set<Training> trainings, Set<Log> logs) {
+ super();
+ this.username = username;
+ this.fullname = fullname;
+ this.email = email;
+ this.pass = pass;
+ this.createdAt = createdAt;
+ this.lastLogin = lastLogin;
+ this.isActive = isActive;
+ this.gyms = gyms;
+ this.protokolls = protokolls;
+ this.trainings = trainings;
+ this.logs = logs;
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the username
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * @param username the username to set
+ */
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ /**
+ * @return the fullname
+ */
+ public String getFullname() {
+ return fullname;
+ }
+
+ /**
+ * @param fullname the fullname to set
+ */
+ public void setFullname(String fullname) {
+ this.fullname = fullname;
+ }
+
+ /**
+ * @return the email
+ */
+ public String getEmail() {
+ return email;
+ }
+
+ /**
+ * @param email the email to set
+ */
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ /**
+ * @return the pass
+ */
+ public String getPass() {
+ return pass;
+ }
+
+ /**
+ * @param pass the pass to set
+ */
+ public void setPass(String pass) {
+ this.pass = pass;
+ }
+
+ /**
+ * @return the gyms
+ */
+ public Set<Gym> getGyms() {
+ return gyms;
+ }
+
+ /**
+ * @param gyms the gyms to set
+ */
+ public void setGyms(Set<Gym> gyms) {
+ this.gyms = gyms;
+ }
+
+ /**
+ * @return the createdAt
+ */
+ public LocalDateTime getCreatedAt() {
+ return createdAt;
+ }
+
+ /**
+ * @param createdAt the createdAt to set
+ */
+ public void setCreatedAt(LocalDateTime createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ /**
+ * @return the lastLogin
+ */
+ public LocalDateTime getLastLogin() {
+ return lastLogin;
+ }
+
+ /**
+ * @param lastLogin the lastLogin to set
+ */
+ public void setLastLogin(LocalDateTime lastLogin) {
+ this.lastLogin = lastLogin;
+ }
+
+ /**
+ * @return the isActive
+ */
+ public Boolean getIsActive() {
+ return isActive;
+ }
+
+ /**
+ * @param isActive the isActive to set
+ */
+ public void setIsActive(Boolean isActive) {
+ this.isActive = isActive;
+ }
+
+ /**
+ * @return the protokolls
+ */
+ public Set<Protokoll> getProtokolls() {
+ return protokolls;
+ }
+
+ /**
+ * @param protokolls the protokolls to set
+ */
+ public void setProtokolls(Set<Protokoll> protokolls) {
+ this.protokolls = protokolls;
+ }
+
+ /**
+ * @return the trainings
+ */
+ public Set<Training> getTrainings() {
+ return trainings;
+ }
+
+ /**
+ * @param trainings the trainings to set
+ */
+ public void setTrainings(Set<Training> trainings) {
+ this.trainings = trainings;
+ }
+
+ /**
+ * @return the logs
+ */
+ public Set<Log> getLogs() {
+ return logs;
+ }
+
+ /**
+ * @param logs the logs to set
+ */
+ public void setLogs(Set<Log> logs) {
+ this.logs = logs;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((createdAt == null) ? 0 : createdAt.hashCode());
+ result = prime * result + ((email == null) ? 0 : email.hashCode());
+ result = prime * result + ((fullname == null) ? 0 : fullname.hashCode());
+ result = prime * result + ((gyms == null) ? 0 : gyms.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((isActive == null) ? 0 : isActive.hashCode());
+ result = prime * result + ((lastLogin == null) ? 0 : lastLogin.hashCode());
+ result = prime * result + ((logs == null) ? 0 : logs.hashCode());
+ result = prime * result + ((pass == null) ? 0 : pass.hashCode());
+ result = prime * result + ((protokolls == null) ? 0 : protokolls.hashCode());
+ result = prime * result + ((trainings == null) ? 0 : trainings.hashCode());
+ result = prime * result + ((username == null) ? 0 : username.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Athlet other = (Athlet) obj;
+ if (createdAt == null) {
+ if (other.createdAt != null)
+ return false;
+ } else if (!createdAt.equals(other.createdAt))
+ return false;
+ if (email == null) {
+ if (other.email != null)
+ return false;
+ } else if (!email.equals(other.email))
+ return false;
+ if (fullname == null) {
+ if (other.fullname != null)
+ return false;
+ } else if (!fullname.equals(other.fullname))
+ return false;
+ if (gyms == null) {
+ if (other.gyms != null)
+ return false;
+ } else if (!gyms.equals(other.gyms))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (isActive == null) {
+ if (other.isActive != null)
+ return false;
+ } else if (!isActive.equals(other.isActive))
+ return false;
+ if (lastLogin == null) {
+ if (other.lastLogin != null)
+ return false;
+ } else if (!lastLogin.equals(other.lastLogin))
+ return false;
+ if (logs == null) {
+ if (other.logs != null)
+ return false;
+ } else if (!logs.equals(other.logs))
+ return false;
+ if (pass == null) {
+ if (other.pass != null)
+ return false;
+ } else if (!pass.equals(other.pass))
+ return false;
+ if (protokolls == null) {
+ if (other.protokolls != null)
+ return false;
+ } else if (!protokolls.equals(other.protokolls))
+ return false;
+ if (trainings == null) {
+ if (other.trainings != null)
+ return false;
+ } else if (!trainings.equals(other.trainings))
+ return false;
+ if (username == null) {
+ if (other.username != null)
+ return false;
+ } else if (!username.equals(other.username))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Athlet [id=");
+ builder.append(id);
+ builder.append(", username=");
+ builder.append(username);
+ builder.append(", fullname=");
+ builder.append(fullname);
+ builder.append(", email=");
+ builder.append(email);
+ builder.append(", pass=");
+ builder.append(pass);
+ builder.append(", createdAt=");
+ builder.append(createdAt);
+ builder.append(", lastLogin=");
+ builder.append(lastLogin);
+ builder.append(", isActive=");
+ builder.append(isActive);
+ builder.append(", gyms=");
+ builder.append(gyms);
+ builder.append(", protokolls=");
+ builder.append(protokolls);
+ builder.append(", trainings=");
+ builder.append(trainings);
+ builder.append(", logs=");
+ builder.append(logs);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "exercise", schema = "athletik")
+public class Exercise {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "name_english", nullable = false)
+ private String nameEnglish;
+
+ @Column(name = "description_english")
+ private String descriptionEnglish;
+
+ @Column(name = "name_german")
+ private String nameGerman;
+
+ @Column(name = "description_german")
+ private String descriptionGerman;
+
+ @Column(name = "url_video")
+ private String urlVideo;
+
+ @ManyToOne
+ @JoinColumn(name = "fk_tool", nullable = false)
+ private Tool tool;
+
+ @ManyToMany
+ @JoinTable(
+ name = "exercise_muscle",
+ schema = "athletik",
+ joinColumns = @JoinColumn(name = "fk_exercise"),
+ inverseJoinColumns = @JoinColumn(name = "fk_muscle")
+ )
+ private Set<Muscle> muscles = new HashSet<>();
+
+ public Exercise() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public Exercise(String nameEnglish, String descriptionEnglish, String nameGerman, String descriptionGerman,
+ String urlVideo, Tool tool, Set<Muscle> muscles) {
+ super();
+ this.nameEnglish = nameEnglish;
+ this.descriptionEnglish = descriptionEnglish;
+ this.nameGerman = nameGerman;
+ this.descriptionGerman = descriptionGerman;
+ this.urlVideo = urlVideo;
+ this.tool = tool;
+ this.muscles = muscles;
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the nameEnglish
+ */
+ public String getNameEnglish() {
+ return nameEnglish;
+ }
+
+ /**
+ * @param nameEnglish the nameEnglish to set
+ */
+ public void setNameEnglish(String nameEnglish) {
+ this.nameEnglish = nameEnglish;
+ }
+
+ /**
+ * @return the descriptionEnglish
+ */
+ public String getDescriptionEnglish() {
+ return descriptionEnglish;
+ }
+
+ /**
+ * @param descriptionEnglish the descriptionEnglish to set
+ */
+ public void setDescriptionEnglish(String descriptionEnglish) {
+ this.descriptionEnglish = descriptionEnglish;
+ }
+
+ /**
+ * @return the nameGerman
+ */
+ public String getNameGerman() {
+ return nameGerman;
+ }
+
+ /**
+ * @param nameGerman the nameGerman to set
+ */
+ public void setNameGerman(String nameGerman) {
+ this.nameGerman = nameGerman;
+ }
+
+ /**
+ * @return the descriptionGerman
+ */
+ public String getDescriptionGerman() {
+ return descriptionGerman;
+ }
+
+ /**
+ * @param descriptionGerman the descriptionGerman to set
+ */
+ public void setDescriptionGerman(String descriptionGerman) {
+ this.descriptionGerman = descriptionGerman;
+ }
+
+ /**
+ * @return the urlVideo
+ */
+ public String getUrlVideo() {
+ return urlVideo;
+ }
+
+ /**
+ * @param urlVideo the urlVideo to set
+ */
+ public void setUrlVideo(String urlVideo) {
+ this.urlVideo = urlVideo;
+ }
+
+ /**
+ * @return the tool
+ */
+ public Tool getTool() {
+ return tool;
+ }
+
+ /**
+ * @param tool the tool to set
+ */
+ public void setTool(Tool tool) {
+ this.tool = tool;
+ }
+
+ /**
+ * @return the muscles
+ */
+ public Set<Muscle> getMuscles() {
+ return muscles;
+ }
+
+ /**
+ * @param muscles the muscles to set
+ */
+ public void setMuscles(Set<Muscle> muscles) {
+ this.muscles = muscles;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((descriptionEnglish == null) ? 0 : descriptionEnglish.hashCode());
+ result = prime * result + ((descriptionGerman == null) ? 0 : descriptionGerman.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((muscles == null) ? 0 : muscles.hashCode());
+ result = prime * result + ((nameEnglish == null) ? 0 : nameEnglish.hashCode());
+ result = prime * result + ((nameGerman == null) ? 0 : nameGerman.hashCode());
+ result = prime * result + ((tool == null) ? 0 : tool.hashCode());
+ result = prime * result + ((urlVideo == null) ? 0 : urlVideo.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Exercise other = (Exercise) obj;
+ if (descriptionEnglish == null) {
+ if (other.descriptionEnglish != null)
+ return false;
+ } else if (!descriptionEnglish.equals(other.descriptionEnglish))
+ return false;
+ if (descriptionGerman == null) {
+ if (other.descriptionGerman != null)
+ return false;
+ } else if (!descriptionGerman.equals(other.descriptionGerman))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (muscles == null) {
+ if (other.muscles != null)
+ return false;
+ } else if (!muscles.equals(other.muscles))
+ return false;
+ if (nameEnglish == null) {
+ if (other.nameEnglish != null)
+ return false;
+ } else if (!nameEnglish.equals(other.nameEnglish))
+ return false;
+ if (nameGerman == null) {
+ if (other.nameGerman != null)
+ return false;
+ } else if (!nameGerman.equals(other.nameGerman))
+ return false;
+ if (tool == null) {
+ if (other.tool != null)
+ return false;
+ } else if (!tool.equals(other.tool))
+ return false;
+ if (urlVideo == null) {
+ if (other.urlVideo != null)
+ return false;
+ } else if (!urlVideo.equals(other.urlVideo))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Exercise [id=");
+ builder.append(id);
+ builder.append(", nameEnglish=");
+ builder.append(nameEnglish);
+ builder.append(", descriptionEnglish=");
+ builder.append(descriptionEnglish);
+ builder.append(", nameGerman=");
+ builder.append(nameGerman);
+ builder.append(", descriptionGerman=");
+ builder.append(descriptionGerman);
+ builder.append(", urlVideo=");
+ builder.append(urlVideo);
+ builder.append(", tool=");
+ builder.append(tool);
+ builder.append(", muscles=");
+ builder.append(muscles);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "goal", schema = "athletik")
+public class Goal {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "goalname", nullable = false, length = 100)
+ private String goalname;
+
+ @Column(name = "description", columnDefinition = "TEXT")
+ private String description;
+
+ @OneToMany(mappedBy = "goal", cascade = CascadeType.ALL, orphanRemoval = true)
+ private Set<Training> trainings = new HashSet<>();
+
+ public Goal() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public Goal(String goalname, String description, Set<Training> trainings) {
+ super();
+ this.goalname = goalname;
+ this.description = description;
+ this.trainings = trainings;
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the goalname
+ */
+ public String getGoalname() {
+ return goalname;
+ }
+
+ /**
+ * @param goalname the goalname to set
+ */
+ public void setGoalname(String goalname) {
+ this.goalname = goalname;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * @return the trainings
+ */
+ public Set<Training> getTrainings() {
+ return trainings;
+ }
+
+ /**
+ * @param trainings the trainings to set
+ */
+ public void setTrainings(Set<Training> trainings) {
+ this.trainings = trainings;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + ((goalname == null) ? 0 : goalname.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((trainings == null) ? 0 : trainings.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Goal other = (Goal) obj;
+ if (description == null) {
+ if (other.description != null)
+ return false;
+ } else if (!description.equals(other.description))
+ return false;
+ if (goalname == null) {
+ if (other.goalname != null)
+ return false;
+ } else if (!goalname.equals(other.goalname))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (trainings == null) {
+ if (other.trainings != null)
+ return false;
+ } else if (!trainings.equals(other.trainings))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Goal [id=");
+ builder.append(id);
+ builder.append(", goalname=");
+ builder.append(goalname);
+ builder.append(", description=");
+ builder.append(description);
+ builder.append(", trainings=");
+ builder.append(trainings);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinTable;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "gym", schema = "athletik")
+public class Gym {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(nullable = false)
+ private String gymname;
+
+ @Column
+ private String gymlocation;
+
+ @ManyToMany(mappedBy = "gyms")
+ private Set<Athlet> athleten = new HashSet<>();
+
+ @ManyToMany
+ @JoinTable(
+ name = "gymtool",
+ schema = "athletik",
+ joinColumns = @JoinColumn(name = "fk_gym"),
+ inverseJoinColumns = @JoinColumn(name = "fk_tool")
+ )
+ private Set<Tool> tools = new HashSet<>();
+
+ public Gym() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public Gym(String gymname, String gymlocation, Set<Athlet> athleten, Set<Tool> tools) {
+ super();
+ this.gymname = gymname;
+ this.gymlocation = gymlocation;
+ this.athleten = athleten;
+ this.tools = tools;
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the gymname
+ */
+ public String getGymname() {
+ return gymname;
+ }
+
+ /**
+ * @param gymname the gymname to set
+ */
+ public void setGymname(String gymname) {
+ this.gymname = gymname;
+ }
+
+ /**
+ * @return the gymlocation
+ */
+ public String getGymlocation() {
+ return gymlocation;
+ }
+
+ /**
+ * @param gymlocation the gymlocation to set
+ */
+ public void setGymlocation(String gymlocation) {
+ this.gymlocation = gymlocation;
+ }
+
+ /**
+ * @return the athleten
+ */
+ public Set<Athlet> getAthleten() {
+ return athleten;
+ }
+
+ /**
+ * @param athleten the athleten to set
+ */
+ public void setAthleten(Set<Athlet> athleten) {
+ this.athleten = athleten;
+ }
+
+ /**
+ * @return the tools
+ */
+ public Set<Tool> getTools() {
+ return tools;
+ }
+
+ /**
+ * @param tools the tools to set
+ */
+ public void setTools(Set<Tool> tools) {
+ this.tools = tools;
+ }
+
+ // Hilfsmethoden
+/*
+ public void addAthlet(Athlet athlet) {
+ this.athleten.add(athlet);
+ athlet.getGyms().add(this);
+ }
+
+ public void removeAthlet(Athlet athlet) {
+ this.athleten.remove(athlet);
+ athlet.getGyms().remove(this);
+ }
+
+ public void addTool(Tool tool) {
+ this.tools.add(tool);
+ tool.getGyms().add(this);
+ }
+
+ public void removeTool(Tool tool) {
+ this.tools.remove(tool);
+ tool.getGyms().remove(this);
+ }
+*/
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((athleten == null) ? 0 : athleten.hashCode());
+ result = prime * result + ((gymlocation == null) ? 0 : gymlocation.hashCode());
+ result = prime * result + ((gymname == null) ? 0 : gymname.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((tools == null) ? 0 : tools.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Gym other = (Gym) obj;
+ if (athleten == null) {
+ if (other.athleten != null)
+ return false;
+ } else if (!athleten.equals(other.athleten))
+ return false;
+ if (gymlocation == null) {
+ if (other.gymlocation != null)
+ return false;
+ } else if (!gymlocation.equals(other.gymlocation))
+ return false;
+ if (gymname == null) {
+ if (other.gymname != null)
+ return false;
+ } else if (!gymname.equals(other.gymname))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (tools == null) {
+ if (other.tools != null)
+ return false;
+ } else if (!tools.equals(other.tools))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Gym [id=");
+ builder.append(id);
+ builder.append(", gymname=");
+ builder.append(gymname);
+ builder.append(", gymlocation=");
+ builder.append(gymlocation);
+ builder.append(", athleten=");
+ builder.append(athleten);
+ builder.append(", tools=");
+ builder.append(tools);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+
+
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PrePersist;
+import javax.persistence.Table;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "log", schema = "athletik")
+public class Log {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "created", nullable = false, updatable = false)
+ private LocalDateTime created;
+
+ @Column(name = "logdata", nullable = false, columnDefinition = "TEXT")
+ private String logdata;
+
+ @Column(name = "sid", nullable = false, length = 100)
+ private String sid;
+
+ @Column(name = "script", nullable = false, length = 255)
+ private String script;
+
+ @Column(name = "log_level", length = 20)
+ private String logLevel;
+
+ @Column(name = "ip_address", length = 45)
+ private String ipAddress;
+
+ @Column(name = "user_agent", length = 500)
+ private String userAgent;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_athlet", nullable = false)
+ private Athlet athlet;
+
+ // Konstruktoren
+ public Log() {
+ this.created = LocalDateTime.now();
+ }
+
+
+
+ public Log(LocalDateTime created, String logdata, String sid, String script, String logLevel, String ipAddress,
+ String userAgent, Athlet athlet) {
+ super();
+ this.created = created;
+ this.logdata = logdata;
+ this.sid = sid;
+ this.script = script;
+ this.logLevel = logLevel;
+ this.ipAddress = ipAddress;
+ this.userAgent = userAgent;
+ this.athlet = athlet;
+ }
+
+
+
+ public Log(String logdata, String sid, String script, Athlet athlet) {
+ this();
+ this.logdata = logdata;
+ this.sid = sid;
+ this.script = script;
+ this.athlet = athlet;
+ }
+
+ public Log(String logdata, String sid, String script, String logLevel, Athlet athlet) {
+ this(logdata, sid, script, athlet);
+ this.logLevel = logLevel;
+ }
+
+ public Log(String logdata, String sid, String script, String logLevel, String ipAddress, String userAgent, Athlet athlet) {
+ this(logdata, sid, script, logLevel, athlet);
+ this.ipAddress = ipAddress;
+ this.userAgent = userAgent;
+ }
+
+ // Pre-Persist Callback
+ @PrePersist
+ protected void onCreate() {
+ if (created == null) {
+ created = LocalDateTime.now();
+ }
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the created
+ */
+ public LocalDateTime getCreated() {
+ return created;
+ }
+
+ /**
+ * @param created the created to set
+ */
+ public void setCreated(LocalDateTime created) {
+ this.created = created;
+ }
+
+ /**
+ * @return the logdata
+ */
+ public String getLogdata() {
+ return logdata;
+ }
+
+ /**
+ * @param logdata the logdata to set
+ */
+ public void setLogdata(String logdata) {
+ this.logdata = logdata;
+ }
+
+ /**
+ * @return the sid
+ */
+ public String getSid() {
+ return sid;
+ }
+
+ /**
+ * @param sid the sid to set
+ */
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+
+ /**
+ * @return the script
+ */
+ public String getScript() {
+ return script;
+ }
+
+ /**
+ * @param script the script to set
+ */
+ public void setScript(String script) {
+ this.script = script;
+ }
+
+ /**
+ * @return the logLevel
+ */
+ public String getLogLevel() {
+ return logLevel;
+ }
+
+ /**
+ * @param logLevel the logLevel to set
+ */
+ public void setLogLevel(String logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ /**
+ * @return the ipAddress
+ */
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ /**
+ * @param ipAddress the ipAddress to set
+ */
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ /**
+ * @return the userAgent
+ */
+ public String getUserAgent() {
+ return userAgent;
+ }
+
+ /**
+ * @param userAgent the userAgent to set
+ */
+ public void setUserAgent(String userAgent) {
+ this.userAgent = userAgent;
+ }
+
+ /**
+ * @return the athlet
+ */
+ public Athlet getAthlet() {
+ return athlet;
+ }
+
+ /**
+ * @param athlet the athlet to set
+ */
+ public void setAthlet(Athlet athlet) {
+ this.athlet = athlet;
+ }
+
+
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((athlet == null) ? 0 : athlet.hashCode());
+ result = prime * result + ((created == null) ? 0 : created.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((ipAddress == null) ? 0 : ipAddress.hashCode());
+ result = prime * result + ((logLevel == null) ? 0 : logLevel.hashCode());
+ result = prime * result + ((logdata == null) ? 0 : logdata.hashCode());
+ result = prime * result + ((script == null) ? 0 : script.hashCode());
+ result = prime * result + ((sid == null) ? 0 : sid.hashCode());
+ result = prime * result + ((userAgent == null) ? 0 : userAgent.hashCode());
+ return result;
+ }
+
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Log other = (Log) obj;
+ if (athlet == null) {
+ if (other.athlet != null)
+ return false;
+ } else if (!athlet.equals(other.athlet))
+ return false;
+ if (created == null) {
+ if (other.created != null)
+ return false;
+ } else if (!created.equals(other.created))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (ipAddress == null) {
+ if (other.ipAddress != null)
+ return false;
+ } else if (!ipAddress.equals(other.ipAddress))
+ return false;
+ if (logLevel == null) {
+ if (other.logLevel != null)
+ return false;
+ } else if (!logLevel.equals(other.logLevel))
+ return false;
+ if (logdata == null) {
+ if (other.logdata != null)
+ return false;
+ } else if (!logdata.equals(other.logdata))
+ return false;
+ if (script == null) {
+ if (other.script != null)
+ return false;
+ } else if (!script.equals(other.script))
+ return false;
+ if (sid == null) {
+ if (other.sid != null)
+ return false;
+ } else if (!sid.equals(other.sid))
+ return false;
+ if (userAgent == null) {
+ if (other.userAgent != null)
+ return false;
+ } else if (!userAgent.equals(other.userAgent))
+ return false;
+ return true;
+ }
+
+
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Log [id=");
+ builder.append(id);
+ builder.append(", created=");
+ builder.append(created);
+ builder.append(", logdata=");
+ builder.append(logdata);
+ builder.append(", sid=");
+ builder.append(sid);
+ builder.append(", script=");
+ builder.append(script);
+ builder.append(", logLevel=");
+ builder.append(logLevel);
+ builder.append(", ipAddress=");
+ builder.append(ipAddress);
+ builder.append(", userAgent=");
+ builder.append(userAgent);
+ builder.append(", athlet=");
+ builder.append(athlet);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "muscle", schema = "athletik")
+public class Muscle {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "muscle_name_latin", nullable = false)
+ private String muscleNameLatin;
+
+ @Column(name = "muscle_name_english")
+ private String muscleNameEnglish;
+
+ @Column(name = "muscle_name_german")
+ private String muscleNameGerman;
+
+ @Column(name = "movement_english", nullable = false)
+ private String movementEnglish;
+
+ @Column(name = "movement_german", nullable = false)
+ private String movementGerman;
+
+ @Column(name = "musclegroup_name_english")
+ private String musclegroupNameEnglish;
+
+ @Column(name = "musclegroup_name_german")
+ private String musclegroupNameGerman;
+
+ @ManyToMany(mappedBy = "muscles")
+ private Set<Exercise> exercises = new HashSet<>();
+
+ public Muscle() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public Muscle(String muscleNameLatin, String muscleNameEnglish, String muscleNameGerman, String movementEnglish,
+ String movementGerman, String musclegroupNameEnglish, String musclegroupNameGerman,
+ Set<Exercise> exercises) {
+ super();
+ this.muscleNameLatin = muscleNameLatin;
+ this.muscleNameEnglish = muscleNameEnglish;
+ this.muscleNameGerman = muscleNameGerman;
+ this.movementEnglish = movementEnglish;
+ this.movementGerman = movementGerman;
+ this.musclegroupNameEnglish = musclegroupNameEnglish;
+ this.musclegroupNameGerman = musclegroupNameGerman;
+ this.exercises = exercises;
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the muscleNameLatin
+ */
+ public String getMuscleNameLatin() {
+ return muscleNameLatin;
+ }
+
+ /**
+ * @param muscleNameLatin the muscleNameLatin to set
+ */
+ public void setMuscleNameLatin(String muscleNameLatin) {
+ this.muscleNameLatin = muscleNameLatin;
+ }
+
+ /**
+ * @return the muscleNameEnglish
+ */
+ public String getMuscleNameEnglish() {
+ return muscleNameEnglish;
+ }
+
+ /**
+ * @param muscleNameEnglish the muscleNameEnglish to set
+ */
+ public void setMuscleNameEnglish(String muscleNameEnglish) {
+ this.muscleNameEnglish = muscleNameEnglish;
+ }
+
+ /**
+ * @return the muscleNameGerman
+ */
+ public String getMuscleNameGerman() {
+ return muscleNameGerman;
+ }
+
+ /**
+ * @param muscleNameGerman the muscleNameGerman to set
+ */
+ public void setMuscleNameGerman(String muscleNameGerman) {
+ this.muscleNameGerman = muscleNameGerman;
+ }
+
+ /**
+ * @return the movementEnglish
+ */
+ public String getMovementEnglish() {
+ return movementEnglish;
+ }
+
+ /**
+ * @param movementEnglish the movementEnglish to set
+ */
+ public void setMovementEnglish(String movementEnglish) {
+ this.movementEnglish = movementEnglish;
+ }
+
+ /**
+ * @return the movementGerman
+ */
+ public String getMovementGerman() {
+ return movementGerman;
+ }
+
+ /**
+ * @param movementGerman the movementGerman to set
+ */
+ public void setMovementGerman(String movementGerman) {
+ this.movementGerman = movementGerman;
+ }
+
+ /**
+ * @return the musclegroupNameEnglish
+ */
+ public String getMusclegroupNameEnglish() {
+ return musclegroupNameEnglish;
+ }
+
+ /**
+ * @param musclegroupNameEnglish the musclegroupNameEnglish to set
+ */
+ public void setMusclegroupNameEnglish(String musclegroupNameEnglish) {
+ this.musclegroupNameEnglish = musclegroupNameEnglish;
+ }
+
+ /**
+ * @return the musclegroupNameGerman
+ */
+ public String getMusclegroupNameGerman() {
+ return musclegroupNameGerman;
+ }
+
+ /**
+ * @param musclegroupNameGerman the musclegroupNameGerman to set
+ */
+ public void setMusclegroupNameGerman(String musclegroupNameGerman) {
+ this.musclegroupNameGerman = musclegroupNameGerman;
+ }
+
+ /**
+ * @return the exercises
+ */
+ public Set<Exercise> getExercises() {
+ return exercises;
+ }
+
+ /**
+ * @param exercises the exercises to set
+ */
+ public void setExercises(Set<Exercise> exercises) {
+ this.exercises = exercises;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((exercises == null) ? 0 : exercises.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((movementEnglish == null) ? 0 : movementEnglish.hashCode());
+ result = prime * result + ((movementGerman == null) ? 0 : movementGerman.hashCode());
+ result = prime * result + ((muscleNameEnglish == null) ? 0 : muscleNameEnglish.hashCode());
+ result = prime * result + ((muscleNameGerman == null) ? 0 : muscleNameGerman.hashCode());
+ result = prime * result + ((muscleNameLatin == null) ? 0 : muscleNameLatin.hashCode());
+ result = prime * result + ((musclegroupNameEnglish == null) ? 0 : musclegroupNameEnglish.hashCode());
+ result = prime * result + ((musclegroupNameGerman == null) ? 0 : musclegroupNameGerman.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Muscle other = (Muscle) obj;
+ if (exercises == null) {
+ if (other.exercises != null)
+ return false;
+ } else if (!exercises.equals(other.exercises))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (movementEnglish == null) {
+ if (other.movementEnglish != null)
+ return false;
+ } else if (!movementEnglish.equals(other.movementEnglish))
+ return false;
+ if (movementGerman == null) {
+ if (other.movementGerman != null)
+ return false;
+ } else if (!movementGerman.equals(other.movementGerman))
+ return false;
+ if (muscleNameEnglish == null) {
+ if (other.muscleNameEnglish != null)
+ return false;
+ } else if (!muscleNameEnglish.equals(other.muscleNameEnglish))
+ return false;
+ if (muscleNameGerman == null) {
+ if (other.muscleNameGerman != null)
+ return false;
+ } else if (!muscleNameGerman.equals(other.muscleNameGerman))
+ return false;
+ if (muscleNameLatin == null) {
+ if (other.muscleNameLatin != null)
+ return false;
+ } else if (!muscleNameLatin.equals(other.muscleNameLatin))
+ return false;
+ if (musclegroupNameEnglish == null) {
+ if (other.musclegroupNameEnglish != null)
+ return false;
+ } else if (!musclegroupNameEnglish.equals(other.musclegroupNameEnglish))
+ return false;
+ if (musclegroupNameGerman == null) {
+ if (other.musclegroupNameGerman != null)
+ return false;
+ } else if (!musclegroupNameGerman.equals(other.musclegroupNameGerman))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Muscle [id=");
+ builder.append(id);
+ builder.append(", muscleNameLatin=");
+ builder.append(muscleNameLatin);
+ builder.append(", muscleNameEnglish=");
+ builder.append(muscleNameEnglish);
+ builder.append(", muscleNameGerman=");
+ builder.append(muscleNameGerman);
+ builder.append(", movementEnglish=");
+ builder.append(movementEnglish);
+ builder.append(", movementGerman=");
+ builder.append(movementGerman);
+ builder.append(", musclegroupNameEnglish=");
+ builder.append(musclegroupNameEnglish);
+ builder.append(", musclegroupNameGerman=");
+ builder.append(musclegroupNameGerman);
+ builder.append(", exercises=");
+ builder.append(exercises);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "protokoll", schema = "athletik")
+public class Protokoll {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "trainingdate", nullable = false)
+ private LocalDateTime trainingDate;
+
+ @Column(name = "number_of_set", nullable = false)
+ private Integer numberOfSet;
+
+ @Column(name = "repetitions", nullable = false)
+ private Integer repetitions;
+
+ @Column(name = "weight", precision = 5, scale = 2)
+ private Double weight;
+
+ @Column(name = "is_test", nullable = false)
+ private Boolean isTest = false;
+
+ @Column(name = "volume")
+ private Double volume;
+
+ @Column(name = "one_rep_max")
+ private Double oneRepMax;
+
+ @Column(name = "notes", length = 500)
+ private String notes;
+
+ @Column(name = "rpe") // Rate of Perceived Exertion
+ private Integer rpe;
+
+ @Column(name = "rest_time") // in seconds
+ private Integer restTime;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_athlet", nullable = false)
+ private Athlet athlet;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_exercise", nullable = false)
+ private Exercise exercise;
+
+ public Protokoll() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public Protokoll(LocalDateTime trainingDate, Integer numberOfSet, Integer repetitions, Double weight,
+ Boolean isTest, Double volume, Double oneRepMax, String notes, Integer rpe, Integer restTime, Athlet athlet,
+ Exercise exercise) {
+ super();
+ this.trainingDate = trainingDate;
+ this.numberOfSet = numberOfSet;
+ this.repetitions = repetitions;
+ this.weight = weight;
+ this.isTest = isTest;
+ this.volume = volume;
+ this.oneRepMax = oneRepMax;
+ this.notes = notes;
+ this.rpe = rpe;
+ this.restTime = restTime;
+ this.athlet = athlet;
+ this.exercise = exercise;
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the trainingDate
+ */
+ public LocalDateTime getTrainingDate() {
+ return trainingDate;
+ }
+
+ /**
+ * @param trainingDate the trainingDate to set
+ */
+ public void setTrainingDate(LocalDateTime trainingDate) {
+ this.trainingDate = trainingDate;
+ }
+
+ /**
+ * @return the numberOfSet
+ */
+ public Integer getNumberOfSet() {
+ return numberOfSet;
+ }
+
+ /**
+ * @param numberOfSet the numberOfSet to set
+ */
+ public void setNumberOfSet(Integer numberOfSet) {
+ this.numberOfSet = numberOfSet;
+ }
+
+ /**
+ * @return the repetitions
+ */
+ public Integer getRepetitions() {
+ return repetitions;
+ }
+
+ /**
+ * @param repetitions the repetitions to set
+ */
+ public void setRepetitions(Integer repetitions) {
+ this.repetitions = repetitions;
+ }
+
+ /**
+ * @return the weight
+ */
+ public Double getWeight() {
+ return weight;
+ }
+
+ /**
+ * @param weight the weight to set
+ */
+ public void setWeight(Double weight) {
+ this.weight = weight;
+ }
+
+ /**
+ * @return the isTest
+ */
+ public Boolean getIsTest() {
+ return isTest;
+ }
+
+ /**
+ * @param isTest the isTest to set
+ */
+ public void setIsTest(Boolean isTest) {
+ this.isTest = isTest;
+ }
+
+ /**
+ * @return the volume
+ */
+ public Double getVolume() {
+ return volume;
+ }
+
+ /**
+ * @param volume the volume to set
+ */
+ public void setVolume(Double volume) {
+ this.volume = volume;
+ }
+
+ /**
+ * @return the oneRepMax
+ */
+ public Double getOneRepMax() {
+ return oneRepMax;
+ }
+
+ /**
+ * @param oneRepMax the oneRepMax to set
+ */
+ public void setOneRepMax(Double oneRepMax) {
+ this.oneRepMax = oneRepMax;
+ }
+
+ /**
+ * @return the notes
+ */
+ public String getNotes() {
+ return notes;
+ }
+
+ /**
+ * @param notes the notes to set
+ */
+ public void setNotes(String notes) {
+ this.notes = notes;
+ }
+
+ /**
+ * @return the rpe
+ */
+ public Integer getRpe() {
+ return rpe;
+ }
+
+ /**
+ * @param rpe the rpe to set
+ */
+ public void setRpe(Integer rpe) {
+ this.rpe = rpe;
+ }
+
+ /**
+ * @return the restTime
+ */
+ public Integer getRestTime() {
+ return restTime;
+ }
+
+ /**
+ * @param restTime the restTime to set
+ */
+ public void setRestTime(Integer restTime) {
+ this.restTime = restTime;
+ }
+
+ /**
+ * @return the athlet
+ */
+ public Athlet getAthlet() {
+ return athlet;
+ }
+
+ /**
+ * @param athlet the athlet to set
+ */
+ public void setAthlet(Athlet athlet) {
+ this.athlet = athlet;
+ }
+
+ /**
+ * @return the exercise
+ */
+ public Exercise getExercise() {
+ return exercise;
+ }
+
+ /**
+ * @param exercise the exercise to set
+ */
+ public void setExercise(Exercise exercise) {
+ this.exercise = exercise;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((athlet == null) ? 0 : athlet.hashCode());
+ result = prime * result + ((exercise == null) ? 0 : exercise.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((isTest == null) ? 0 : isTest.hashCode());
+ result = prime * result + ((notes == null) ? 0 : notes.hashCode());
+ result = prime * result + ((numberOfSet == null) ? 0 : numberOfSet.hashCode());
+ result = prime * result + ((oneRepMax == null) ? 0 : oneRepMax.hashCode());
+ result = prime * result + ((repetitions == null) ? 0 : repetitions.hashCode());
+ result = prime * result + ((restTime == null) ? 0 : restTime.hashCode());
+ result = prime * result + ((rpe == null) ? 0 : rpe.hashCode());
+ result = prime * result + ((trainingDate == null) ? 0 : trainingDate.hashCode());
+ result = prime * result + ((volume == null) ? 0 : volume.hashCode());
+ result = prime * result + ((weight == null) ? 0 : weight.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Protokoll other = (Protokoll) obj;
+ if (athlet == null) {
+ if (other.athlet != null)
+ return false;
+ } else if (!athlet.equals(other.athlet))
+ return false;
+ if (exercise == null) {
+ if (other.exercise != null)
+ return false;
+ } else if (!exercise.equals(other.exercise))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (isTest == null) {
+ if (other.isTest != null)
+ return false;
+ } else if (!isTest.equals(other.isTest))
+ return false;
+ if (notes == null) {
+ if (other.notes != null)
+ return false;
+ } else if (!notes.equals(other.notes))
+ return false;
+ if (numberOfSet == null) {
+ if (other.numberOfSet != null)
+ return false;
+ } else if (!numberOfSet.equals(other.numberOfSet))
+ return false;
+ if (oneRepMax == null) {
+ if (other.oneRepMax != null)
+ return false;
+ } else if (!oneRepMax.equals(other.oneRepMax))
+ return false;
+ if (repetitions == null) {
+ if (other.repetitions != null)
+ return false;
+ } else if (!repetitions.equals(other.repetitions))
+ return false;
+ if (restTime == null) {
+ if (other.restTime != null)
+ return false;
+ } else if (!restTime.equals(other.restTime))
+ return false;
+ if (rpe == null) {
+ if (other.rpe != null)
+ return false;
+ } else if (!rpe.equals(other.rpe))
+ return false;
+ if (trainingDate == null) {
+ if (other.trainingDate != null)
+ return false;
+ } else if (!trainingDate.equals(other.trainingDate))
+ return false;
+ if (volume == null) {
+ if (other.volume != null)
+ return false;
+ } else if (!volume.equals(other.volume))
+ return false;
+ if (weight == null) {
+ if (other.weight != null)
+ return false;
+ } else if (!weight.equals(other.weight))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Protokoll [id=");
+ builder.append(id);
+ builder.append(", trainingDate=");
+ builder.append(trainingDate);
+ builder.append(", numberOfSet=");
+ builder.append(numberOfSet);
+ builder.append(", repetitions=");
+ builder.append(repetitions);
+ builder.append(", weight=");
+ builder.append(weight);
+ builder.append(", isTest=");
+ builder.append(isTest);
+ builder.append(", volume=");
+ builder.append(volume);
+ builder.append(", oneRepMax=");
+ builder.append(oneRepMax);
+ builder.append(", notes=");
+ builder.append(notes);
+ builder.append(", rpe=");
+ builder.append(rpe);
+ builder.append(", restTime=");
+ builder.append(restTime);
+ builder.append(", athlet=");
+ builder.append(athlet);
+ builder.append(", exercise=");
+ builder.append(exercise);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+}
+
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "tools", schema = "athletik")
+public class Tool {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "toolname_english", nullable = false)
+ private String toolnameEnglish;
+
+ @Column(name = "toolname_german", nullable = false)
+ private String toolnameGerman;
+
+ @Column(name = "min_weight", precision = 5, scale = 2)
+ private BigDecimal minWeight = BigDecimal.ZERO;
+
+ @Column(name = "steps_weight", precision = 5, scale = 2)
+ private BigDecimal stepsWeight = BigDecimal.ZERO;
+
+ @Column(name = "max_weight", precision = 5, scale = 2)
+ private BigDecimal maxWeight = BigDecimal.ZERO;
+
+ @Column(name = "description")
+ private String description;
+
+ public Tool() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public Tool(String toolnameEnglish, String toolnameGerman, BigDecimal minWeight, BigDecimal stepsWeight,
+ BigDecimal maxWeight, String description) {
+ super();
+ this.toolnameEnglish = toolnameEnglish;
+ this.toolnameGerman = toolnameGerman;
+ this.minWeight = minWeight;
+ this.stepsWeight = stepsWeight;
+ this.maxWeight = maxWeight;
+ this.description = description;
+ }
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the toolnameEnglish
+ */
+ public String getToolnameEnglish() {
+ return toolnameEnglish;
+ }
+
+ /**
+ * @param toolnameEnglish the toolnameEnglish to set
+ */
+ public void setToolnameEnglish(String toolnameEnglish) {
+ this.toolnameEnglish = toolnameEnglish;
+ }
+
+ /**
+ * @return the toolnameGerman
+ */
+ public String getToolnameGerman() {
+ return toolnameGerman;
+ }
+
+ /**
+ * @param toolnameGerman the toolnameGerman to set
+ */
+ public void setToolnameGerman(String toolnameGerman) {
+ this.toolnameGerman = toolnameGerman;
+ }
+
+ /**
+ * @return the minWeight
+ */
+ public BigDecimal getMinWeight() {
+ return minWeight;
+ }
+
+ /**
+ * @param minWeight the minWeight to set
+ */
+ public void setMinWeight(BigDecimal minWeight) {
+ this.minWeight = minWeight;
+ }
+
+ /**
+ * @return the stepsWeight
+ */
+ public BigDecimal getStepsWeight() {
+ return stepsWeight;
+ }
+
+ /**
+ * @param stepsWeight the stepsWeight to set
+ */
+ public void setStepsWeight(BigDecimal stepsWeight) {
+ this.stepsWeight = stepsWeight;
+ }
+
+ /**
+ * @return the maxWeight
+ */
+ public BigDecimal getMaxWeight() {
+ return maxWeight;
+ }
+
+ /**
+ * @param maxWeight the maxWeight to set
+ */
+ public void setMaxWeight(BigDecimal maxWeight) {
+ this.maxWeight = maxWeight;
+ }
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((maxWeight == null) ? 0 : maxWeight.hashCode());
+ result = prime * result + ((minWeight == null) ? 0 : minWeight.hashCode());
+ result = prime * result + ((stepsWeight == null) ? 0 : stepsWeight.hashCode());
+ result = prime * result + ((toolnameEnglish == null) ? 0 : toolnameEnglish.hashCode());
+ result = prime * result + ((toolnameGerman == null) ? 0 : toolnameGerman.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Tool other = (Tool) obj;
+ if (description == null) {
+ if (other.description != null)
+ return false;
+ } else if (!description.equals(other.description))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (maxWeight == null) {
+ if (other.maxWeight != null)
+ return false;
+ } else if (!maxWeight.equals(other.maxWeight))
+ return false;
+ if (minWeight == null) {
+ if (other.minWeight != null)
+ return false;
+ } else if (!minWeight.equals(other.minWeight))
+ return false;
+ if (stepsWeight == null) {
+ if (other.stepsWeight != null)
+ return false;
+ } else if (!stepsWeight.equals(other.stepsWeight))
+ return false;
+ if (toolnameEnglish == null) {
+ if (other.toolnameEnglish != null)
+ return false;
+ } else if (!toolnameEnglish.equals(other.toolnameEnglish))
+ return false;
+ if (toolnameGerman == null) {
+ if (other.toolnameGerman != null)
+ return false;
+ } else if (!toolnameGerman.equals(other.toolnameGerman))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Tools [id=");
+ builder.append(id);
+ builder.append(", toolnameEnglish=");
+ builder.append(toolnameEnglish);
+ builder.append(", toolnameGerman=");
+ builder.append(toolnameGerman);
+ builder.append(", minWeight=");
+ builder.append(minWeight);
+ builder.append(", stepsWeight=");
+ builder.append(stepsWeight);
+ builder.append(", maxWeight=");
+ builder.append(maxWeight);
+ builder.append(", description=");
+ builder.append(description);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PrePersist;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "training", schema = "athletik")
+public class Training {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "title", nullable = false, length = 200)
+ private String title;
+
+ @Column(name = "description", columnDefinition = "TEXT")
+ private String description;
+
+ @Column(name = "repetitions_of_set")
+ private Integer repetitionsOfSet;
+
+ @Column(name = "repetitions")
+ private Integer repetitions;
+
+ @Column(name = "factor_of_fmax", precision = 5, scale = 2)
+ private Double factorOfFmax;
+
+ @Column(name = "created", nullable = false, updatable = false)
+ private LocalDateTime created;
+
+ @Column(name = "valid_since", nullable = false)
+ private LocalDateTime validSince;
+
+ @Column(name = "valid_until")
+ private LocalDateTime validUntil;
+
+ @Column(name = "is_active")
+ private Boolean isActive = true;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_goal", nullable = false)
+ private Goal goal;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_athlet", nullable = false)
+ private Athlet athlet;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "fk_exercise", nullable = false)
+ private Exercise exercise;
+
+ public Training() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public Training(String title, String description, Integer repetitionsOfSet, Integer repetitions,
+ Double factorOfFmax, LocalDateTime created, LocalDateTime validSince, LocalDateTime validUntil,
+ Boolean isActive, Goal goal, Athlet athlet, Exercise exercise) {
+ super();
+ this.title = title;
+ this.description = description;
+ this.repetitionsOfSet = repetitionsOfSet;
+ this.repetitions = repetitions;
+ this.factorOfFmax = factorOfFmax;
+ this.created = created;
+ this.validSince = validSince;
+ this.validUntil = validUntil;
+ this.isActive = isActive;
+ this.goal = goal;
+ this.athlet = athlet;
+ this.exercise = exercise;
+ }
+
+
+
+ // Pre-Persist Callback
+ @PrePersist
+ protected void onCreate() {
+ if (created == null) {
+ created = LocalDateTime.now();
+ }
+ if (validSince == null) {
+ validSince = LocalDateTime.now();
+ }
+ }
+
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+ /**
+ * @return the title
+ */
+ public String getTitle() {
+ return title;
+ }
+
+
+ /**
+ * @param title the title to set
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+
+ /**
+ * @return the repetitionsOfSet
+ */
+ public Integer getRepetitionsOfSet() {
+ return repetitionsOfSet;
+ }
+
+
+ /**
+ * @param repetitionsOfSet the repetitionsOfSet to set
+ */
+ public void setRepetitionsOfSet(Integer repetitionsOfSet) {
+ this.repetitionsOfSet = repetitionsOfSet;
+ }
+
+
+ /**
+ * @return the repetitions
+ */
+ public Integer getRepetitions() {
+ return repetitions;
+ }
+
+
+ /**
+ * @param repetitions the repetitions to set
+ */
+ public void setRepetitions(Integer repetitions) {
+ this.repetitions = repetitions;
+ }
+
+
+ /**
+ * @return the factorOfFmax
+ */
+ public Double getFactorOfFmax() {
+ return factorOfFmax;
+ }
+
+
+ /**
+ * @param factorOfFmax the factorOfFmax to set
+ */
+ public void setFactorOfFmax(Double factorOfFmax) {
+ this.factorOfFmax = factorOfFmax;
+ }
+
+
+ /**
+ * @return the created
+ */
+ public LocalDateTime getCreated() {
+ return created;
+ }
+
+
+ /**
+ * @param created the created to set
+ */
+ public void setCreated(LocalDateTime created) {
+ this.created = created;
+ }
+
+
+ /**
+ * @return the validSince
+ */
+ public LocalDateTime getValidSince() {
+ return validSince;
+ }
+
+
+ /**
+ * @param validSince the validSince to set
+ */
+ public void setValidSince(LocalDateTime validSince) {
+ this.validSince = validSince;
+ }
+
+
+ /**
+ * @return the validUntil
+ */
+ public LocalDateTime getValidUntil() {
+ return validUntil;
+ }
+
+
+ /**
+ * @param validUntil the validUntil to set
+ */
+ public void setValidUntil(LocalDateTime validUntil) {
+ this.validUntil = validUntil;
+ }
+
+
+ /**
+ * @return the isActive
+ */
+ public Boolean getIsActive() {
+ return isActive;
+ }
+
+
+ /**
+ * @param isActive the isActive to set
+ */
+ public void setIsActive(Boolean isActive) {
+ this.isActive = isActive;
+ }
+
+
+ /**
+ * @return the goal
+ */
+ public Goal getGoal() {
+ return goal;
+ }
+
+
+ /**
+ * @param goal the goal to set
+ */
+ public void setGoal(Goal goal) {
+ this.goal = goal;
+ }
+
+
+ /**
+ * @return the athlet
+ */
+ public Athlet getAthlet() {
+ return athlet;
+ }
+
+
+ /**
+ * @param athlet the athlet to set
+ */
+ public void setAthlet(Athlet athlet) {
+ this.athlet = athlet;
+ }
+
+
+ /**
+ * @return the exercise
+ */
+ public Exercise getExercise() {
+ return exercise;
+ }
+
+
+ /**
+ * @param exercise the exercise to set
+ */
+ public void setExercise(Exercise exercise) {
+ this.exercise = exercise;
+ }
+
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((athlet == null) ? 0 : athlet.hashCode());
+ result = prime * result + ((created == null) ? 0 : created.hashCode());
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + ((exercise == null) ? 0 : exercise.hashCode());
+ result = prime * result + ((factorOfFmax == null) ? 0 : factorOfFmax.hashCode());
+ result = prime * result + ((goal == null) ? 0 : goal.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((isActive == null) ? 0 : isActive.hashCode());
+ result = prime * result + ((repetitions == null) ? 0 : repetitions.hashCode());
+ result = prime * result + ((repetitionsOfSet == null) ? 0 : repetitionsOfSet.hashCode());
+ result = prime * result + ((title == null) ? 0 : title.hashCode());
+ result = prime * result + ((validSince == null) ? 0 : validSince.hashCode());
+ result = prime * result + ((validUntil == null) ? 0 : validUntil.hashCode());
+ return result;
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Training other = (Training) obj;
+ if (athlet == null) {
+ if (other.athlet != null)
+ return false;
+ } else if (!athlet.equals(other.athlet))
+ return false;
+ if (created == null) {
+ if (other.created != null)
+ return false;
+ } else if (!created.equals(other.created))
+ return false;
+ if (description == null) {
+ if (other.description != null)
+ return false;
+ } else if (!description.equals(other.description))
+ return false;
+ if (exercise == null) {
+ if (other.exercise != null)
+ return false;
+ } else if (!exercise.equals(other.exercise))
+ return false;
+ if (factorOfFmax == null) {
+ if (other.factorOfFmax != null)
+ return false;
+ } else if (!factorOfFmax.equals(other.factorOfFmax))
+ return false;
+ if (goal == null) {
+ if (other.goal != null)
+ return false;
+ } else if (!goal.equals(other.goal))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (isActive == null) {
+ if (other.isActive != null)
+ return false;
+ } else if (!isActive.equals(other.isActive))
+ return false;
+ if (repetitions == null) {
+ if (other.repetitions != null)
+ return false;
+ } else if (!repetitions.equals(other.repetitions))
+ return false;
+ if (repetitionsOfSet == null) {
+ if (other.repetitionsOfSet != null)
+ return false;
+ } else if (!repetitionsOfSet.equals(other.repetitionsOfSet))
+ return false;
+ if (title == null) {
+ if (other.title != null)
+ return false;
+ } else if (!title.equals(other.title))
+ return false;
+ if (validSince == null) {
+ if (other.validSince != null)
+ return false;
+ } else if (!validSince.equals(other.validSince))
+ return false;
+ if (validUntil == null) {
+ if (other.validUntil != null)
+ return false;
+ } else if (!validUntil.equals(other.validUntil))
+ return false;
+ return true;
+ }
+
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Training [id=");
+ builder.append(id);
+ builder.append(", title=");
+ builder.append(title);
+ builder.append(", description=");
+ builder.append(description);
+ builder.append(", repetitionsOfSet=");
+ builder.append(repetitionsOfSet);
+ builder.append(", repetitions=");
+ builder.append(repetitions);
+ builder.append(", factorOfFmax=");
+ builder.append(factorOfFmax);
+ builder.append(", created=");
+ builder.append(created);
+ builder.append(", validSince=");
+ builder.append(validSince);
+ builder.append(", validUntil=");
+ builder.append(validUntil);
+ builder.append(", isActive=");
+ builder.append(isActive);
+ builder.append(", goal=");
+ builder.append(goal);
+ builder.append(", athlet=");
+ builder.append(athlet);
+ builder.append(", exercise=");
+ builder.append(exercise);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.math.BigDecimal;
+
+public interface ViewAllExercises {
+ Long getIdExercise();
+ String getNameEnglish();
+ String getDescriptionEnglish();
+ String getNameGerman();
+ String getDescriptionGerman();
+ String getUrlVideo();
+ Long getIdTool();
+ String getToolnameEnglish();
+ String getToolnameGerman();
+ BigDecimal getMinWeight();
+ BigDecimal getMaxWeight();
+ BigDecimal getStepsWeight();
+ String getDescription();
+ Long getId();
+ String getNameLatin();
+ String getMuscleNameEnglish();
+ String getMuscleNameGerman();
+ String getMovementEnglish();
+ String getMovementGerman();
+ Long getFkMusclegroup();
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+public interface ViewMusclegroups {
+ Long getId();
+ String getNameEnglish();
+ String getNameGerman();
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+public interface ViewMuscles {
+ Long getId();
+ String getNameLatin();
+ String getNameEnglish();
+ String getNameGerman();
+ String getMovementEnglish();
+ String getMovementGerman();
+ Long getFkMusclegroup();
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.time.LocalDateTime;
+
+public interface ViewProtokollSetsOfToday {
+ Long getFkUser();
+ Long getFkExercise();
+ LocalDateTime getTrainingdate();
+ Integer getNumberOfSet();
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.math.BigDecimal;
+
+public interface ViewTools {
+ Long getId();
+ String getToolnameEnglish();
+ String getToolnameGerman();
+ BigDecimal getMinWeight();
+ BigDecimal getStepsWeight();
+ BigDecimal getMaxWeight();
+ String getDescription();
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+import java.math.BigDecimal;
+
+public interface ViewToolweights {
+ Long getId();
+ BigDecimal getMinWeight();
+ BigDecimal getStepsWeight();
+ BigDecimal getMaxWeight();
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.model;
+
+public interface ViewUsers {
+ Long getId();
+ String getUsername();
+ String getNameUser();
+ String getEmail();
+ String getPass();
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import com.triathlon_coaching.product.athletik.backend.model.Athlet;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+@Repository
+public interface AthletRepository extends JpaRepository<Athlet, Long> {
+
+ Optional<Athlet> findByUsername(String username);
+
+ Optional<Athlet> findByEmail(String email);
+
+ Boolean existsByUsername(String username);
+
+ Boolean existsByEmail(String email);
+
+ @Query("SELECT a FROM Athlet a JOIN a.gyms g WHERE g.id = :gymId")
+ java.util.List<Athlet> findByGymId(@Param("gymId") Long gymId);
+
+ java.util.List<Athlet> findByIsActive(Boolean isActive);
+
+ java.util.List<Athlet> findByFullnameContainingIgnoreCase(String name);
+
+ @Query("SELECT a FROM Athlet a WHERE a.lastLogin < :date")
+ java.util.List<Athlet> findInactiveSince(@Param("date") LocalDateTime date);
+
+ @Transactional
+ @Modifying
+ @Query("UPDATE Athlet a SET a.lastLogin = :lastLogin WHERE a.id = :id")
+ void updateLastLogin(@Param("id") Long id, @Param("lastLogin") LocalDateTime lastLogin);
+
+ @Transactional
+ @Modifying
+ @Query("UPDATE Athlet a SET a.isActive = :isActive WHERE a.id = :id")
+ void updateActiveStatus(@Param("id") Long id, @Param("isActive") Boolean isActive);
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import com.triathlon_coaching.product.athletik.backend.model.Exercise;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ExerciseRepository extends JpaRepository<Exercise, Long> {
+ @Query("SELECT e FROM Exercise e JOIN e.muscles m WHERE m.musclegroupNameEnglish = :muscleGroup")
+ List<Exercise> findByMuscleGroup(@Param("muscleGroup") String muscleGroup);
+
+ @Query("SELECT e FROM Exercise e JOIN e.muscles m WHERE m.id = :muscleId")
+ List<Exercise> findByMuscleId(@Param("muscleId") Long muscleId);
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import com.triathlon_coaching.product.athletik.backend.model.Goal;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface GoalRepository extends JpaRepository<Goal, Long> {
+
+ Optional<Goal> findByGoalname(String goalname);
+
+ List<Goal> findByGoalnameContainingIgnoreCase(String goalname);
+
+ List<Goal> findByDescriptionContainingIgnoreCase(String description);
+
+ @Query("SELECT g FROM Goal g JOIN g.trainings t WHERE t.athlet.id = :athletId")
+ List<Goal> findByAthletId(@Param("athletId") Long athletId);
+
+ @Query("SELECT g FROM Goal g JOIN g.trainings t WHERE t.exercise.id = :exerciseId")
+ List<Goal> findByExerciseId(@Param("exerciseId") Long exerciseId);
+
+ @Query("SELECT DISTINCT g FROM Goal g WHERE g.id NOT IN (SELECT t.goal.id FROM Training t WHERE t.athlet.id = :athletId)")
+ List<Goal> findAvailableForAthlet(@Param("athletId") Long athletId);
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.triathlon_coaching.product.athletik.backend.model.Gym;
+
+@Repository
+public interface GymRepository extends JpaRepository<Gym, Long> {
+
+ @Query("SELECT g FROM Gym g JOIN g.athleten a WHERE a.id = :athletId")
+ List<Gym> findByAthletenId(@Param("athletId") Long athletId);
+
+ List<Gym> findByGymnameContainingIgnoreCase(String name);
+
+ List<Gym> findByGymlocationContainingIgnoreCase(String location);
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import com.triathlon_coaching.product.athletik.backend.model.Log;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Repository
+public interface LogRepository extends JpaRepository<Log, Long> {
+
+ List<Log> findByAthletIdOrderByCreatedDesc(Long athletId);
+
+ Page<Log> findByAthletIdOrderByCreatedDesc(Long athletId, Pageable pageable);
+
+ List<Log> findBySid(String sid);
+
+ List<Log> findByScriptContainingIgnoreCase(String script);
+
+ List<Log> findByLogLevel(String logLevel);
+
+ List<Log> findByLogdataContainingIgnoreCase(String logdata);
+
+ List<Log> findByCreatedBetween(LocalDateTime start, LocalDateTime end);
+
+ List<Log> findByCreatedBefore(LocalDateTime date);
+
+ @Query("SELECT l FROM Log l WHERE l.athlet.id = :athletId AND l.created BETWEEN :start AND :end ORDER BY l.created DESC")
+ List<Log> findByAthletIdAndCreatedBetween(@Param("athletId") Long athletId,
+ @Param("start") LocalDateTime start,
+ @Param("end") LocalDateTime end);
+
+ @Query("SELECT l FROM Log l WHERE l.athlet.id = :athletId AND l.logLevel = :logLevel ORDER BY l.created DESC")
+ List<Log> findByAthletIdAndLogLevel(@Param("athletId") Long athletId,
+ @Param("logLevel") String logLevel);
+
+ @Query("SELECT l FROM Log l WHERE l.athlet.id = :athletId AND LOWER(l.logdata) LIKE LOWER(CONCAT('%', :searchTerm, '%')) ORDER BY l.created DESC")
+ List<Log> findByAthletIdAndLogdataContaining(@Param("athletId") Long athletId,
+ @Param("searchTerm") String searchTerm);
+
+ @Query("SELECT COUNT(l) FROM Log l WHERE l.athlet.id = :athletId AND l.created >= :since")
+ Long countByAthletIdSince(@Param("athletId") Long athletId,
+ @Param("since") LocalDateTime since);
+
+ @Query("SELECT DISTINCT l.script FROM Log l WHERE l.athlet.id = :athletId")
+ List<String> findDistinctScriptsByAthletId(@Param("athletId") Long athletId);
+
+ @Query("SELECT DISTINCT l.logLevel FROM Log l WHERE l.athlet.id = :athletId")
+ List<String> findDistinctLogLevelsByAthletId(@Param("athletId") Long athletId);
+
+ @Query("SELECT l FROM Log l WHERE l.athlet.id = :athletId AND l.created = (SELECT MAX(l2.created) FROM Log l2 WHERE l2.athlet.id = :athletId)")
+ Log findLatestByAthletId(@Param("athletId") Long athletId);
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.triathlon_coaching.product.athletik.backend.model.Muscle;
+
+@Repository
+public interface MuscleRepository extends JpaRepository<Muscle, Long> {
+
+ @Query("SELECT DISTINCT m.musclegroupNameEnglish FROM Muscle m WHERE m.musclegroupNameEnglish IS NOT NULL")
+ List<String> findAllMuscleGroups();
+
+ @Query("SELECT m FROM Muscle m WHERE m.musclegroupNameEnglish = :group OR m.musclegroupNameGerman = :group")
+ List<Muscle> findByMuscleGroup(@Param("group") String group);
+
+ @Query("SELECT m FROM Muscle m JOIN m.exercises e WHERE e.id = :exerciseId")
+ List<Muscle> findByExercisesId(@Param("exerciseId") Long exerciseId);
+
+ List<Muscle> findByMuscleNameLatinContainingIgnoreCase(String name);
+
+ List<Muscle> findByMuscleNameEnglishContainingIgnoreCase(String name);
+
+ List<Muscle> findByMuscleNameGermanContainingIgnoreCase(String name);
+
+ @Query("SELECT m FROM Muscle m WHERE LOWER(m.movementEnglish) LIKE LOWER(CONCAT('%', :movement, '%')) OR LOWER(m.movementGerman) LIKE LOWER(CONCAT('%', :movement, '%'))")
+ List<Muscle> findByMovementContainingIgnoreCase(@Param("movement") String movement);
+
+ List<Muscle> findByMusclegroupNameEnglishOrMusclegroupNameGerman(String muscleGroup, String muscleGroup2);
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import com.triathlon_coaching.product.athletik.backend.model.Protokoll;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Repository
+public interface ProtokollRepository extends JpaRepository<Protokoll, Long> {
+
+ List<Protokoll> findByAthletIdOrderByTrainingDateDesc(Long athletId);
+
+ List<Protokoll> findByAthletIdAndExerciseIdOrderByTrainingDateDesc(Long athletId, Long exerciseId);
+
+ List<Protokoll> findByAthletIdAndTrainingDateBetween(Long athletId, LocalDateTime start, LocalDateTime end);
+
+ List<Protokoll> findByAthletIdAndIsTest(Long athletId, Boolean isTest);
+
+ List<Protokoll> findByAthletIdAndExerciseIdAndIsTest(Long athletId, Long exerciseId, Boolean isTest);
+
+ @Query("SELECT p FROM Protokoll p WHERE p.athlet.id = :athletId AND DATE(p.trainingDate) = CURRENT_DATE")
+ List<Protokoll> findTodaySessionsByAthletId(@Param("athletId") Long athletId);
+
+ @Query("SELECT MAX(p.numberOfSet) FROM Protokoll p WHERE p.athlet.id = :athletId AND p.exercise.id = :exerciseId AND DATE(p.trainingDate) = CURRENT_DATE")
+ Integer findMaxSetNumberForToday(@Param("athletId") Long athletId, @Param("exerciseId") Long exerciseId);
+
+ @Query("SELECT p FROM Protokoll p WHERE p.athlet.id = :athletId AND p.exercise.id = :exerciseId AND p.isTest = true ORDER BY p.trainingDate DESC")
+ List<Protokoll> findLatestTestsByAthletAndExercise(@Param("athletId") Long athletId, @Param("exerciseId") Long exerciseId);
+
+ @Query("SELECT p FROM Protokoll p WHERE p.athlet.id = :athletId AND p.exercise.id = :exerciseId AND p.isTest = false ORDER BY p.trainingDate DESC")
+ List<Protokoll> findLatestTrainingsByAthletAndExercise(@Param("athletId") Long athletId, @Param("exerciseId") Long exerciseId);
+
+ @Query("SELECT p FROM Protokoll p WHERE p.athlet.id = :athletId AND p.trainingDate = (SELECT MAX(p2.trainingDate) FROM Protokoll p2 WHERE p2.athlet.id = :athletId AND p2.exercise.id = p.exercise.id AND p2.isTest = true)")
+ List<Protokoll> findLatestTestForEachExercise(@Param("athletId") Long athletId);
+
+ @Query("SELECT p FROM Protokoll p WHERE p.athlet.id = :athletId AND p.exercise.id = :exerciseId ORDER BY p.trainingDate DESC, p.numberOfSet DESC")
+ Page<Protokoll> findByAthletIdAndExerciseIdPaged(@Param("athletId") Long athletId, @Param("exerciseId") Long exerciseId, Pageable pageable);
+
+ @Query("SELECT SUM(p.volume) FROM Protokoll p WHERE p.athlet.id = :athletId AND p.trainingDate BETWEEN :start AND :end")
+ Double findTotalVolumeByAthletIdAndDateRange(@Param("athletId") Long athletId, @Param("start") LocalDateTime start, @Param("end") LocalDateTime end);
+
+ @Query("SELECT p FROM Protokoll p WHERE p.athlet.id = :athletId AND p.weight >= :minWeight")
+ List<Protokoll> findByAthletIdAndMinWeight(@Param("athletId") Long athletId, @Param("minWeight") Double minWeight);
+
+ @Query("SELECT p FROM Protokoll p WHERE p.athlet.id = :athletId AND p.oneRepMax IS NOT NULL ORDER BY p.oneRepMax DESC")
+ List<Protokoll> findPersonalRecords(@Param("athletId") Long athletId);
+
+ Long countByAthletIdAndTrainingDateAfter(Long athletId, LocalDateTime date);
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import com.triathlon_coaching.product.athletik.backend.model.Tool;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+
+import com.triathlon_coaching.product.athletik.backend.model.Tool;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ToolRepository extends JpaRepository<Tool, Long> {
+
+ @Query("SELECT t FROM Tool t JOIN t.gyms g WHERE g.id = :gymId")
+ List<Tool> findByGymsId(@Param("gymId") Long gymId);
+
+ List<Tool> findByToolnameEnglishContainingIgnoreCase(String name);
+
+ List<Tool> findByToolnameGermanContainingIgnoreCase(String name);
+
+ @Query("SELECT t FROM Tool t WHERE t.minWeight <= :weight AND t.maxWeight >= :weight")
+ List<Tool> findByWeightRange(@Param("weight") Double weight);
+
+ @Query("SELECT t FROM Tool t WHERE t.minWeight <= :weight AND t.maxWeight >= :weight AND :weight % t.stepsWeight = 0")
+ List<Tool> findByWeightAndStep(@Param("weight") Double weight);
+
+ List<Tool> findByMinWeightGreaterThanEqual(Double minWeight);
+
+ List<Tool> findByMaxWeightLessThanEqual(Double maxWeight);
+
+ List<Tool> findByMinWeightLessThanEqualAndMaxWeightGreaterThanEqual(Double minWeight, Double maxWeight);
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.repo;
+
+import com.triathlon_coaching.product.athletik.backend.model.Training;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface TrainingRepository extends JpaRepository<Training, Long> {
+
+ List<Training> findByAthletIdOrderByCreatedDesc(Long athletId);
+
+ List<Training> findByAthletIdAndIsActiveTrue(Long athletId);
+
+ List<Training> findByExerciseId(Long exerciseId);
+
+ List<Training> findByGoalId(Long goalId);
+
+ @Query("SELECT t FROM Training t WHERE t.athlet.id = :athletId AND t.isActive = true AND " +
+ "(t.validSince IS NULL OR t.validSince <= :now) AND " +
+ "(t.validUntil IS NULL OR t.validUntil >= :now)")
+ List<Training> findActiveByAthletId(@Param("athletId") Long athletId, @Param("now") LocalDateTime now);
+
+ @Query("SELECT t FROM Training t WHERE t.athlet.id = :athletId AND t.exercise.id = :exerciseId AND t.isActive = true")
+ List<Training> findByAthletIdAndExerciseId(@Param("athletId") Long athletId, @Param("exerciseId") Long exerciseId);
+
+ @Query("SELECT t FROM Training t WHERE t.athlet.id = :athletId AND t.goal.id = :goalId AND t.isActive = true")
+ List<Training> findByAthletIdAndGoalId(@Param("athletId") Long athletId, @Param("goalId") Long goalId);
+
+ @Query("SELECT t FROM Training t WHERE t.created BETWEEN :start AND :end")
+ List<Training> findByCreatedBetween(@Param("start") LocalDateTime start, @Param("end") LocalDateTime end);
+
+ @Query("SELECT t FROM Training t WHERE t.validSince <= :date AND (t.validUntil IS NULL OR t.validUntil >= :date)")
+ List<Training> findValidAt(@Param("date") LocalDateTime date);
+
+ Optional<Training> findByAthletIdAndExerciseIdAndRepetitionsOfSetAndRepetitionsAndFactorOfFmax(
+ Long athletId, Long exerciseId, Integer repetitionsOfSet, Integer repetitions, Double factorOfFmax);
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Athlet;
+import com.triathlon_coaching.product.athletik.backend.repo.AthletRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class AthletService {
+
+ @Autowired
+ private AthletRepository athletRepository;
+
+ @Autowired
+ private PasswordEncoder passwordEncoder;
+
+ @Autowired
+ private EmailService emailService;
+
+ public List<Athlet> findAllAthleten() {
+ return athletRepository.findAll();
+ }
+
+ public Optional<Athlet> findAthletById(Long id) {
+ return athletRepository.findById(id);
+ }
+
+ public Optional<Athlet> findAthletByUsername(String username) {
+ return athletRepository.findByUsername(username);
+ }
+
+ public Optional<Athlet> findAthletByEmail(String email) {
+ return athletRepository.findByEmail(email);
+ }
+
+ public List<Athlet> findAthletenByGymId(Long gymId) {
+ return athletRepository.findByGymId(gymId);
+ }
+
+ public boolean existsByUsername(String username) {
+ return athletRepository.existsByUsername(username);
+ }
+
+ public boolean existsByEmail(String email) {
+ return athletRepository.existsByEmail(email);
+ }
+
+ public Athlet saveAthlet(Athlet athlet) {
+ return athletRepository.save(athlet);
+ }
+
+ @Transactional
+ public Athlet registerAthlet(Athlet athlet) {
+ // Passwort hashen
+ athlet.setPass(passwordEncoder.encode(athlet.getPass()));
+ Athlet savedAthlet = athletRepository.save(athlet);
+
+ // Willkommens-E-Mail senden
+ emailService.sendWelcomeEmail(savedAthlet);
+
+ return savedAthlet;
+ }
+
+ public Optional<Athlet> authenticate(String username, String password) {
+ Optional<Athlet> athletOptional = athletRepository.findByUsername(username);
+ if (athletOptional.isPresent()) {
+ Athlet athlet = athletOptional.get();
+ if (passwordEncoder.matches(password, athlet.getPass())) {
+ // Last Login aktualisieren
+ athlet.setLastLogin(LocalDateTime.now());
+ athletRepository.save(athlet);
+ return Optional.of(athlet);
+ }
+ }
+ return Optional.empty();
+ }
+
+ @Transactional
+ public boolean updatePassword(Long id, String currentPassword, String newPassword) {
+ Optional<Athlet> athletOptional = athletRepository.findById(id);
+ if (athletOptional.isPresent()) {
+ Athlet athlet = athletOptional.get();
+ if (passwordEncoder.matches(currentPassword, athlet.getPass())) {
+ athlet.setPass(passwordEncoder.encode(newPassword));
+ athletRepository.save(athlet);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void deleteAthlet(Long id) {
+ athletRepository.deleteById(id);
+ }
+
+ @Transactional
+ public void deactivateAthlet(Long id) {
+ athletRepository.updateActiveStatus(id, false);
+ }
+
+ @Transactional
+ public void activateAthlet(Long id) {
+ athletRepository.updateActiveStatus(id, true);
+ }
+
+ @Transactional
+ public void updateLastLogin(Long id) {
+ athletRepository.updateLastLogin(id, LocalDateTime.now());
+ }
+
+ public List<Athlet> findInactiveAthletenSince(LocalDateTime date) {
+ return athletRepository.findInactiveSince(date);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Athlet;
+import com.triathlon_coaching.product.athletik.backend.model.Protokoll;
+import com.triathlon_coaching.product.athletik.backend.repo.AthletRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+
+@Service
+public class EmailService {
+
+ @Autowired
+ private JavaMailSender mailSender;
+
+ @Autowired
+ private TemplateEngine templateEngine;
+
+ @Autowired
+ private AthletRepository athletRepository;
+
+ @Async
+ public void sendTrainingSummary(Long athletId, List<Protokoll> trainingData) {
+ Optional<Athlet> athletOptional = athletRepository.findById(athletId);
+ if (!athletOptional.isPresent()) {
+ return;
+ }
+
+ Athlet athlet = athletOptional.get();
+ String emailContent = generateTrainingSummaryEmail(athlet, trainingData);
+
+ try {
+ MimeMessage message = mailSender.createMimeMessage();
+ MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
+
+ helper.setTo(athlet.getEmail());
+ helper.setSubject("Ihr Training vom " + LocalDate.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy")));
+ helper.setText(emailContent, true);
+
+ mailSender.send(message);
+ } catch (MessagingException e) {
+ // Logging des Fehlers
+ System.err.println("Fehler beim Senden der E-Mail: " + e.getMessage());
+ }
+ }
+
+ private String generateTrainingSummaryEmail(Athlet athlet, List<Protokoll> trainingData) {
+ Context context = new Context(Locale.GERMAN);
+ context.setVariable("athlet", athlet);
+ context.setVariable("trainingData", trainingData);
+ context.setVariable("trainingDate", LocalDate.now());
+ // context.setVariable("totalVolume", calculateTotalVolume(trainingData));
+ context.setVariable("totalSets", trainingData.size());
+
+ return templateEngine.process("email/training-summary", context);
+ }
+
+ /*
+ private double calculateTotalVolume(List<Protokoll> trainingData) {
+ return trainingData.stream()
+ .mapToDouble(p -> p.getWeight() * p.getRepetitions())
+ .sum();
+ }
+ */
+ @Async
+ public void sendWelcomeEmail(Athlet athlet) {
+ Context context = new Context(Locale.GERMAN);
+ context.setVariable("athlet", athlet);
+
+ String emailContent = templateEngine.process("email/welcome", context);
+
+ try {
+ MimeMessage message = mailSender.createMimeMessage();
+ MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
+
+ helper.setTo(athlet.getEmail());
+ helper.setSubject("Willkommen bei Athletik Training!");
+ helper.setText(emailContent, true);
+
+ mailSender.send(message);
+ } catch (MessagingException e) {
+ System.err.println("Fehler beim Senden der Willkommens-E-Mail: " + e.getMessage());
+ }
+ }
+
+ @Async
+ public void sendPasswordResetEmail(Athlet athlet, String resetToken) {
+ Context context = new Context(Locale.GERMAN);
+ context.setVariable("athlet", athlet);
+ context.setVariable("resetToken", resetToken);
+
+ String emailContent = templateEngine.process("email/password-reset", context);
+
+ try {
+ MimeMessage message = mailSender.createMimeMessage();
+ MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
+
+ helper.setTo(athlet.getEmail());
+ helper.setSubject("Passwort zurücksetzen - Athletik Training");
+ helper.setText(emailContent, true);
+
+ mailSender.send(message);
+ } catch (MessagingException e) {
+ System.err.println("Fehler beim Senden der Passwort-Reset-E-Mail: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Exercise;
+import com.triathlon_coaching.product.athletik.backend.model.Muscle;
+import com.triathlon_coaching.product.athletik.backend.repo.ExerciseRepository;
+import com.triathlon_coaching.product.athletik.backend.repo.MuscleRepository;
+import com.triathlon_coaching.product.athletik.backend.repo.ToolRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class ExerciseService {
+
+ @Autowired
+ private ExerciseRepository exerciseRepository;
+
+ @Autowired
+ private MuscleRepository muscleRepository;
+
+ @Autowired
+ private ToolRepository toolRepository;
+
+ public List<Exercise> findAllExercises() {
+ return exerciseRepository.findAll();
+ }
+
+ public Optional<Exercise> findExerciseById(Long id) {
+ return exerciseRepository.findById(id);
+ }
+
+ public List<Exercise> findExercisesByMuscleGroup(String muscleGroup) {
+ return exerciseRepository.findByMuscleGroup(muscleGroup);
+ }
+
+ public List<Exercise> findExercisesByMuscleId(Long muscleId) {
+ return exerciseRepository.findByMuscleId(muscleId);
+ }
+
+ public List<String> findAllMuscleGroups() {
+ return muscleRepository.findAllMuscleGroups();
+ }
+
+ public List<Muscle> findAllMuscles() {
+ return muscleRepository.findAll();
+ }
+
+ public List<Muscle> findMusclesByGroup(String muscleGroup) {
+ return muscleRepository.findByMusclegroupNameEnglishOrMusclegroupNameGerman(muscleGroup, muscleGroup);
+ }
+
+ public List<Double> getWeightsForTool(Long toolId) {
+ return toolRepository.findById(toolId)
+ .map(tool -> {
+ List<Double> weights = new ArrayList<>();
+ double current = tool.getMinWeight();
+ while (current <= tool.getMaxWeight()) {
+ weights.add(current);
+ current += tool.getStepsWeight();
+ }
+ return weights;
+ })
+ .orElse(Collections.emptyList());
+ }
+
+ public Map<String, Object> getExerciseSummary() {
+ Map<String, Object> summary = new HashMap<>();
+
+ List<String> muscleGroups = findAllMuscleGroups();
+ summary.put("muscleGroups", muscleGroups);
+
+ Map<String, List<Muscle>> musclesByGroup = new HashMap<>();
+ for (String group : muscleGroups) {
+ musclesByGroup.put(group, findMusclesByGroup(group));
+ }
+ summary.put("musclesByGroup", musclesByGroup);
+
+ Map<Long, List<Exercise>> exercisesByMuscle = new HashMap<>();
+ List<Muscle> allMuscles = findAllMuscles();
+ for (Muscle muscle : allMuscles) {
+ exercisesByMuscle.put(muscle.getId(), findExercisesByMuscleId(muscle.getId()));
+ }
+ summary.put("exercisesByMuscle", exercisesByMuscle);
+
+ return summary;
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Goal;
+import com.triathlon_coaching.product.athletik.backend.repo.GoalRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class GoalService {
+
+ @Autowired
+ private GoalRepository goalRepository;
+
+ public List<Goal> findAllGoals() {
+ return goalRepository.findAll();
+ }
+
+ public Optional<Goal> findGoalById(Long id) {
+ return goalRepository.findById(id);
+ }
+
+ public Optional<Goal> findGoalByName(String goalname) {
+ return goalRepository.findByGoalname(goalname);
+ }
+
+ public List<Goal> findGoalsByAthletId(Long athletId) {
+ return goalRepository.findByAthletId(athletId);
+ }
+
+ public List<Goal> findGoalsByExerciseId(Long exerciseId) {
+ return goalRepository.findByExerciseId(exerciseId);
+ }
+
+ public List<Goal> findAvailableGoalsForAthlet(Long athletId) {
+ return goalRepository.findAvailableForAthlet(athletId);
+ }
+
+ public List<Goal> searchGoals(String searchTerm) {
+ List<Goal> byName = goalRepository.findByGoalnameContainingIgnoreCase(searchTerm);
+ List<Goal> byDescription = goalRepository.findByDescriptionContainingIgnoreCase(searchTerm);
+
+ // Duplikate entfernen und kombinieren
+ byName.addAll(byDescription.stream()
+ .filter(goal -> !byName.contains(goal))
+ .toList());
+
+ return byName;
+ }
+
+ public Goal saveGoal(Goal goal) {
+ return goalRepository.save(goal);
+ }
+
+ public void deleteGoal(Long id) {
+ goalRepository.deleteById(id);
+ }
+
+ public boolean existsByName(String goalname) {
+ return goalRepository.findByGoalname(goalname).isPresent();
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Gym;
+import com.triathlon_coaching.product.athletik.backend.repo.GymRepository;
+
+@Service
+public class GymService {
+
+ @Autowired
+ private GymRepository gymRepository;
+
+ public List<Gym> findAllGyms() {
+ return gymRepository.findAll();
+ }
+
+ public Optional<Gym> findGymById(Long id) {
+ return gymRepository.findById(id);
+ }
+
+ public List<Gym> findGymsByAthletId(Long athletId) {
+ return gymRepository.findByAthletenId(athletId);
+ }
+
+ public Gym saveGym(Gym gym) {
+ return gymRepository.save(gym);
+ }
+
+ public void deleteGym(Long id) {
+ gymRepository.deleteById(id);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Log;
+import com.triathlon_coaching.product.athletik.backend.repo.LogRepository;
+
+@Service
+public class LogService {
+
+ @Autowired
+ private LogRepository logRepository;
+
+ @Autowired
+ private AthletService athletService;
+
+ public List<Log> findAllLogs() {
+ return logRepository.findAll();
+ }
+
+ public List<Log> findByAthletId(Long athletId) {
+ return logRepository.findByAthletIdOrderByCreatedDesc(athletId);
+ }
+
+ public Page<Log> findByAthletId(Long athletId, Pageable pageable) {
+ return logRepository.findByAthletIdOrderByCreatedDesc(athletId, pageable);
+ }
+
+ public List<Log> findByAthletIdAndDateRange(Long athletId, LocalDateTime start, LocalDateTime end) {
+ return logRepository.findByAthletIdAndCreatedBetween(athletId, start, end);
+ }
+
+ public List<Log> findByAthletIdAndLogLevel(Long athletId, String logLevel) {
+ return logRepository.findByAthletIdAndLogLevel(athletId, logLevel);
+ }
+
+ public List<Log> searchByAthletIdAndLogdata(Long athletId, String searchTerm) {
+ return logRepository.findByAthletIdAndLogdataContaining(athletId, searchTerm);
+ }
+
+ public Log saveLog(Log log) {
+ return logRepository.save(log);
+ }
+
+ public void deleteLog(Long id) {
+ logRepository.deleteById(id);
+ }
+
+ public void deleteOldLogs(LocalDateTime before) {
+ List<Log> oldLogs = logRepository.findByCreatedBefore(before);
+ logRepository.deleteAll(oldLogs);
+ }
+
+ // Hilfsmethoden für das Logging
+ public void logInfo(Long athletId, String logdata, String script, HttpServletRequest request) {
+ createLog(athletId, logdata, "INFO", script, request);
+ }
+
+ public void logWarning(Long athletId, String logdata, String script, HttpServletRequest request) {
+ createLog(athletId, logdata, "WARNING", script, request);
+ }
+
+ public void logError(Long athletId, String logdata, String script, HttpServletRequest request) {
+ createLog(athletId, logdata, "ERROR", script, request);
+ }
+
+ public void logDebug(Long athletId, String logdata, String script, HttpServletRequest request) {
+ createLog(athletId, logdata, "DEBUG", script, request);
+ }
+
+ private void createLog(Long athletId, String logdata, String logLevel, String script, HttpServletRequest request) {
+ athletService.findAthletById(athletId).ifPresent(athlet -> {
+ Log log = new Log();
+ log.setLogdata(logdata);
+ log.setLogLevel(logLevel);
+ log.setScript(script);
+ log.setAthlet(athlet);
+
+ if (request != null) {
+ log.setSid(request.getSession().getId());
+ log.setIpAddress(getClientIpAddress(request));
+ log.setUserAgent(request.getHeader("User-Agent"));
+ }
+
+ logRepository.save(log);
+ });
+ }
+
+ private String getClientIpAddress(HttpServletRequest request) {
+ String ip = request.getHeader("X-Forwarded-For");
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+ }
+ if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ return ip;
+ }
+
+ public Long getLogCountSince(Long athletId, LocalDateTime since) {
+ return logRepository.countByAthletIdSince(athletId, since);
+ }
+
+ public List<String> getDistinctScripts(Long athletId) {
+ return logRepository.findDistinctScriptsByAthletId(athletId);
+ }
+
+ public List<String> getDistinctLogLevels(Long athletId) {
+ return logRepository.findDistinctLogLevelsByAthletId(athletId);
+ }
+
+ public Log getLatestLog(Long athletId) {
+ return logRepository.findLatestByAthletId(athletId);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Muscle;
+import com.triathlon_coaching.product.athletik.backend.repo.MuscleRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class MuscleService {
+
+ @Autowired
+ private MuscleRepository muscleRepository;
+
+ public List<Muscle> findAllMuscles() {
+ return muscleRepository.findAll();
+ }
+
+ public Optional<Muscle> findMuscleById(Long id) {
+ return muscleRepository.findById(id);
+ }
+
+ public List<Muscle> findMusclesByGroup(String muscleGroup) {
+ return muscleRepository.findByMuscleGroup(muscleGroup);
+ }
+
+ public List<String> findAllMuscleGroups() {
+ return muscleRepository.findAllMuscleGroups();
+ }
+
+ public List<Muscle> findMusclesByExerciseId(Long exerciseId) {
+ return muscleRepository.findByExercisesId(exerciseId);
+ }
+
+ public List<Muscle> findPrimaryMusclesByExerciseId(Long exerciseId) {
+ // Hier müsste die Logik für isprimary implementiert werden
+ // Vereinfacht geben wir alle Muskeln der Übung zurück
+ return muscleRepository.findByExercisesId(exerciseId);
+ }
+
+ public Muscle saveMuscle(Muscle muscle) {
+ return muscleRepository.save(muscle);
+ }
+
+ public void deleteMuscle(Long id) {
+ muscleRepository.deleteById(id);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Protokoll;
+import com.triathlon_coaching.product.athletik.backend.repo.ProtokollRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class ProtokollService {
+
+ @Autowired
+ private ProtokollRepository protokollRepository;
+
+ @Autowired
+ private EmailService emailService;
+
+ public List<Protokoll> findAllProtokolls() {
+ return protokollRepository.findAll();
+ }
+
+ public Optional<Protokoll> findProtokollById(Long id) {
+ return protokollRepository.findById(id);
+ }
+
+ public List<Protokoll> findByAthletId(Long athletId) {
+ return protokollRepository.findByAthletIdOrderByTrainingDateDesc(athletId);
+ }
+
+ public List<Protokoll> findByAthletIdAndExerciseId(Long athletId, Long exerciseId) {
+ return protokollRepository.findByAthletIdAndExerciseIdOrderByTrainingDateDesc(athletId, exerciseId);
+ }
+
+ public List<Protokoll> findTodaySessionsByAthletId(Long athletId) {
+ return protokollRepository.findTodaySessionsByAthletId(athletId);
+ }
+
+ public List<Protokoll> findByAthletIdAndDateRange(Long athletId, LocalDateTime start, LocalDateTime end) {
+ return protokollRepository.findByAthletIdAndTrainingDateBetween(athletId, start, end);
+ }
+
+ public List<Protokoll> findTestsByAthletId(Long athletId) {
+ return protokollRepository.findByAthletIdAndIsTest(athletId, true);
+ }
+
+ public List<Protokoll> findTrainingsByAthletId(Long athletId) {
+ return protokollRepository.findByAthletIdAndIsTest(athletId, false);
+ }
+
+ public List<Protokoll> findLatestTestsByAthletAndExercise(Long athletId, Long exerciseId) {
+ return protokollRepository.findLatestTestsByAthletAndExercise(athletId, exerciseId);
+ }
+
+ public List<Protokoll> findLatestTestForEachExercise(Long athletId) {
+ return protokollRepository.findLatestTestForEachExercise(athletId);
+ }
+
+ public Integer findMaxSetNumberForToday(Long athletId, Long exerciseId) {
+ Integer maxSet = protokollRepository.findMaxSetNumberForToday(athletId, exerciseId);
+ return maxSet != null ? maxSet : 0;
+ }
+
+ public Protokoll saveProtokoll(Protokoll protokoll) {
+ return protokollRepository.save(protokoll);
+ }
+
+ public void deleteProtokoll(Long id) {
+ protokollRepository.deleteById(id);
+ }
+
+ public Double calculateTotalVolume(Long athletId, LocalDateTime start, LocalDateTime end) {
+ Double totalVolume = protokollRepository.findTotalVolumeByAthletIdAndDateRange(athletId, start, end);
+ return totalVolume != null ? totalVolume : 0.0;
+ }
+
+ public Double calculateDailyVolume(Long athletId) {
+ LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
+ LocalDateTime endOfDay = startOfDay.plusDays(1);
+ return calculateTotalVolume(athletId, startOfDay, endOfDay);
+ }
+
+ public Double calculateWeeklyVolume(Long athletId) {
+ LocalDateTime startOfWeek = LocalDateTime.now().minusDays(7);
+ LocalDateTime now = LocalDateTime.now();
+ return calculateTotalVolume(athletId, startOfWeek, now);
+ }
+
+ public List<Protokoll> findPersonalRecords(Long athletId) {
+ return protokollRepository.findPersonalRecords(athletId);
+ }
+
+ public Page<Protokoll> findByAthletIdAndExerciseIdPaged(Long athletId, Long exerciseId, Pageable pageable) {
+ return protokollRepository.findByAthletIdAndExerciseIdPaged(athletId, exerciseId, pageable);
+ }
+
+ public Long getTrainingCountSince(Long athletId, LocalDateTime since) {
+ return protokollRepository.countByAthletIdAndTrainingDateAfter(athletId, since);
+ }
+
+ public void sendTrainingSummaryEmail(Long athletId) {
+ List<Protokoll> todayTraining = findTodaySessionsByAthletId(athletId);
+ emailService.sendTrainingSummary(athletId, todayTraining);
+ }
+
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Tool;
+import com.triathlon_coaching.product.athletik.backend.repo.ToolRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class ToolService {
+
+ @Autowired
+ private ToolRepository toolRepository;
+
+ public List<Tool> findAllTools() {
+ return toolRepository.findAll();
+ }
+
+ public Optional<Tool> findToolById(Long id) {
+ return toolRepository.findById(id);
+ }
+
+ public List<Tool> findToolsByGymId(Long gymId) {
+ return toolRepository.findByGymsId(gymId);
+ }
+
+ public List<Tool> findByToolnameEnglishContainingIgnoreCase(String name) {
+ return toolRepository.findByToolnameEnglishContainingIgnoreCase(name);
+ }
+
+ public List<Tool> findByToolnameGermanContainingIgnoreCase(String name) {
+ return toolRepository.findByToolnameGermanContainingIgnoreCase(name);
+ }
+
+ public Tool saveTool(Tool tool) {
+ return toolRepository.save(tool);
+ }
+
+ public void deleteTool(Long id) {
+ toolRepository.deleteById(id);
+ }
+
+ public boolean existsById(Long id) {
+ return toolRepository.existsById(id);
+ }
+}
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.service;
+
+import com.triathlon_coaching.product.athletik.backend.model.Training;
+import com.triathlon_coaching.product.athletik.backend.repo.TrainingRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class TrainingService {
+
+ @Autowired
+ private TrainingRepository trainingRepository;
+
+ public List<Training> findAllTrainings() {
+ return trainingRepository.findAll();
+ }
+
+ public Optional<Training> findTrainingById(Long id) {
+ return trainingRepository.findById(id);
+ }
+
+ public List<Training> findTrainingsByAthletId(Long athletId) {
+ return trainingRepository.findByAthletIdOrderByCreatedDesc(athletId);
+ }
+
+ public List<Training> findActiveTrainingsByAthletId(Long athletId) {
+ return trainingRepository.findByAthletIdAndIsActiveTrue(athletId);
+ }
+
+ public List<Training> findCurrentlyValidTrainingsByAthletId(Long athletId) {
+ return trainingRepository.findActiveByAthletId(athletId, LocalDateTime.now());
+ }
+
+ public List<Training> findTrainingsByExerciseId(Long exerciseId) {
+ return trainingRepository.findByExerciseId(exerciseId);
+ }
+
+ public List<Training> findTrainingsByGoalId(Long goalId) {
+ return trainingRepository.findByGoalId(goalId);
+ }
+
+ public List<Training> findTrainingsByAthletIdAndExerciseId(Long athletId, Long exerciseId) {
+ return trainingRepository.findByAthletIdAndExerciseId(athletId, exerciseId);
+ }
+
+
+ public void deleteTraining(Long id) {
+ trainingRepository.deleteById(id);
+ }
+
+ public void deactivateTraining(Long id) {
+ trainingRepository.findById(id).ifPresent(training -> {
+ training.setIsActive(false);
+ trainingRepository.save(training);
+ });
+ }
+
+ public void activateTraining(Long id) {
+ trainingRepository.findById(id).ifPresent(training -> {
+ training.setIsActive(true);
+ trainingRepository.save(training);
+ });
+ }
+
+ public boolean trainingExists(Long athletId, Long exerciseId, Integer repetitionsOfSet,
+ Integer repetitions, Double factorOfFmax) {
+ return trainingRepository
+ .findByAthletIdAndExerciseIdAndRepetitionsOfSetAndRepetitionsAndFactorOfFmax(
+ athletId, exerciseId, repetitionsOfSet, repetitions, factorOfFmax)
+ .isPresent();
+ }
+
+ public List<Training> findTrainingsCreatedBetween(LocalDateTime start, LocalDateTime end) {
+ return trainingRepository.findByCreatedBetween(start, end);
+ }
+
+ public List<Training> findValidTrainingsAt(LocalDateTime date) {
+ return trainingRepository.findValidAt(date);
+ }
+
+ public void sendTrainingSummaryEmail(Long id) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public double calculateOneRepMax(double weight, int repetitions) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.backend.util;
+
+public class AthletikConstants {
+
+ public static final String NOREPLYEMAIL = "noreply@triathlon-coaching.com";
+
+}
--- /dev/null
+
+spring:
+ datasource:
+ url: jdbc:postgresql://localhost:5432/sport
+# username: laktatnebel
+# password: njThR3G&c9?B7ZpQ
+ username: oleb
+ password: wpj_9+L6ukX+SN2-
+ driver-class-name: org.postgresql.Driver
+ jpa:
+ hibernate:
+ ddl-auto: validate
+ properties:
+ hibernate:
+ dialect: org.hibernate.dialect.PostgreSQLDialect
+ default_schema: athletik
+ show_sql: true
+ format_sql: true
+ mail:
+ host: localhost
+ port: 25
+ protocol: smtp
+ properties:
+ mail:
+ smtp:
+ auth: false
+ starttls:
+ enable: false
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 10MB
+ thymeleaf:
+ cache: false
+ prefix: classpath:/templates/
+ suffix: .html
+
+server:
+ port: 8080
+ servlet:
+ context-path: /athletik
+
+app:
+ base-url: http://localhost:8080
+
+logging:
+ level:
+ com.triathlon_coaching.product.athletik: DEBUG
+
+# Sicherheitskonfiguration
+security:
+ password:
+ encoder: sha512
+
+
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head>
+ <meta charset="UTF-8">
+ <title>Training Zusammenfassung</title>
+ <style>
+ body { font-family: Arial, sans-serif; line-height: 1.6; }
+ .header { background-color: #f8f9fa; padding: 20px; text-align: center; }
+ .content { padding: 20px; }
+ .exercise-table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
+ .exercise-table th, .exercise-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
+ .exercise-table th { background-color: #f2f2f2; }
+ .summary { background-color: #e9ecef; padding: 15px; border-radius: 5px; }
+ </style>
+</head>
+<body>
+ <div class="header">
+ <h1>Dein Training vom <span th:text="${#temporals.format(trainingDate, 'dd.MM.yyyy')}"></span></h1>
+ </div>
+
+ <div class="content">
+ <p>Aloha <span th:text="${athlet.fullname}"></span>,</p>
+
+ <p>hier ist Deine Trainings-Zusammenfassung vom <span th:text="${#temporals.format(trainingDate, 'dd.MM.yyyy')}"></span>:</p>
+
+ <table class="exercise-table">
+ <thead>
+ <tr>
+ <th>Übung</th>
+ <th>Sätze</th>
+ <th>Wiederholungen</th>
+ <th>Gewicht (kg)</th>
+ <th>Volumen (kg)</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="exercise : ${trainingData}">
+ <td th:text="${exercise.exercise.nameGerman}">Übungsname</td>
+ <td th:text="${exercise.numberOfSet}">Sätze</td>
+ <td th:text="${exercise.repetitions}">Wiederholungen</td>
+ <td th:text="${#numbers.formatDecimal(exercise.weight, 1, 2)}">Gewicht</td>
+ <td th:text="${#numbers.formatDecimal(exercise.weight * exercise.repetitions, 1, 2)}">Volumen</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div class="summary">
+ <h3>Zusammenfassung</h3>
+ <p><strong>Gesamtvolumen:</strong> <span th:text="${#numbers.formatDecimal(totalVolume, 1, 2)}"></span> kg</p>
+ <p><strong>Anzahl Sätze:</strong> <span th:text="${totalSets}"></span></p>
+ </div>
+
+ <p>Weiter so! Bleib dran für optimale Trainingserfolge.</p>
+
+ <p>Mit sportlichen Grüßen<br>triathlon-coaching.com</p>
+ </div>
+</body>
+</html>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
- <groupId>com.triathlon-coaching.product</groupId>
- <artifactId>athletik.athletik-web</artifactId>
- <version>0.0.1-SNAPSHOT</version>
+ <artifactId>athletik.web</artifactId>
<packaging>pom</packaging>
- <name>${product.artifactId}</name>
+ <name>${project.artifactId}</name>
<description>Athletik Training WebUI</description>
<parent>
- <groupId>de.laktatnebel.maven</groupId>
- <artifactId>laktatnebelscript</artifactId>
- <version>2.1.9</version>
+ <groupId>com.triathlon-coaching.product</groupId>
+ <artifactId>athletik</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
</parent>
</project>
--- /dev/null
+<?php
+
+
+define ("HOST", "localhost");
+define ("SCHEMA", "athletik");
+define ("DB", "sport");
+//define ("USER", "laktatnebel");
+define ("USER", "oleb");
+//define ("PASS", "njThR3G&c9?B7ZpQ");
+define ("PASS", "wpj_9+L6ukX+SN2-");
+
+
+date_default_timezone_set('Europe/Berlin');
+
+?>
+++ /dev/null
-<?php
-
-
-define ("HOST", "localhost");
-define ("SCHEMA", "athletik");
-define ("DB", "sport");
-//define ("USER", "laktatnebel");
-define ("USER", "oleb");
-//define ("PASS", "njThR3G&c9?B7ZpQ");
-define ("PASS", "wpj_9+L6ukX+SN2-");
-
-
-date_default_timezone_set('Europe/Berlin');
-
-?>
--- /dev/null
+/**
+ *
+ */
+
+document.addEventListener('DOMContentLoaded', function() {
+ const forms = document.querySelectorAll('.ajax-form');
+
+ forms.forEach(form => {
+ form.addEventListener('submit', async function(e) {
+ e.preventDefault();
+
+ const formData = new FormData(this);
+ const submitButton = this.querySelector('button[type="submit"]');
+ // Loading-State
+ submitButton.disabled = true;
+ submitButton.textContent = 'saving ...';
+
+ try {
+ const response = await fetch('save-data.php', {
+ method: 'POST',
+ body: formData,
+ credentials: 'include', // Cookies mitsenden
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest'
+ }
+ });
+
+ const result = await response.json();
+
+ if (result.success) {
+ showMessage('Data saved successfully!', 'success');
+ this.reset(); // Formular zurücksetzen
+ } else {
+ showMessage('Error: ' + result.message, 'error');
+ }
+
+ } catch (error) {
+ showMessage('Network error: ' + error.message, 'error');
+ } finally {
+ // Button zurücksetzen
+ submitButton.disabled = false;
+ submitButton.textContent = 'Save';
+ }
+ });
+ });
+
+ function showMessage(text, type) {
+ const messageDiv = document.getElementById('responseMessage');
+ messageDiv.textContent = text;
+ messageDiv.className = type;
+ messageDiv.style.display = 'block';
+
+ // Nachricht nach 5 Sekunden ausblenden
+ setTimeout(() => {
+ messageDiv.style.display = 'none';
+ }, 5000);
+ }
+});
\ No newline at end of file
--- /dev/null
+<?php
+
+require ("db/database_functions_pgsql.php");
+
+require ("db/database_functions_select.php");
+
+
+$selectFromViewMusclegroups = "SELECT * FROM ".SCHEMA.".view_musclegroups;";
+
+$selectWeightsFromViewTools = "SELECT * FROM ".SCHEMA.".view_toolweights WHERE id=%d;";
+
+$selectFromViewUsers = "SELECT name_user FROM ".SCHEMA.".view_users;";
+
+$selectUserNameFromViewUsers = "SELECT name_user FROM ".SCHEMA.".view_users WHERE id=%d;";
+
+$selectMucleGroupFromViewMuscles = "SELECT * FROM ".SCHEMA.".view_muscles WHERE fk_musclegroup=%d;";
+
+$selectMucleFromViewAllExercises = "SELECT * FROM ".SCHEMA.".view_allexercises WHERE id=%d;";
+
+$selectUserExerciseFromViewProtokoll = "SELECT * FROM ".SCHEMA.".view_protokollsetsoftoday WHERE fk_user=%d AND fk_exercise=%d;";
+
+//$selectUserExerciseFromViewProtokoll = "SELECT * FROM ".SCHEMA.".view_protokoll WHERE fk_user=%d AND fk_exercise=$d;";
+
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+
+function generateInsertSchema($schema, $table, $values) {
+ $insert_str = "INSERT INTO ".$schema.".".$table." VALUES (";
+
+ //print_r($values);
+ $anzValues = count($values);
+ for ($i = 0 ; $i < $anzValues; $i++) {
+ $insert_str .= $values[$i];
+ if ($i < ($anzValues-1)) {
+ $insert_str .= ", ";
+ }
+ }
+
+ $insert_str .= ");";
+ //echo debugPrint($insert_str);
+ return $insert_str;
+}
+
+function generateInsertSchemaReturn($schema, $table, $values, $return) {
+ $insert_str = "INSERT INTO ".$schema.".".$table." VALUES (";
+
+ //print_r($values);
+ $anzValues = count($values);
+ for ($i = 0 ; $i < $anzValues; $i++) {
+ $insert_str .= $values[$i];
+ if ($i < ($anzValues-1)) {
+ $insert_str .= ", ";
+ }
+ }
+
+ $insert_str .= ") ".$return.";";
+ //echo debugPrint($insert_str);
+ return $insert_str;
+}
+
+function generateInsert($table, $values) {
+ $insert_str = "INSERT INTO ".$table." VALUES (";
+
+ //print_r($values);
+ $anzValues = count($values);
+ for ($i = 0 ; $i < $anzValues; $i++) {
+ $insert_str .= $values[$i];
+ if ($i < $anzValues-1) {
+ $insert_str .= ", ";
+ }
+ }
+
+ $insert_str .= ");";
+ //echo debugPrint($insert_str);
+ return $insert_str;
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Mit PostgresSQL verbinden */
+function getDBConnection() {
+
+ $str_connection = "host=".HOST." port=5432 dbname=".DB." user=".USER." password=".PASS." ";
+ //echo $str_connection;
+ // mit DB verbinden
+ //$connect_dbms_handle = new PDO("pgsql:dbname=".DB, USER, PASS);
+ $connect_dbms_handle = @pg_connect($str_connection) or die('Verbindungsaufbau fehlgeschlagen: ' . pg_last_error());
+
+ if ($connect_dbms_handle) {
+ return $connect_dbms_handle;
+ } else {
+ echo "Datenbankabfrage fehlgeschlagen!";
+ echo pg_last_error($connect_dbms_handle);
+ return false;
+ }
+}
+
+/**
+ * PostgresSQL-Verbindung schliessen */
+function closeDBConnection($ref_connection) {
+ @pg_close($ref_connection) or die('Verbindungsclose fehlgeschlagen: ');
+ //echo pg_last_error($ref_connection);
+}
+
+
+// SQL an DB absetzen
+// Parameter: Tablle, Feld(er), Wert(e)
+// Rückgabewert: boolean
+function getBooleanData ($dbms_connection, $db_query) {
+ // Variablen
+ $return_bool_value = false ;
+
+ // DB Abfage starten
+ //echo $db_query;
+ $res_sql_result = pg_query ($dbms_connection, $db_query);
+ // Gültigkeit der DB Abfage testen
+ if ($res_sql_result) {
+ //echo "<li>".$res_sql_result;
+ $return_bool_value = true;
+ } else {
+ return "Datenbankabfrage fehlgeschlagen!";
+ }
+
+ return $return_bool_value;
+}
+
+
+// SQL an DB absetzen
+// Parameter: Tablle, Feld(er), Wert(e)
+// Rückgabewert: Array
+function getData ($dbms_connection, $db_query) {
+ $return_arr_data = array(); // Rückgabewert als Array
+ //echo "\n<p> SQL:<br>".$ref_str_db_query."</p>";
+
+ // DB Abfage starten
+ //echo $db_query;
+ $res_sql_result = pg_query ($dbms_connection, $db_query);
+ // Gültigkeit der DB Abfage testen
+ if ($res_sql_result) {
+ //echo "<p>".$res_sql_result."</p>";
+ while ($arr_sql_data = pg_fetch_row($res_sql_result)) {
+ //echo debugPrint($arr_sql_data);
+ array_push ($return_arr_data, $arr_sql_data);
+ }
+ //var_dump( $return_arr_data);
+ } else {
+ return "Datenbankabfrage fehlgeschlagen!";
+ }
+
+ return $return_arr_data;
+}
+
+
+// SQL an DB absetzen
+// Parameter: Tablle, Feld(er), Wert(e)
+// Rückgabewert: Array
+function getDataReturnID ($dbms_connection, $db_query) {
+ $return_arr_data = array(); // Rückgabewert als Array
+ //echo "\n<p> SQL:<br>".$ref_str_db_query."</p>";
+
+ // DB Abfage starten
+ //echo $db_query;
+ $res_sql_result = pg_query ($dbms_connection, $db_query);
+ // Gültigkeit der DB Abfage testen
+ if ($res_sql_result) {
+ //echo "<p>".$res_sql_result."</p>";
+ while ($arr_sql_data = pg_fetch_row($res_sql_result)) {
+ //echo debugPrint($arr_sql_data);
+ array_push ($return_arr_data, $arr_sql_data);
+ }
+ //var_dump( $return_arr_data);
+ } else {
+ return "Datenbankabfrage fehlgeschlagen!";
+ }
+
+ return $return_arr_data[0][0];
+}
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+function generateSelect ($selectedFields, $table) {
+ $select_str = "SELECT ";
+
+ if (is_array($selectedFields)) {
+ //print_r($selectedFields);
+ $anzFields = count($selectedFields);
+ for ($i = 0 ; $i < $anzFields; $i++) {
+ $select_str .= $selectedFields[$i];
+ if ($i < $anzFields-1) {
+ $select_str .= ", ";
+ }
+ }
+ } else {
+ $select_str .= "*";
+ }
+
+ $select_str .= " FROM ".$table;
+
+ $select_str .= ";";
+
+ //echo $select_str;
+ return $select_str;
+}
+
+
+function generateSelectWhereOrder ($selectedFields, $table, $whereClause, $orderClause) {
+ $select_str = "SELECT ";
+
+ if (is_array($selectedFields)) {
+ //print_r($selectedFields);
+ $anzFields = count($selectedFields);
+ for ($i = 0 ; $i < $anzFields; $i++) {
+ $select_str .= $selectedFields[$i];
+ if ($i < $anzFields-1) {
+ $select_str .= ", ";
+ }
+ }
+ } else {
+ $select_str .= "*";
+ }
+
+ $select_str .= " FROM ".$table;
+
+ if ($whereClause != null) {
+ $select_str .= " WHERE ";
+
+ //print_r($whereClause);
+ $anzWheres = count($whereClause);
+ for ($i = 0 ; $i < $anzWheres; $i++) {
+ $select_str .= $whereClause[$i];
+ if ($i < $anzWheres-1) {
+ $select_str .= " AND ";
+ }
+ }
+ }
+
+ if ($orderClause != null) {
+ $select_str .= " ORDER BY ";
+
+ //print_r($orderClause);
+ $anzOrders = count($orderClause);
+ for ($i = 0 ; $i < $anzOrders; $i++) {
+ $select_str .= $orderClause[$i];
+ if ($i < $anzOrders-1) {
+ $select_str .= ", ";
+ }
+ }
+ }
+
+ $select_str .= ";";
+
+ //echo $select_str;
+ return $select_str;
+}
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/** $ref_button_name Name des <button>
+ * $ref_value_button Daten; null möglich
+ * $ref_html_button HTML zwischen <button></button>; null möglich
+ * $ref_id Id des <button>
+ * $ref_class Class des <button>; null möglich
+ * $ref_tabindex Tabindex in der <form>
+
+ * $ref_type <button>-type (submit, reset, button)
+ * $ref_javascript Javascript; null möglich
+
+ * $ref_labeltitle <label>-Text; null möglich
+ * $ref_p_flag true, wenn alles in <p> soll
+ * $ref_newline_flag true, wenn <label> ueber <button> stehen soll
+ * $ref_intend Anz. Tabs einrücken
+ * */
+function makeButton($ref_button_name, $ref_value_button, $ref_html_button, $ref_id, $ref_class, $ref_tabindex, $ref_type, $ref_javascript, $ref_labeltitle, $ref_p_flag, $ref_newline_flag, $ref_intend) {
+
+ $intend = make_intend_str($ref_intend);
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "<p>\n";
+ }
+
+
+ if ($ref_labeltitle != null) {
+ echo $intend."\t";
+ echo "<label for=\"".$ref_button_name."\">".$ref_labeltitle."</label>";
+ if ($ref_newline_flag) {
+ echo "<br />";
+ }
+ echo "\n";
+ }
+
+ $str_id = $ref_id == null ? " " : " id=\"".$ref_id."\" ";
+ $str_class = $ref_class == null ? " " : " class=\"".$ref_class."\" ";
+ $str_tabindex = $ref_tabindex == null ? " " : " tabindex=\"".$ref_tabindex."\" ";
+ $str_javascript = $ref_javascript == null ? " " : " onchange=\"".$ref_javascript."\" ";
+
+ echo $intend."\t";
+
+ echo "<button ".$str_id.$str_class.$str_tabindex."name=\"".$ref_button_name."\" type=\"".$ref_type."\" ";
+ if ($ref_value_button != null) {
+ echo " value=\"".$ref_value_button."\"";
+ }
+ echo "/>\n";
+
+ echo $intend."\t\t";
+
+ echo $ref_html_button."\n";
+
+ echo $intend."\t";
+ echo "</button>\n";
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "</p>\n";
+ }
+}
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/** $ref_name Name des <input>
+ * $ref_value_input Daten; null möglich
+ * $ref_id Id des <input>
+ * $ref_class Class des <input>; null möglich
+ * $ref_tabindex Tabindex in der <form>
+
+ * $ref_type <input>-type (hidden, password, text ...)
+ * $ref_size Größe des Feldes
+ * $ref_maxlength Max. Größe der Eingabe
+ * $ref_javascript Javascript; null möglich
+
+ * $ref_mandantory Pflichtfeldmarkierung; null möglich
+ * $ref_labeltitle <label>-Text; null möglich
+ * $ref_p_flag true, wenn alles in <p> soll
+ * $ref_newline_flag true, wenn <label> ueber <input> stehen soll
+ * $ref_intend Anz. Tabs einrücken
+ * */
+function makeInput($ref_name, $ref_value_input, $ref_id, $ref_class, $ref_tabindex, $ref_type, $ref_size, $ref_maxlength, $ref_javascript, $ref_mandantory, $ref_labeltitle, $ref_p_flag, $ref_newline_flag, $ref_intend) {
+
+ $intend = make_intend_str($ref_intend);
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "<p>\n";
+ }
+
+ echo $intend."\t";
+
+ if ($ref_mandantory) {
+ echo "* ";
+ }
+
+ if ($ref_labeltitle != null) {
+ echo "<label for=\"".$ref_name."\">".$ref_labeltitle."</label>";
+ if ($ref_newline_flag) {
+ echo "<br />";
+ }
+ echo "\n";
+ }
+
+ $str_id = $ref_id == null ? " " : " id=\"".$ref_id."\" ";
+ $str_class = $ref_class == null ? " " : " class=\"".$ref_class."\" ";
+ $str_tabindex = $ref_tabindex == null ? " " : " tabindex=\"".$ref_tabindex."\" ";
+ $str_javascript = $ref_javascript == null ? " " : " onchange=\"".$ref_javascript."\" ";
+
+ echo $intend."\t";
+
+ echo "<input ".$str_id.$str_class.$str_tabindex.$str_javascript."name=\"".$ref_name."\" type=\"".$ref_type."\" size=\"".$ref_size."\" maxlength=\"".$ref_maxlength."\" ";
+
+ if (isset($_POST[$ref_name]) && strlen($_POST[$ref_name]) > 0) {
+ echo " value=\"".$_POST[$ref_name]."\"";
+ } else if ($ref_value_input != null ){
+ echo " value=\"".$ref_value_input."\"";
+ }
+ echo "/>\n";
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "</p>\n";
+ }
+}
+
+function make_multi_input($ref_name, $ref_type, $ref_size, $ref_maxlength, $ref_tabindex, $ref_id, $ref_labeltitle, $ref_class, $ref_classerrorextension, $ref_error_label, $ref_mandantory, $ref_intend, $ref_p_flag) {
+
+ if ($ref_p_flag) {
+ echo make_intend($ref_intend)."<p>\n";
+ }
+ echo make_intend($ref_intend)."\t";
+ if ($ref_mandantory) {
+ echo "*";
+ }
+ echo "<label for=\"".$ref_name[0]."\">".$ref_labeltitle."</label><br />\n";
+
+ for ($i=0; $i<count($ref_name); $i++) {
+ echo make_intend($ref_intend)."\t<input class=\"".$ref_class[$i];
+ if ($ref_error_label == $ref_name[$i]) {
+ echo $ref_classerrorextension;
+ }
+ echo "\" type=\"".$ref_type[$i]."\" name=\"".$ref_name[$i]."\" size=\"".$ref_size[$i]."\" maxlength=\"".$ref_maxlength[$i]."\" tabindex=\"".$ref_tabindex[$i]."\" id=\"".$ref_id[$i]."\" ";
+ if (isset($_POST[$ref_name[$i]]) && strlen($_POST[$ref_name[$i]]) > 0) {
+ echo " value=\"".$_POST[$ref_name[$i]]."\"";
+ }
+ echo "/>\n";
+ }
+ if ($ref_p_flag) {
+ echo make_intend($ref_intend)."</p>\n";
+ }
+}
+
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/** $ref_select_name Name des <select>
+ * $ref_value_array Daten-Array; null möglich
+ * $ref_id Id des <select>
+ * $ref_class Class des <select>; null möglich
+ * $ref_tabindex Tabindex in der <form>
+
+ * $ref_start Start-Index statt Datenarray falls Datenarray null
+ * $ref_end End-Index statt Datenarray falls Datenarray null
+ * $ref_int_preselect Index vorausgewähltes Element; default -1
+ * $ref_multiple Mehrfachauswahl <select multiple>; default false
+ * $ref_int_size Für mehrzeilige Mehrfachauswahl > 1;
+ * $ref_javascript Javascript; null möglich
+
+ * $ref_mandantory Pflichtfeldmarkierung; null möglich
+ * $ref_labeltitle <label>-Text; null möglich
+ * $ref_p_flag true, wenn alles in <p> soll
+ * $ref_newline_flag true, wenn <label> ueber <select> stehen soll
+ * $ref_intend Anz. Tabs einrücken
+ * */
+function makeSelect($ref_select_name, $ref_value_array, $ref_id, $ref_class, $ref_tabindex, $ref_start, $ref_end, $ref_int_preselect, $ref_multiple, $ref_int_size, $ref_javascript, $ref_mandantory, $ref_labeltitle, $ref_p_flag, $ref_newline_flag, $ref_intend) {
+
+ $intend = make_intend_str($ref_intend);
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "<p>\n";
+ }
+
+ echo $intend."\t";
+
+ if ($ref_mandantory) {
+ echo "* ";
+ }
+
+ if ($ref_labeltitle != null) {
+ echo "<label for=\"".$ref_select_name."\">".$ref_labeltitle."</label>";
+ if ($ref_newline_flag) {
+ echo "<br />";
+ }
+ echo "\n";
+ }
+
+ $str_id = $ref_id == null ? " " : " id=\"".$ref_id."\" ";
+ $str_class = $ref_class == null ? " " : " class=\"".$ref_class."\" ";
+ $str_tabindex = $ref_tabindex == null ? " " : " tabindex=\"".$ref_tabindex."\" ";
+ $str_javascript = $ref_javascript == null ? " " : " onchange=\"".$ref_javascript."\" ";
+
+ echo $intend."\t";
+
+ echo "<select ".$str_id.$str_class.$str_tabindex.$str_javascript."name=\"".$ref_select_name."\" size=\"".$ref_int_size."\" "." ";
+ if ($ref_multiple == true) {
+ echo "multiple=\"multiple\" ";
+ }
+ echo ">\n";
+
+ if ($ref_value_array != null) {
+
+ // Flag: True, falls das Datenarray multidimensional ist. Dann wird das Attribut value in <option> mit dem wert aus dem Unterarray gefüllt, ansonsten wird der Schleifenindex verwendet.
+ $multiDimensionalArrayFlag = is_array($ref_value_array[0]);
+
+ for ($i=0; $i<count($ref_value_array); $i++) {
+ echo $intend;
+ echo "\t\t<option value=\"".($multiDimensionalArrayFlag ? $ref_value_array[$i][0] : $i)."\"";
+ if (($multiDimensionalArrayFlag ? $ref_value_array[$i][0] : ($i+1)) == $ref_int_preselect) { // $i-1 deshalb, weil das Array mit dem 0-ten Element beginnt, der Value aber mit 1 anfängt
+ echo " selected";
+ }
+ echo ">".($multiDimensionalArrayFlag ? $ref_value_array[$i][1] : $ref_value_array[$i])."</option>\n";
+ }
+ } else {
+ for ($i=$ref_start; $i<(1+$ref_end); $i++) {
+ echo $intend;
+ echo "\t\t<option value=\"".$i."\"";
+ if ($i == $ref_int_preselect) {
+ echo " selected";
+ }
+ echo ">".$i."</option>\n";
+ }
+ }
+
+ echo $intend."\t";
+ echo "</select>\n";
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "</p>\n";
+ }
+}
+
+
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+require ("gui/gui_functions_select.php");
+require ("gui/gui_functions_input.php");
+require ("gui/gui_functions_button.php");
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+function sessionHandling($scriptname, $dbms_connection) {
+ session_start();
+
+ $sid = session_id();
+
+ if (isset($_POST['username']) && isset($_POST['pass'])) {
+ // eigentliche Prüfung
+ if (checkLogin($dbms_connection, $_POST['username'],$_POST['pass']) == 1) {
+ $_SESSION['sess_user'] = $_POST['username'];
+ } else {
+ $_SESSION['sess_user'] = "guest";
+ }
+ } else if (!isset($_SESSION['sess_user']) || $_POST['logout'] == "Abmelden") {
+ $_SESSION['sess_user'] = "guest";
+ }
+
+ $session_user = "0";
+
+ if ($_SESSION['sess_user'] == "guest") {
+ $session_user = "0";
+ } else {
+ $session_user = "(SELECT id FROM users WHERE username='".$_SESSION['sess_user']."')";
+ }
+
+ getData($dbms_connection, generateInsert(SCHEMA, "session", array("'".$sid."'", $session_user, "now()", "'".$page."'")));
+
+
+
+}
+
+function checkLogin($dbms_connection, $ref_user, $ref_pass) {
+
+
+ $str = "SELECT count(*) FROM users WHERE username='".$ref_user."' AND pass='".$ref_pass."'";
+
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+require ("session/session_functions.php");
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+function debugPrint($param) {
+ echo "<p>";
+ if (is_array($param)) {
+ if ($asList) {
+ debugPrintAsList($param);
+ } else {
+ echo "_";
+ foreach ($param as $p) {
+ echo $p."_";
+ }
+ }
+ } else {
+ echo $param;
+ }
+ echo "</p>\n";
+}
+
+function debugPrintAsList($param) {
+ echo "<ol>\n";
+ foreach ($param as $p) {
+ echo "<li>".$p."_</li>\n";
+ }
+ echo "</ol>\n";
+}
+
+function coordinates ($ref_longitude, $ref_latitude) {
+ $return_geo = array("","");
+
+ $return_geo[0] = $ref_longitude[0] + $ref_longitude[1]/60 + $ref_longitude[2]/3600;
+ $return_geo[1] = $ref_latitude[0] + $ref_latitude[1]/60 + $ref_latitude[2]/3600;
+
+ return $return_geo;
+}
+
+function find_pos_in_array($ref_array, $ref_value) {
+ $pos = -1;
+
+ for ($i=0; $i<count($ref_array); $i++) {
+ if ($ref_array[$i] == $ref_value) {
+ $pos = $i;
+ }
+ }
+
+ return $pos;
+}
+
+function make_intend($ref_count) {
+ for ($i=0; $i<$ref_count; $i++) {
+ echo "\t";
+ }
+}
+
+function make_intend_str($ref_count) {
+ $intend = "";
+ for ($i=0; $i<$ref_count; $i++) {
+ $intend .= "\t";
+ }
+ return $intend;
+}
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+require ("util/util_functions.php");
+
+
+function getArrayOfWeights($connect_dbms_handle, $selectWeightsFromViewTools, $ref_tool) {
+
+ $dataWeights = getData($connect_dbms_handle, sprintf($selectWeightsFromViewTools, $ref_tool));
+ //print_r($dataWeights);
+ $weightsArray = array();
+
+ for ($weight = $dataWeights[0][1]; $weight <= $dataWeights[0][3]; $weight += $dataWeights[0][2]) {
+ //echo $weight;
+ array_push($weightsArray, array ($weight, $weight." kg"));
+ }
+
+ //print_r($weightsArray);
+
+ return $weightsArray;
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php require_once '../athletik_glob_vars.php'; ?>
+<?php require_once 'lib/database_functions.php'; ?>
+<?php require_once 'lib/session_functions.php'; ?>
+<?php
+session_start();
+
+header('Content-Type: application/json');
+
+header('Access-Control-Allow-Origin: https://www.triathlon-coaching.com');
+header('Access-Control-Allow-Credentials: true');
+header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
+header('Access-Control-Allow-Headers: Content-Type');
+// Session Cookie Einstellungen (in deiner Haupt-Login-Datei)
+session_set_cookie_params([
+'lifetime' => 3600,
+'path' => '/',
+'domain' => '.triathlon-coaching.com',
+'secure' => true,
+'httponly' => true,
+'samesite' => 'Lax'
+]);
+
+error_log ("hallo", 0);
+
+// AJAX Request check
+function is_ajax_request() {
+ return isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
+ strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
+}
+
+if (!is_ajax_request() || $_SERVER['REQUEST_METHOD'] !== 'POST') {
+ http_response_code(403);
+ echo json_encode(['success' => false, 'message' => 'Forbidden']);
+ exit;
+}
+
+error_log ("hallo2", 0);
+
+// Login checsessionk
+if (!isset($_SESSION['user_id']) || !isset($_SESSION['logged_in'])) {
+ echo json_encode(['success' => false, 'message' => 'Please login again']);
+ exit;
+}
+
+$current_user = $_SESSION['user_id'];
+
+error_log ("hallo".$current_user, 0);
+
+
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ http_response_code(405);
+ echo json_encode(['success' => false, 'message' => 'Method not allowed']);
+ exit;
+}
+
+foreach (array_keys($_POST) as $post) {
+ //echo $post." => ".$_POST[$post]."\n";
+ $change = explode ("_", $post);
+ $exercise += $change[count($change)-1];
+
+ //echo $exercise;
+}
+
+$exercise = $exercise / count(array_keys($_POST));
+
+$update_arr = array();
+array_push($update_arr, $current_user);
+array_push($update_arr, $exercise);
+array_push($update_arr, "now()");
+array_push($update_arr, $_POST['set_'.$exercise]);
+array_push($update_arr, $_POST['reps_'.$exercise]);
+array_push($update_arr, $_POST['weight_'.$exercise]);
+
+$connect_dbms_handle = getDBConnection();
+
+$sqlInsert = generateInsertSchema(SCHEMA, "protokoll", $update_arr);
+$sqlInsert_result = getBooleanData($connect_dbms_handle, $sqlInsert);
+//echo $sqlinsert_result;
+
+$sqllog = generateInsertSchema("ticket", "dt_sqllog", array("DEFAULT", "now()", "'".addslashes(str_replace("'", "\"", $sqlupdate))."'", $current_user, "'".uniqid()."'", "'".$page."'"));
+$sqllog_result = getBooleanData($connect_dbms_handle, $sqllog);
+
+
+?>
\ No newline at end of file
--- /dev/null
+@charset "UTF-8";
+
+BODY {
+ font-family: sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
+ 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
+ 'Helvetica Neue';
+ line-height: 1.5;
+ font-size: 1rem;
+ margin: 0;
+}
+
+HEADER, SECTION {
+ margin-left: 15em;
+ padding: 0 0 0 1rem;
+}
+
+NAV {
+ background: #f0f0f0;
+ height: 100%;
+ position: fixed;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ width: 15em;
+ overflow-x: hidden;
+}
+
+OL {
+ margin: 1.25em 0;
+}
+
+UL.navbar {
+ list-style-type: none;
+}
+
+.navbar li a {
+ text-decoration: none;
+ color: #333;
+ padding: 0.5rem 1rem;
+ display: block;
+ font-size: 2em;
+}
+
+.navbar li a:active, .navbar li a:hover {
+ background: #ddd;
+ transition: background 0.2s ease;
+}
+
+P.muscle {
+ border-top: 0.2em solid black;
+ padding: 0.25em 0 0 0;
+}
+
+P.start {
+ font-size: 1.25rem;
+ padding: 0 0 1.5em 0;
+}
+
+LI, P {
+ font-size: 1rem;
+}
+
+A {
+ text-decoration: none;
+}
+
+.musclename {
+ font-weight: 600;
+ color: #933;
+ background-color: #ddd;
+ padding: 0.5em;
+}
+
+.important {
+ font-weight: 600;
+ color: red;
+}
+
+.fa {
+ font-size: 1.5em;
+}
+
+H1 {
+ text-align: center;
+ font-size: 4.5em;
+}
+
+H2 {
+ text-align: center;
+ font-size: 3em;
+ text-decoration: underline overline;
+}
+
+.totop {
+ background-color: #666;
+ color: #ccc;
+ padding: 0.5em 2em;
+}
+
+.totop A {
+ color: #ccc;
+ font-size: 0.75em;
+}
+
+.hidden { display: none; }
+.success {
+ background: #d4edda;
+ color: #155724;
+ padding: 10px;
+ margin: 10px 0;
+ border: 1px solid #c3e6cb;
+}
+.error {
+ background: #f8d7da;
+ color: #721c24;
+ padding: 10px;
+ margin: 10px 0;
+ border: 1px solid #f5c6cb;
+}
+
+button:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
\ No newline at end of file
--- /dev/null
+<?php
+putenv("PGGSSENCMODE=disable");
+putenv("LC_ALL=C");
+?>
+<?php require_once '../athletik_glob_vars.php'; ?>
+<?php require_once 'lib/database_functions.php'; ?>
+<?php require_once 'lib/session_functions.php'; ?>
+<?php require_once 'lib/gui_functions.php'; ?>
+<?php require_once 'lib/util_functions.php'; ?>
+<?php
+$page = 'index.php';
+
+$j=0;
+
+$connect_dbms_handle = getDBConnection();
+
+$current_user=1;
+$lang=2;
+
+$dataUsername = getData($connect_dbms_handle, sprintf($selectUserNameFromViewUsers, $current_user));
+
+
+
+
+?>
+<!DOCTYPE html>
+<html lang="de">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="stylesheet"
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+<title>Athletiktraining <?php echo $dataUsername[0][0]; ?></title>
+<link rel="stylesheet" href="stylesheet/athletik.css" type="text/css" media="screen, projection" />
+
+</head>
+<body>
+
+ <header>
+ <h1 id="nav"><span class="eng">Exercises</span> / <span class="deu">Übungen</span></h1>
+ </header>
+
+ <nav>
+ <img src="img/Reichstag_Berlin.jpg" alt="deutsch" height="50px"><img src="img/Big_Ben_London_closeup.jpg" alt="english" height="50px">
+ <ul class="navbar">
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#general">Allgemeine Hinweise</a></li>
+ <li><a href="#combinations">Sinnvolle Sessions</a></li>
+<?php
+$dataMusclegroups = getData($connect_dbms_handle, $selectFromViewMusclegroups);
+
+foreach ($dataMusclegroups as $musclegroup) {
+?>
+ <li><a href="#mg<?php echo $musclegroup[0]; ?>"><span class="eng"><?php echo $musclegroup[1] ?></span> / <span class="deu"><?php echo $musclegroup[2] ?></span></a></li>";
+<?php
+}
+?>
+<!--
+ <li><a href="#arms">Arme</a></li>
+ <li><a href="#shoulders">Schulter</a></li>
+ <li><a href="#chest">Brust</a></li>
+ <li><a href="#back">Rücken</a></li>
+ <li><a href="#lowerbody">Rumpf</a></li>
+ <li><a href="#hips">Hüfte & Gesäß</a></li>
+ <li><a href="#legs">Beine</a></li>
+ -->
+ <li><a href="#cardio">Cardio</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ul>
+ </nav>
+
+ <section id="warmup">
+ <h2>Warmup</h2>
+ <p class="start">Geräte: Crosstrainer oder Rudergerät</p>
+ <ol>
+ <li>Kreislauf "starten": 10 min mindestens</li>
+ <li>Mobilisierung: Alle Gelenke durchbewegen:
+ <ul>
+ <li>Handgelenke kreisen</li>
+ <li>Armkreisen</li>
+ <li>Kopf/Hals</li>
+ <li>Oberkörper vor- und zurückbeugen</li>
+ <li>Hüftkreisen</li>
+ <li>2-3 mal Anfersen</li>
+ <li>Füße kreisen lassen</li>
+ </ul>
+ </li>
+ </ol>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="general">
+ <h2>Allgemeine Hinweise</h2>
+ <ul>
+ <li>alles außer Rumpf:
+ <ul><li>
+ 75% der Maximalkraft
+ </li><li>Bewegung: Explosiv ausführen, 2 Sekunden zurückführen, 1-2
+ Sekunden halten</li>
+ <li>3 Sätze a 10 Wiederholungen</li>
+ </ul>
+ </li>
+ <li>Rumpf:
+ <ul>
+ <li>50% der Maximalkraft</li>
+ <li>Bewegung: zügig in beide Richtungen ausführen, ohne halten</li>
+ <li>3 Sätze a 20-30 Wiederholungen</li>
+ </ul>
+ </li>
+ <li>Ca. 1 Min. Erholung zwischen den Sätzen.</li>
+ <li>Wenn die Bewegungsqualität unsauber wird: Abbruch der Übung!</li>
+ <li><span class="important">Scheiben auf der Langhantel
+ immer mit Klammern sichern !!!</span></li>
+ <li>Begriffe:<br />Barbell: Langhantel<br />Bumbbell:
+ Kurzhantel
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="combinations">
+ <h2>Sinnvolle Sessions</h2>
+ <ul>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#arms">Arme</a></li>
+ <li><a href="#shoulders">Schulter</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#chest">Brust</a></li>
+ <li><a href="#back">Rücken</a></li>
+ <li><a href="#lowerbody">Rumpf</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#hips">Hüfte & Gesäß</a></li>
+ <li><a href="#legs">Beine</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a>, wenn Cardio im Gym</li>
+ <li><a href="#cardio">Cardio</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+<?php
+foreach ($dataMusclegroups as $musclegroup) {
+?>
+ <section id="mg<?php echo $musclegroup[0] ?>">
+ <h2><span class="eng"><?php echo $musclegroup[1] ?></span> / <span class="deu"><?php echo $musclegroup[2] ?></span></h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+<?php
+ $dataMuscles = getData($connect_dbms_handle, sprintf($selectMucleGroupFromViewMuscles, $musclegroup[0]));
+ foreach ($dataMuscles as $muscle) {
+?>
+ <p class="muscle">
+ Muskel: <span class="musclename"><?php echo $muscle[1] ?> / <span class="eng"><?php echo $muscle[2] ?></span> / <span class="deu"><?php echo $muscle[3] ?></span></span><br /> Bewegung:
+ <span class="eng"><?php echo $muscle[4] ?></span> / <span class="deu"><?php echo $muscle[5] ?></span>
+ </p>
+ <ul>
+<?php
+ $dataAllExercises = getData($connect_dbms_handle, sprintf($selectMucleFromViewAllExercises, $muscle[0]));
+
+ foreach ($dataAllExercises as $exercise) {
+?>
+ <li>
+ <p>
+ Gerät: <span class="eng"><?php echo $exercise[7] ?></span> / <span class="deu"><?php echo $exercise[8] ?></span><br />
+ <a target="_blank" href="><?php echo $exercise[5] ?>">
+ <span class="eng"><?php echo $exercise[17] ?></span> / <span class="deu"><?php echo $exercise[3] ?></span><span class="fa"></span>
+ </a><br />
+ <form name="protokoll_"<?php echo $exercise[0] ?> id="protokoll_"<?php echo $exercise[0] ?> class="ajax-form">
+<?php
+ $dataProtokoll = getData($connect_dbms_handle, sprintf($selectUserExerciseFromViewProtokoll, $current_user, $exercise[0]));
+ print_r($dataProtokoll);
+
+ $nextSet = count($dataProtokoll) + 1;
+ $weightarray = getArrayOfWeights($connect_dbms_handle, $selectWeightsFromViewTools, $exercise[6]);
+
+ makeInput("set_".$exercise[0], $nextSet, "set_".$exercise[0], null, null, "text", 1, 1, null, null, "Set: ", false, false, 6 );
+ makeSelect("reps_".$exercise[0], null, "rep_".$exercise[0], null, null, 1, 50, -1, false, 1, null, null, "Reps.: ", false, false, 6);
+ makeSelect("weight_".$exercise[0], $weightarray, "weight_".$exercise[0], null, null, 0, 0, -1, false, 1, null, null, null, false, false, 6);
+ makeButton("save_".$exercise[0], "save_".$exercise[0], "Save", "save_".$exercise[0], null, null, "submit", null, null, false, false, 6);
+
+
+?>
+ </form><div id="responseMessage_"<?php echo $exercise[0] ?> class="hidden"></div>
+ </p>
+ </li>
+
+<?php
+ }
+?>
+ </ul>
+<?php
+ }
+?>
+ </section>
+
+<?php
+}
+?>
+ <section id="arms">
+ <h2>Arme</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Triceps Brachii / Trizeps</span><br /> Bewegung:
+ Armstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Triceps/DBLyingTriExt">Dumbbell
+ Lying Triceps Extension <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Triceps/CBPushdown">Cable
+ Pushdown <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Biceps Brachii / Bizeps</span><br /> Bewegung:
+ Armbeugung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Easy Bar Langhantel (die geschwungene Langhantel)<br /> <a
+ target="_blank"
+ href="https://exrx.net/WeightExercises/Biceps/BBCurl">Barbell
+ Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Biceps/DBCurl">Dumbbell
+ Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Biceps/CBCurl">Cable
+ Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Brachialis</span><br /> Bewegung:
+ Armbeugung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Brachialis/DBPreacherCurl">Dumbbell
+ Preacher Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="shoulders">
+ <h2>Schulter</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Anterior Deltoid / Deltamuskel vorne</span><br />
+ Bewegung: Oberarm anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/DeltoidAnterior/DBShoulderPress">Dumbbell
+ Shoulder Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Posterior Deltoid / Deltamuskel hinten</span><br />
+ Bewegung: Oberarm nach hinten ziehen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug (ggf. 2)<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/DeltoidPosterior/CBStandingReverseFly">Cable
+ Reverse Fly <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Lateral Deltoid / Deltamuskel seitlich</span><br />
+ Bewegung: Oberarm anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/DeltoidLateral/BBUprightRow">Barbell
+ Upright Row <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Supraspinatus</span><br />
+ Bewegung: Oberarm schräg anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Supraspinatus/DBFrontLateralRaise">Dumbbell
+ Front Lateral Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="chest">
+ <h2>Brust</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Pectoralis Major/ Brustmuskel groß, Ansatz am
+ Brustbein</span><br /> Bewegung: Schulterstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralSternal/DBBenchPress">Dumbbell
+ Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralSternal/BBBenchPress">Barbell
+ Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Pectoralis Major / Brustmuskel groß, Ansatz am
+ Schlüsselbein</span><br /> Bewegung: Schulterstreckung <br /> <span
+ class="important">Rückenlage auf einer schrägen (!) Bank</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralClavicular/DBInclineBenchPress">Dumbbell
+ Incline Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralClavicular/BBInclineBenchPress">Barbell
+ Incline Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralClavicular/CBInclineFly">Cable
+ Incline Fly <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Pectoralis Minor / Brustmuskel klein</span><br />
+ Bewegung: Schulterstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralSternal/CBStandingFly">Cable
+ Standing Fly <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Serratus Anterior / Sägemuskel</span><br /> Bewegung:
+ Schulterstreckung <br /> <span class="important">Rückenlage
+ auf einer schrägen (!) Bank</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/SerratusAnterior/BBInclineShoulderRaise">Barbell
+ Incline Shoulder Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/SerratusAnterior/DBInclineShoulderRaise">Dumbbell
+ Incline Shoulder Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="back">
+ <h2>Rücken</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Latissimus Dorsi</span><br /> Bewegung:
+ Oberarm anlegen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Lat-Zug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/LatissimusDorsi/CBFrontPulldown">Cable
+ Pulldown <span class="fa"></span>
+ </a> <br /> <span class="important">Keine Rückenlage oder mit
+ dem Körpergewicht arbeiten</span>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Trapezius / Trapezmuskel</span><br /> Bewegung:
+ Schulter anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/TrapeziusUpper/DBShrug">Dumbbell
+ Shrug <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Rücken</span><br /> Bewegung:
+ Schultern zusammenziehen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Rudermaschine / Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/BackGeneral/CBStraightBackSeatedRow">Cable
+ Straight Back Seated Row <span class="fa"></span> <br />
+ <span class="important">Keine Rückenlage oder mit dem
+ Körpergewicht arbeiten; Rücken bleibt gerade</span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/BackGeneral/DBBentOverRow">Dumbbell
+ Bent-over Row <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Infraspinatus</span><br />
+ Bewegung: Außenrotation
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Infraspinatus/CBStandingExternalRotation">Cable
+ Standing Shoulder External Rotation <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Subscapularis</span><br />
+ Bewegung: Innenrotation
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Subscapularis/CBStandingInternalRotation">Cable
+ Standing Shoulder Internal Rotation <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="lowerbody">
+ <h2>Rumpf</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Rectus Abdominis / gerade Bauchmuskeln</span><br />
+ Bewegung: Rumpfbeugung<br /> <span class="important">Tip: Übungen für schräge und gerade Bauchmuskeln nicht direkt hintereinander</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/BWSitUpAD">Sit-up <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Ball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/BWBallCrunch">Ball Crunch (on stability ball) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: TRX<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/STJackknife">Suspended Jack-knife <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: schräge Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/BWInclineSitUp">Incline Sit-up <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Obliques / schräge Bauchmuskeln</span><br />
+ Bewegung: Rumpfbeugung schräg<br /> <span class="important">Tip: Übungen für schräge und gerade Bauchmuskeln nicht direkt hintereinander</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/BWTwistingCrunch">Twisting Crunch <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Ball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/BWTwistingBallCrunch">Twisting Crunch (on stability ball) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: TRX<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/STTwistingJackknife">Suspended Twisting Jack-knife <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: schräge Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/BWInclineTwistingSitUp">Incline Twisting Sit-up <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Erector Spinae / Rückenmuskel</span><br />
+ Bewegung: Rumpfstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/BWAlternatingBirdDog">Alternating Bird Dog <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/Superman">Superman <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Ball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/BWHyperextensionBall">Back Extension (on stability ball) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/DBOneArmStraightLegDeadlift">Dumbbell One Arm Straight Leg Deadlift <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: schräge Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/BW45HyperextensionHips">45° Hyperextension <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="hips">
+ <h2>Hüfte & Gesäß</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Gluteus Maximus / großer Gesäßmuskel</span><br />
+ Bewegung: Hüftstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/BWSquat">Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/BWLunge">Lunges <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/DBSplitSquat">Dumbbell Split Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/DBFrontSquat">Dumbbell Front Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Gluteus Minor u.a. / kleiner Gesäßmuskel</span><br />
+ Bewegung: Bein Abspreizen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipAbductor/BWSideBridgeHipAbduction">Side Bridge Hip Abduction <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipAbductor/CBHipAbduction">Cable Hip Abduction <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Piriformes u.a.</span><br />
+ Bewegung: Beine schließen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipAdductors/CBHipAdduction">Cable Hip Adduction <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Rectus Femoris u.a. / Hüftbeuger</span><br />
+ Bewegung: Hüftbeugung<br /><span class="important">Tip: Geht auch mit gestreckten Beinen</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipFlexors/BWLyingLegRaise">Lying Leg Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipFlexors/CBLyingLegRaiseBench">Cable Lying Leg Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="legs">
+ <h2>Beine</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Quadrizeps femoris / Oberschenkel</span><br />
+ Bewegung: Kniestreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Beinpresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Quadriceps/SLHackSquat">Hack Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Bizeps femoris u.a. / Unterschenkel</span><br />
+ Bewegung: Kniebeugung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Hamstrings/CBLyingLegCurl">Cable Lying Leg Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Gastrocnemius / zweibäuchiger Wadenmuskel</span><br />
+ Bewegung: Fuß strecken / Knie beugen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Beinpresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Gastrocnemius/SLLyingCalfPress">Sled Lying Calf Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Gastrocnemius/DBSingleLegCalfRaise">Dumbbell Single Leg Calf Raise
+ <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Soleus / Schollenmuskel</span><br />
+ Bewegung: Fuß strecken
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Multipresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Soleus/SMSeatedCalfRaise">Smith Seated Calf Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Tibialis Anterior / vorderer Schienbeinmuskel</span><br />
+ Bewegung: Fuß anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/TibialisAnterior/DBReverseCalfRaise">Dumbbell Reverse Calf Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Beinpresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/TibialisAnterior/SLHackReverseCalfRaise">Sled Hack Reverse Calf Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="cardio">
+ <h2>Cardio</h2>
+ <p class="muscle">
+ Laufen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Dauerläufe in ruhigem Tempo, so daß Du noch durch die Nase atmen kannst.<br />Dauer: 30-60 min
+ </p>
+ </li>
+ <li>
+ <p>
+ Intervalläufe, 5-10 x 300-500m schnell und hart, 2-4 min Trab- / Gehpause.<br />Vorher 15-20 min einlaufen, anschließend 10 min auslaufen. Immer.
+ </p>
+ </li>
+ <li>
+ <p>
+ Berganläufe, 5-10 x 1-2 min schnell und hart, 2-4 min Trab- / Gehpause.<br />Vorher 15-20 min einlaufen, anschließend 10 min auslaufen. Immer.
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Schwimmen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Dauerschwimmen, 1000 bis ?? m in ruhigem Tempo in verschiedenen Lagen.
+ </p>
+ </li>
+ <li>
+ <p>
+ <a href="https://swim.triathlon-coaching.com">Schwimmtrainingspläne</a> (fast) ohne Ende...
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Zirkeltraining / CrossFit<br />Jede Übung 1 min, 1min Pause
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kettleball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Kettlebell/KBTwoArmSwing">Kettlebell Two Arm Swing <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/Aerobic/Exercises/Burpee">Burpee <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Medizinball<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/MBWallShot">Medicine Ball Wall Shot <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Box / Step<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/BoxLateralJump">Lateral Box Jumps <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Medizinball<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/MBChestThrowSitupWall">Medicine Ball Chest Throw Sit-up (on wall) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Tau<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Power/RopeWave">Rope Wave <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Power/DBThruster">Dumbbell Thruster <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/SplitJump">Split Jump <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="stretching">
+ <h2>Stretching</h2>
+ <p class="start">Jede Übung 3 mal (pro Seite)<br />Anpannen - Entspannen - Dehnen<br />Pflicht: Die Muskeln, die man auch trainiert hat, dehenen</p>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Hals</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Sternocleidomastoid/NeckRetraction">Neck Retraction Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Splenius/Neck">Neck Extensor Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Schulter</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/DeltoidAnterior/Doorway">Doorway Front Deltoid Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/DeltoidLateral/SideDelt">Side Deltoid Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/DeltoidPosterior/RearDelt">Rear Deltoid Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Arme</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Triceps/Overhead">Overhead Triceps Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Biceps/Seated">Seated Biceps Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Brachioradialis/Standing">Standing Brachioradialis Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/WristFlexors/Seated">Seated Wrist Flexor Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/WristExtensors/Single">Single Arm Wrist Extensor <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Rücken</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/BackGeneral/PCCrossHand">Lever Back Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/LatissimusDorsi/Overhead">Overhead Lat Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/LatissimusDorsi/StandingSideReach">Standing Side Reach Lat Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Rhomboids/Hugging">Hugging Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Infraspinatus/SideLying">Side Lying Infraspinatus <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Subscapularis/Doorway">Doorway Subscapularis Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Brust</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/ChestGeneral/StraightArm">Straight Arm Chest Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/PectoralisMinor/Wall">Wall Angel <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Bauch</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/RectusAbdominis/Prone">Lying (prone) Abdominal Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Obliques/LyingCrossover">Lying Crossover Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Obliques/Pretzel">Pretzel Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/ErectorSpinae/SeatedFloor">Seated Lower Back Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Hüfte</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/GluteusMaximus/LyingModified">Lying Glute Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/GluteusMaximus/Squatting">Squatting Glute Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/WallIliotibial">Wall Iliotibial Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/Pretzel">Seated Pretzel Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/SeatedHipInternalRotator">Seated Hip Internal Rotator Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/LyingCrossover">Lying Crossover Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipFlexors/KneelingHipFlexor">Kneeling Hip Flexor Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipExternalRotators/SeatedHipExternalRotator">Seated Hip External Rotator Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Beine</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Quadriceps/SideLying">Lying (side) Quadriceps Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Hamstrings/LyingSingleLeg">Lying Hamstring Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Hamstrings/SeatedSingleLeg">Seated Single Leg Hamstring Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAdductors/SeatedGroinFloor">Seated Groin Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAdductors/SideLunge">Side Lunge Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Gastrocnemius/Wall">Wall Straight Leg Calf Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Soleus/Wall">Wall Bent Knee Calf Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/TibialisAnterior/Kneeling">Kneeling Shin Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+<script src="js/athletik.js"></script>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html lang="de">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="stylesheet"
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+<title>Kraft- und Ausdauertraining Lasse</title>
+<style type="text/css">
+BODY {
+ font-family: sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
+ 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
+ 'Helvetica Neue';
+ line-height: 1.5;
+ font-size: 1rem;
+ margin: 0;
+}
+
+HEADER, SECTION {
+ margin-left: 15em;
+ padding: 0 0 0 1rem;
+}
+
+NAV {
+ background: #f0f0f0;
+ height: 100%;
+ position: fixed;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ width: 15em;
+ overflow-x: hidden;
+}
+
+OL {
+ margin: 1.25em 0;
+}
+
+UL.navbar {
+ list-style-type: none;
+}
+
+.navbar li a {
+ text-decoration: none;
+ color: #333;
+ padding: 0.5rem 1rem;
+ display: block;
+ font-size: 2em;
+}
+
+.navbar li a:active, .navbar li a:hover {
+ background: #ddd;
+ transition: background 0.2s ease;
+}
+
+P.muscle {
+ border-top: 0.2em solid black;
+ padding: 0.25em 0 0 0;
+}
+
+P.start {
+ font-size: 1.25rem;
+ padding: 0 0 1.5em 0;
+}
+
+LI, P {
+ font-size: 1rem;
+}
+
+A {
+ text-decoration: none;
+}
+
+.musclename {
+ font-weight: 600;
+ color: #933;
+ background-color: #ddd;
+ padding: 0.5em;
+}
+
+.important {
+ font-weight: 600;
+ color: red;
+}
+
+.fa {
+ font-size: 1.5em;
+}
+
+H1 {
+ text-align: center;
+ font-size: 4.5em;
+}
+
+H2 {
+ text-align: center;
+ font-size: 3em;
+ text-decoration: underline overline;
+}
+
+.totop {
+ background-color: #666;
+ color: #ccc;
+ padding: 0.5em 2em;
+}
+
+.totop A {
+ color: #ccc;
+ font-size: 0.75em;
+}
+</style>
+</head>
+<body>
+
+ <header>
+ <h1 id="nav">Trainingsplan</h1>
+ </header>
+
+ <nav>
+ <ul class="navbar">
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#general">Allgemeine Hinweise</a></li>
+ <li><a href="#combinations">Sinnvolle Sessions</a></li>
+ <li><a href="#arms">Arme</a></li>
+ <li><a href="#shoulders">Schulter</a></li>
+ <li><a href="#chest">Brust</a></li>
+ <li><a href="#back">Rücken</a></li>
+ <li><a href="#lowerbody">Rumpf</a></li>
+ <li><a href="#hips">Hüfte & Gesäß</a></li>
+ <li><a href="#legs">Beine</a></li>
+ <li><a href="#cardio">Cardio</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ul>
+ </nav>
+
+ <section id="warmup">
+ <h2>Warmup</h2>
+ <p class="start">Geräte: Crosstrainer oder Rudergerät</p>
+ <ol>
+ <li>Kreislauf "starten": 10 min mindestens</li>
+ <li>Mobilisierung: Alle Gelenke durchbewegen:
+ <ul>
+ <li>Handgelenke kreisen</li>
+ <li>Armkreisen</li>
+ <li>Kopf/Hals</li>
+ <li>Oberkörper vor- und zurückbeugen</li>
+ <li>Hüftkreisen</li>
+ <li>2-3 mal Anfersen</li>
+ <li>Füße kreisen lassen</li>
+ </ul>
+ </li>
+ </ol>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="general">
+ <h2>Allgemeine Hinweise</h2>
+ <ul>
+ <li>alles außer Rumpf:
+ <ul><li>
+ 75% der Maximalkraft
+ </li><li>Bewegung: Explosiv ausführen, 2 Sekunden zurückführen, 1-2
+ Sekunden halten</li>
+ <li>3 Sätze a 10 Wiederholungen</li>
+ </ul>
+ </li>
+ <li>Rumpf:
+ <ul>
+ <li>50% der Maximalkraft</li>
+ <li>Bewegung: zügig in beide Richtungen ausführen, ohne halten</li>
+ <li>3 Sätze a 20-30 Wiederholungen</li>
+ </ul>
+ </li>
+ <li>Ca. 1 Min. Erholung zwischen den Sätzen.</li>
+ <li>Wenn die Bewegungsqualität unsauber wird: Abbruch der Übung!</li>
+ <li><span class="important">Scheiben auf der Langhantel
+ immer mit Klammern sichern !!!</span></li>
+ <li>Begriffe:<br />Barbell: Langhantel<br />Bumbbell:
+ Kurzhantel
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="combinations">
+ <h2>Sinnvolle Sessions</h2>
+ <ul>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#arms">Arme</a></li>
+ <li><a href="#shoulders">Schulter</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#chest">Brust</a></li>
+ <li><a href="#back">Rücken</a></li>
+ <li><a href="#lowerbody">Rumpf</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a></li>
+ <li><a href="#hips">Hüfte & Gesäß</a></li>
+ <li><a href="#legs">Beine</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ <li><ol>
+ <li><a href="#warmup">Aufwärmen</a>, wenn Cardio im Gym</li>
+ <li><a href="#cardio">Cardio</a></li>
+ <li><a href="#stretching">Stretching</a></li>
+ </ol></li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="arms">
+ <h2>Arme</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Triceps Brachii / Trizeps</span><br /> Bewegung:
+ Armstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Triceps/DBLyingTriExt">Dumbbell
+ Lying Triceps Extension <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Triceps/CBPushdown">Cable
+ Pushdown <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Biceps Brachii / Bizeps</span><br /> Bewegung:
+ Armbeugung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Easy Bar Langhantel (die geschwungene Langhantel)<br /> <a
+ target="_blank"
+ href="https://exrx.net/WeightExercises/Biceps/BBCurl">Barbell
+ Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Biceps/DBCurl">Dumbbell
+ Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Biceps/CBCurl">Cable
+ Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Brachialis</span><br /> Bewegung:
+ Armbeugung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Brachialis/DBPreacherCurl">Dumbbell
+ Preacher Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="shoulders">
+ <h2>Schulter</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Anterior Deltoid / Deltamuskel vorne</span><br />
+ Bewegung: Oberarm anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/DeltoidAnterior/DBShoulderPress">Dumbbell
+ Shoulder Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Posterior Deltoid / Deltamuskel hinten</span><br />
+ Bewegung: Oberarm nach hinten ziehen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug (ggf. 2)<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/DeltoidPosterior/CBStandingReverseFly">Cable
+ Reverse Fly <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Lateral Deltoid / Deltamuskel seitlich</span><br />
+ Bewegung: Oberarm anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/DeltoidLateral/BBUprightRow">Barbell
+ Upright Row <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Supraspinatus</span><br />
+ Bewegung: Oberarm schräg anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Supraspinatus/DBFrontLateralRaise">Dumbbell
+ Front Lateral Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="chest">
+ <h2>Brust</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Pectoralis Major/ Brustmuskel groß, Ansatz am
+ Brustbein</span><br /> Bewegung: Schulterstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralSternal/DBBenchPress">Dumbbell
+ Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralSternal/BBBenchPress">Barbell
+ Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Pectoralis Major / Brustmuskel groß, Ansatz am
+ Schlüsselbein</span><br /> Bewegung: Schulterstreckung <br /> <span
+ class="important">Rückenlage auf einer schrägen (!) Bank</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralClavicular/DBInclineBenchPress">Dumbbell
+ Incline Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralClavicular/BBInclineBenchPress">Barbell
+ Incline Bench Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralClavicular/CBInclineFly">Cable
+ Incline Fly <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Pectoralis Minor / Brustmuskel klein</span><br />
+ Bewegung: Schulterstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/PectoralSternal/CBStandingFly">Cable
+ Standing Fly <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Serratus Anterior / Sägemuskel</span><br /> Bewegung:
+ Schulterstreckung <br /> <span class="important">Rückenlage
+ auf einer schrägen (!) Bank</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Langhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/SerratusAnterior/BBInclineShoulderRaise">Barbell
+ Incline Shoulder Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/SerratusAnterior/DBInclineShoulderRaise">Dumbbell
+ Incline Shoulder Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="back">
+ <h2>Rücken</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Latissimus Dorsi</span><br /> Bewegung:
+ Oberarm anlegen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Lat-Zug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/LatissimusDorsi/CBFrontPulldown">Cable
+ Pulldown <span class="fa"></span>
+ </a> <br /> <span class="important">Keine Rückenlage oder mit
+ dem Körpergewicht arbeiten</span>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Trapezius / Trapezmuskel</span><br /> Bewegung:
+ Schulter anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/TrapeziusUpper/DBShrug">Dumbbell
+ Shrug <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Rücken</span><br /> Bewegung:
+ Schultern zusammenziehen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Rudermaschine / Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/BackGeneral/CBStraightBackSeatedRow">Cable
+ Straight Back Seated Row <span class="fa"></span> <br />
+ <span class="important">Keine Rückenlage oder mit dem
+ Körpergewicht arbeiten; Rücken bleibt gerade</span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/BackGeneral/DBBentOverRow">Dumbbell
+ Bent-over Row <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Infraspinatus</span><br />
+ Bewegung: Außenrotation
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Infraspinatus/CBStandingExternalRotation">Cable
+ Standing Shoulder External Rotation <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Subscapularis</span><br />
+ Bewegung: Innenrotation
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Subscapularis/CBStandingInternalRotation">Cable
+ Standing Shoulder Internal Rotation <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="lowerbody">
+ <h2>Rumpf</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Rectus Abdominis / gerade Bauchmuskeln</span><br />
+ Bewegung: Rumpfbeugung<br /> <span class="important">Tip: Übungen für schräge und gerade Bauchmuskeln nicht direkt hintereinander</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/BWSitUpAD">Sit-up <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Ball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/BWBallCrunch">Ball Crunch (on stability ball) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: TRX<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/STJackknife">Suspended Jack-knife <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: schräge Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/RectusAbdominis/BWInclineSitUp">Incline Sit-up <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Obliques / schräge Bauchmuskeln</span><br />
+ Bewegung: Rumpfbeugung schräg<br /> <span class="important">Tip: Übungen für schräge und gerade Bauchmuskeln nicht direkt hintereinander</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/BWTwistingCrunch">Twisting Crunch <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Ball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/BWTwistingBallCrunch">Twisting Crunch (on stability ball) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: TRX<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/STTwistingJackknife">Suspended Twisting Jack-knife <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: schräge Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Obliques/BWInclineTwistingSitUp">Incline Twisting Sit-up <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Erector Spinae / Rückenmuskel</span><br />
+ Bewegung: Rumpfstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/BWAlternatingBirdDog">Alternating Bird Dog <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/Superman">Superman <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Ball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/BWHyperextensionBall">Back Extension (on stability ball) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/DBOneArmStraightLegDeadlift">Dumbbell One Arm Straight Leg Deadlift <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: schräge Bank<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/ErectorSpinae/BW45HyperextensionHips">45° Hyperextension <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="hips">
+ <h2>Hüfte & Gesäß</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Gluteus Maximus / großer Gesäßmuskel</span><br />
+ Bewegung: Hüftstreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/BWSquat">Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/BWLunge">Lunges <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/DBSplitSquat">Dumbbell Split Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/GluteusMaximus/DBFrontSquat">Dumbbell Front Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Gluteus Minor u.a. / kleiner Gesäßmuskel</span><br />
+ Bewegung: Bein Abspreizen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipAbductor/BWSideBridgeHipAbduction">Side Bridge Hip Abduction <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipAbductor/CBHipAbduction">Cable Hip Abduction <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Piriformes u.a.</span><br />
+ Bewegung: Beine schließen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipAdductors/CBHipAdduction">Cable Hip Adduction <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Rectus Femoris u.a. / Hüftbeuger</span><br />
+ Bewegung: Hüftbeugung<br /><span class="important">Tip: Geht auch mit gestreckten Beinen</span>
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipFlexors/BWLyingLegRaise">Lying Leg Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/HipFlexors/CBLyingLegRaiseBench">Cable Lying Leg Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="legs">
+ <h2>Beine</h2>
+ <p class="start">Nur eine Übung je Bewegung / Muskel:</p>
+ <p class="muscle">
+ Muskel: <span class="musclename">Quadrizeps femoris / Oberschenkel</span><br />
+ Bewegung: Kniestreckung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Beinpresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Quadriceps/SLHackSquat">Hack Squat <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Bizeps femoris u.a. / Unterschenkel</span><br />
+ Bewegung: Kniebeugung
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kabelzug<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Hamstrings/CBLyingLegCurl">Cable Lying Leg Curl <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Gastrocnemius / zweibäuchiger Wadenmuskel</span><br />
+ Bewegung: Fuß strecken / Knie beugen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Beinpresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Gastrocnemius/SLLyingCalfPress">Sled Lying Calf Press <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Gastrocnemius/DBSingleLegCalfRaise">Dumbbell Single Leg Calf Raise
+ <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Soleus / Schollenmuskel</span><br />
+ Bewegung: Fuß strecken
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Multipresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Soleus/SMSeatedCalfRaise">Smith Seated Calf Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel: <span class="musclename">Tibialis Anterior / vorderer Schienbeinmuskel</span><br />
+ Bewegung: Fuß anheben
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/TibialisAnterior/DBReverseCalfRaise">Dumbbell Reverse Calf Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Beinpresse<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/TibialisAnterior/SLHackReverseCalfRaise">Sled Hack Reverse Calf Raise <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="cardio">
+ <h2>Cardio</h2>
+ <p class="muscle">
+ Laufen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Dauerläufe in ruhigem Tempo, so daß Du noch durch die Nase atmen kannst.<br />Dauer: 30-60 min
+ </p>
+ </li>
+ <li>
+ <p>
+ Intervalläufe, 5-10 x 300-500m schnell und hart, 2-4 min Trab- / Gehpause.<br />Vorher 15-20 min einlaufen, anschließend 10 min auslaufen. Immer.
+ </p>
+ </li>
+ <li>
+ <p>
+ Berganläufe, 5-10 x 1-2 min schnell und hart, 2-4 min Trab- / Gehpause.<br />Vorher 15-20 min einlaufen, anschließend 10 min auslaufen. Immer.
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Schwimmen
+ </p>
+ <ul>
+ <li>
+ <p>
+ Dauerschwimmen, 1000 bis ?? m in ruhigem Tempo in verschiedenen Lagen.
+ </p>
+ </li>
+ <li>
+ <p>
+ <a href="https://swim.triathlon-coaching.com">Schwimmtrainingspläne</a> (fast) ohne Ende...
+ </p>
+ </li>
+ </ul>
+ <p class="muscle">
+ Zirkeltraining / CrossFit<br />Jede Übung 1 min, 1min Pause
+ </p>
+ <ul>
+ <li>
+ <p>
+ Gerät: Kettleball<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Kettlebell/KBTwoArmSwing">Kettlebell Two Arm Swing <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/Aerobic/Exercises/Burpee">Burpee <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Medizinball<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/MBWallShot">Medicine Ball Wall Shot <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Box / Step<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/BoxLateralJump">Lateral Box Jumps <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Medizinball<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/MBChestThrowSitupWall">Medicine Ball Chest Throw Sit-up (on wall) <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Tau<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Power/RopeWave">Rope Wave <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: Kurzhantel<br /> <a target="_blank"
+ href="https://exrx.net/WeightExercises/Power/DBThruster">Dumbbell Thruster <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ <li>
+ <p>
+ Gerät: none<br /> <a target="_blank"
+ href="https://exrx.net/Plyometrics/SplitJump">Split Jump <span class="fa"></span>
+ </a>
+ </p>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+ <section id="stretching">
+ <h2>Stretching</h2>
+ <p class="start">Jede Übung 3 mal (pro Seite)<br />Anpannen - Entspannen - Dehnen<br />Pflicht: Die Muskeln, die man auch trainiert hat, dehenen</p>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Hals</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Sternocleidomastoid/NeckRetraction">Neck Retraction Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Splenius/Neck">Neck Extensor Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Schulter</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/DeltoidAnterior/Doorway">Doorway Front Deltoid Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/DeltoidLateral/SideDelt">Side Deltoid Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/DeltoidPosterior/RearDelt">Rear Deltoid Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Arme</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Triceps/Overhead">Overhead Triceps Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Biceps/Seated">Seated Biceps Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Brachioradialis/Standing">Standing Brachioradialis Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/WristFlexors/Seated">Seated Wrist Flexor Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/WristExtensors/Single">Single Arm Wrist Extensor <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Rücken</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/BackGeneral/PCCrossHand">Lever Back Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/LatissimusDorsi/Overhead">Overhead Lat Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/LatissimusDorsi/StandingSideReach">Standing Side Reach Lat Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Rhomboids/Hugging">Hugging Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Infraspinatus/SideLying">Side Lying Infraspinatus <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Subscapularis/Doorway">Doorway Subscapularis Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Brust</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/ChestGeneral/StraightArm">Straight Arm Chest Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/PectoralisMinor/Wall">Wall Angel <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Bauch</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/RectusAbdominis/Prone">Lying (prone) Abdominal Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Obliques/LyingCrossover">Lying Crossover Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Obliques/Pretzel">Pretzel Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/ErectorSpinae/SeatedFloor">Seated Lower Back Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Hüfte</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/GluteusMaximus/LyingModified">Lying Glute Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/GluteusMaximus/Squatting">Squatting Glute Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/WallIliotibial">Wall Iliotibial Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/Pretzel">Seated Pretzel Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/SeatedHipInternalRotator">Seated Hip Internal Rotator Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAbductors/LyingCrossover">Lying Crossover Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipFlexors/KneelingHipFlexor">Kneeling Hip Flexor Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipExternalRotators/SeatedHipExternalRotator">Seated Hip External Rotator Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="muscle">
+ Muskel(-gruppe): <span class="musclename">Beine</span>
+ </p>
+ <ul>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Quadriceps/SideLying">Lying (side) Quadriceps Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Hamstrings/LyingSingleLeg">Lying Hamstring Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Hamstrings/SeatedSingleLeg">Seated Single Leg Hamstring Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAdductors/SeatedGroinFloor">Seated Groin Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/HipAdductors/SideLunge">Side Lunge Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Gastrocnemius/Wall">Wall Straight Leg Calf Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/Soleus/Wall">Wall Bent Knee Calf Stretch <span class="fa"></span></a>
+ </li>
+ <li>
+ <a target="_blank" href="https://exrx.net/Stretches/TibialisAnterior/Kneeling">Kneeling Shin Stretch <span class="fa"></span></a>
+ </li>
+ </ul>
+ <p class="totop">
+ <a href="#nav">nach oben</a>
+ </p>
+ </section>
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+package com.triathlon_coaching.product.athletik.web;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+@ComponentScan({"com.triathlon_coaching.product.athletik.web", "com.triathlon_coaching.product.athletik.backend"})
+public class AthletikWebApplication extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(FitnessWebApplication.class);
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(FitnessWebApplication.class, args);
+ }
+}
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>athletik.webapp</artifactId>
+ <packaging>war</packaging>
+
+ <name>${project.artifactId}</name>
+ <description>Athletik Training Webapp</description>
+
+ <parent>
+ <groupId>com.triathlon-coaching.product</groupId>
+ <artifactId>athletik</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </parent>
+
+
+ <dependencyManagement>
+ <dependencies>
+
+ <!-- Thymeleaf -->
+ <!-- WebUI-->
+ <dependency>
+ <groupId>org.thymeleaf</groupId>
+ <artifactId>thymeleaf-spring5</artifactId>
+ <version>${thymeleaf.version}</version>
+ </dependency>
+
+ <!-- JEE -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${javax.servlet-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Web (für REST API) -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <version>${spring-boot.version}</version>
+ </dependency>
+
+ <!-- Tomcat Embed (for testing) -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ <scope>provided</scope>
+ <version>${spring-boot.version}</version>
+ </dependency>
+
+ </dependencies>
+ </dependencyManagement>
+
+
+ <dependencies>
+ <!-- Backend Module -->
+ <dependency>
+ <groupId>com.triathlon-coaching.product</groupId>
+ <artifactId>athletik.service</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Thymeleaf -->
+ <!-- WebUI-->
+ <dependency>
+ <groupId>org.thymeleaf</groupId>
+ <artifactId>thymeleaf-spring5</artifactId>
+ </dependency>
+
+ <!-- Web -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+
+ <!-- Servlet API (provided by Tomcat) -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Tomcat Embed (for testing) -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>fitness-web</finalName>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot.version}</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>com.fitnessapp.web.FitnessWebApplication</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>dev</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <properties>
+ <spring.profiles.active>dev</spring.profiles.active>
+ </properties>
+ </profile>
+ <profile>
+ <id>prod</id>
+ <properties>
+ <spring.profiles.active>prod</spring.profiles.active>
+ </properties>
+ </profile>
+ </profiles>
+
+</project>
--- /dev/null
+<!DOCTYPE html>
+<html lang="de" xmlns:th="http://www.thymeleaf.org">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Athletik Training - Startseite</title>
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
+ <link rel="stylesheet" href="css/athletik.css">
+ <style>
+ .hero-section {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ padding: 80px 0;
+ text-align: center;
+ }
+ .feature-card {
+ border: none;
+ border-radius: 15px;
+ box-shadow: 0 4px 15px rgba(0,0,0,0.1);
+ transition: transform 0.3s ease;
+ height: 100%;
+ }
+ .feature-card:hover {
+ transform: translateY(-5px);
+ }
+ .feature-icon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+ color: #667eea;
+ }
+ .stats-number {
+ font-size: 2.5rem;
+ font-weight: bold;
+ color: #667eea;
+ }
+ .testimonial-card {
+ background: #f8f9fa;
+ border-radius: 15px;
+ padding: 2rem;
+ margin: 1rem 0;
+ }
+ .cta-section {
+ background: #f8f9fa;
+ padding: 60px 0;
+ }
+ .muscle-group-card {
+ background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%);
+ color: white;
+ border-radius: 15px;
+ padding: 20px;
+ text-align: center;
+ margin-bottom: 20px;
+ min-height: 120px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: transform 0.3s ease;
+ }
+ .muscle-group-card:hover {
+ transform: scale(1.05);
+ }
+ .navbar-brand {
+ font-weight: bold;
+ font-size: 1.5rem;
+ }
+ @media (max-width: 768px) {
+ .hero-section {
+ padding: 60px 0;
+ }
+ .feature-icon {
+ font-size: 2.5rem;
+ }
+ }
+ </style>
+</head>
+<body>
+ <!-- Navigation -->
+ <nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
+ <div class="container">
+ <a class="navbar-brand" href="/">
+ <i class="fas fa-dumbbell me-2"></i>Athletik Training
+ </a>
+ <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+ <div class="collapse navbar-collapse" id="navbarNav">
+ <ul class="navbar-nav ms-auto">
+ <li class="nav-item">
+ <a class="nav-link" href="#features">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#musclegroups">Muskelgruppen</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#testimonials">Erfolge</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#about">Über uns</a>
+ </li>
+ <li class="nav-item">
+ <a class="btn btn-outline-light ms-2" href="/login">
+ <i class="fas fa-sign-in-alt"></i> Login
+ </a>
+ </li>
+ <li class="nav-item">
+ <a class="btn btn-primary ms-2" href="/login?register=true">
+ <i class="fas fa-user-plus"></i> Registrieren
+ </a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </nav>
+
+ <!-- Hero Section -->
+ <section class="hero-section">
+ <div class="container">
+ <div class="row">
+ <div class="col-lg-8 mx-auto">
+ <h1 class="display-4 fw-bold mb-4">Dein digitaler Trainingspartner</h1>
+ <p class="lead mb-4">Protokolliere deine Workouts, tracke deine Fortschritte und erreiche deine Fitnessziele mit unserer intelligenten Plattform.</p>
+ <div class="d-flex gap-3 justify-content-center flex-wrap">
+ <a href="/login?register=true" class="btn btn-light btn-lg">
+ <i class="fas fa-rocket me-2"></i>Jetzt starten
+ </a>
+ <a href="#features" class="btn btn-outline-light btn-lg">
+ <i class="fas fa-info-circle me-2"></i>Mehr erfahren
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <!-- Stats Section -->
+ <section class="py-5 bg-light">
+ <div class="container">
+ <div class="row text-center">
+ <div class="col-md-3 col-6 mb-4">
+ <div class="stats-number" id="totalUsers">5.000+</div>
+ <p class="text-muted">Aktive Nutzer</p>
+ </div>
+ <div class="col-md-3 col-6 mb-4">
+ <div class="stats-number" id="totalWorkouts">250.000+</div>
+ <p class="text-muted">Protokollierte Workouts</p>
+ </div>
+ <div class="col-md-3 col-6 mb-4">
+ <div class="stats-number" id="totalExercises">200+</div>
+ <p class="text-muted">Übungen</p>
+ </div>
+ <div class="col-md-3 col-6 mb-4">
+ <div class="stats-number" id="successRate">98%</div>
+ <p class="text-muted">Zufriedene Athleten</p>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <!-- Features Section -->
+ <section id="features" class="py-5">
+ <div class="container">
+ <div class="text-center mb-5">
+ <h2 class="display-5 fw-bold">Warum Athletik Training?</h2>
+ <p class="lead text-muted">Alles, was du für deinen Trainingserfolg brauchst</p>
+ </div>
+
+ <div class="row g-4">
+ <div class="col-lg-4 col-md-6">
+ <div class="card feature-card h-100">
+ <div class="card-body text-center p-4">
+ <div class="feature-icon">
+ <i class="fas fa-clipboard-list"></i>
+ </div>
+ <h4>Intuitive Protokollierung</h4>
+ <p class="text-muted">Erfasse deine Trainingseinheiten mühelos mit unserem benutzerfreundlichen Interface.</p>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-lg-4 col-md-6">
+ <div class="card feature-card h-100">
+ <div class="card-body text-center p-4">
+ <div class="feature-icon">
+ <i class="fas fa-chart-line"></i>
+ </div>
+ <h4>Fortschritt tracking</h4>
+ <p class="text-muted">Verfolge deine Leistungssteigerung mit detaillierten Statistiken und Diagrammen.</p>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-lg-4 col-md-6">
+ <div class="card feature-card h-100">
+ <div class="card-body text-center p-4">
+ <div class="feature-icon">
+ <i class="fas fa-dumbbell"></i>
+ </div>
+ <h4>Umfangreiche Übungsdatenbank</h4>
+ <p class="text-muted">Über 200 Übungen mit Videoanleitungen und Muskelgruppen-Zuordnung.</p>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-lg-4 col-md-6">
+ <div class="card feature-card h-100">
+ <div class="card-body text-center p-4">
+ <div class="feature-icon">
+ <i class="fas fa-calculator"></i>
+ </div>
+ <h4>1RM Berechnung</h4>
+ <p class="text-muted">Automatische Berechnung deiner Maximalkraft basierend auf deinen Trainingseinheiten.</p>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-lg-4 col-md-6">
+ <div class="card feature-card h-100">
+ <div class="card-body text-center p-4">
+ <div class="feature-icon">
+ <i class="fas fa-envelope"></i>
+ </div>
+ <h4>E-Mail Zusammenfassungen</h4>
+ <p class="text-muted">Erhalte detaillierte Trainingszusammenfassungen per E-Mail nach jeder Einheit.</p>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-lg-4 col-md-6">
+ <div class="card feature-card h-100">
+ <div class="card-body text-center p-4">
+ <div class="feature-icon">
+ <i class="fas fa-mobile-alt"></i>
+ </div>
+ <h4>Mobile Optimiert</h4>
+ <p class="text-muted">Perfekt für die Nutzung im Fitnessstudio auf deinem Smartphone oder Tablet.</p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <!-- Muscle Groups Section -->
+ <section id="musclegroups" class="py-5 bg-light">
+ <div class="container">
+ <div class="text-center mb-5">
+ <h2 class="display-5 fw-bold">Muskelgruppen</h2>
+ <p class="lead text-muted">Trainiere gezielt alle Muskelgruppen</p>
+ </div>
+
+ <div class="row" id="muscleGroupsContainer">
+ <!-- Wird dynamisch gefüllt -->
+ </div>
+ </div>
+ </section>
+
+ <!-- Testimonials Section -->
+ <section id="testimonials" class="py-5">
+ <div class="container">
+ <div class="text-center mb-5">
+ <h2 class="display-5 fw-bold">Erfolgsgeschichten</h2>
+ <p class="lead text-muted">Was unsere Athleten sagen</p>
+ </div>
+
+ <div class="row">
+ <div class="col-lg-4 mb-4">
+ <div class="testimonial-card text-center">
+ <div class="mb-3">
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ </div>
+ <p class="fst-italic">"Durch das präzise Tracking meiner Trainingseinheiten konnte ich meine Maximalkraft in 3 Monaten um 25% steigern!"</p>
+ <h6>Markus T.</h6>
+ <small class="text-muted">Seit 6 Monaten dabei</small>
+ </div>
+ </div>
+
+ <div class="col-lg-4 mb-4">
+ <div class="testimonial-card text-center">
+ <div class="mb-3">
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ </div>
+ <p class="fst-italic">"Die E-Mail-Zusammenfassungen helfen mir, meinen Fortschritt im Blick zu behalten und motivieren mich weiterzumachen."</p>
+ <h6>Sarah K.</h6>
+ <small class="text-muted">Seit 1 Jahr dabei</small>
+ </div>
+ </div>
+
+ <div class="col-lg-4 mb-4">
+ <div class="testimonial-card text-center">
+ <div class="mb-3">
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ <i class="fas fa-star text-warning"></i>
+ </div>
+ <p class="fst-italic">"Die Übungsdatenbank mit Videoanleitungen hat mein Training revolutioniert. Endlich mache ich jede Übung korrekt!"</p>
+ <h6>Thomas R.</h6>
+ <small class="text-muted">Seit 3 Monaten dabei</small>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <!-- CTA Section -->
+ <section id="cta" class="cta-section">
+ <div class="container">
+ <div class="row">
+ <div class="col-lg-8 mx-auto text-center">
+ <h2 class="display-6 fw-bold mb-4">Bereit, dein Training zu transformieren?</h2>
+ <p class="lead mb-4">Starte noch heute und werde Teil unserer Community von erfolgreichen Athleten.</p>
+ <a href="/login?register=true" class="btn btn-primary btn-lg px-5">
+ <i class="fas fa-user-plus me-2"></i>Kostenlos registrieren
+ </a>
+ </div>
+ </div>
+ </div>
+ </section>
+
+ <!-- Footer -->
+ <footer class="bg-dark text-white py-4">
+ <div class="container">
+ <div class="row">
+ <div class="col-lg-4 mb-4">
+ <h5><i class="fas fa-dumbbell me-2"></i>Athletik Training</h5>
+ <p class="text-muted">Dein digitaler Partner für maximale Trainingserfolge.</p>
+ </div>
+ <div class="col-lg-2 col-6 mb-4">
+ <h6>Navigation</h6>
+ <ul class="list-unstyled">
+ <li><a href="#features" class="text-muted text-decoration-none">Features</a></li>
+ <li><a href="#musclegroups" class="text-muted text-decoration-none">Muskelgruppen</a></li>
+ <li><a href="#testimonials" class="text-muted text-decoration-none">Erfolge</a></li>
+ </ul>
+ </div>
+ <div class="col-lg-2 col-6 mb-4">
+ <h6>Rechtliches</h6>
+ <ul class="list-unstyled">
+ <li><a href="#" class="text-muted text-decoration-none">Datenschutz</a></li>
+ <li><a href="#" class="text-muted text-decoration-none">Impressum</a></li>
+ <li><a href="#" class="text-muted text-decoration-none">AGB</a></li>
+ </ul>
+ </div>
+ <div class="col-lg-4 mb-4">
+ <h6>Kontakt</h6>
+ <p class="text-muted mb-1">
+ <i class="fas fa-envelope me-2"></i>support@athletik-training.de
+ </p>
+ <div class="d-flex gap-3 mt-3">
+ <a href="#" class="text-muted"><i class="fab fa-facebook fa-lg"></i></a>
+ <a href="#" class="text-muted"><i class="fab fa-instagram fa-lg"></i></a>
+ <a href="#" class="text-muted"><i class="fab fa-twitter fa-lg"></i></a>
+ </div>
+ </div>
+ </div>
+ <hr class="my-4">
+ <div class="text-center">
+ <p class="text-muted mb-0">© 2024 Athletik Training. Alle Rechte vorbehalten.</p>
+ </div>
+ </div>
+ </footer>
+
+ <!-- JavaScript -->
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
+ <script>
+ // Muskelgruppen laden
+ async function loadMuscleGroups() {
+ try {
+ const response = await fetch('/api/muscles/groups');
+ if (response.ok) {
+ const muscleGroups = await response.json();
+ displayMuscleGroups(muscleGroups);
+ }
+ } catch (error) {
+ console.error('Error loading muscle groups:', error);
+ }
+ }
+
+ function displayMuscleGroups(muscleGroups) {
+ const container = document.getElementById('muscleGroupsContainer');
+ const muscleGroupNames = {
+ 'Arms': 'Oberarme',
+ 'Shoulders': 'Schultern',
+ 'Back': 'Rücken',
+ 'Chest': 'Brust',
+ 'Core': 'Rumpf',
+ 'Hips': 'Hüfte',
+ 'Legs': 'Beine',
+ 'Calves': 'Waden'
+ };
+
+ const icons = {
+ 'Arms': 'fas fa-hand-fist',
+ 'Shoulders': 'fas fa-arrows-alt-h',
+ 'Back': 'fas fa-archway',
+ 'Chest': 'fas fa-tshirt',
+ 'Core': 'fas fa-circle',
+ 'Hips': 'fas fa-hip',
+ 'Legs': 'fas fa-walking',
+ 'Calves': 'fas fa-shoe-prints'
+ };
+
+ muscleGroups.forEach(group => {
+ const col = document.createElement('div');
+ col.className = 'col-md-3 col-6 mb-3';
+ col.innerHTML = `
+ <div class="muscle-group-card">
+ <div>
+ <i class="${icons[group] || 'fas fa-dumbbell'} fa-2x mb-2"></i>
+ <h6 class="mb-0">${muscleGroupNames[group] || group}</h6>
+ </div>
+ </div>
+ `;
+ container.appendChild(col);
+ });
+ }
+
+ // Statistikdaten laden
+ async function loadStatistics() {
+ try {
+ const response = await fetch('/api/stats');
+ if (response.ok) {
+ const stats = await response.json();
+ updateStatistics(stats);
+ }
+ } catch (error) {
+ console.error('Error loading statistics:', error);
+ }
+ }
+
+ function updateStatistics(stats) {
+ if (stats.totalUsers) {
+ document.getElementById('totalUsers').textContent = stats.totalUsers.toLocaleString() + '+';
+ }
+ if (stats.totalWorkouts) {
+ document.getElementById('totalWorkouts').textContent = stats.totalWorkouts.toLocaleString() + '+';
+ }
+ if (stats.totalExercises) {
+ document.getElementById('totalExercises').textContent = stats.totalExercises + '+';
+ }
+ }
+
+ // Smooth Scroll für Navigation
+ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
+ anchor.addEventListener('click', function (e) {
+ e.preventDefault();
+ const target = document.querySelector(this.getAttribute('href'));
+ if (target) {
+ target.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start'
+ });
+ }
+ });
+ });
+
+ // Initialisierung
+ document.addEventListener('DOMContentLoaded', function() {
+ loadMuscleGroups();
+ loadStatistics();
+ });
+ </script>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+/**
+ *
+ */
+
+document.addEventListener('DOMContentLoaded', function() {
+ const forms = document.querySelectorAll('.ajax-form');
+
+ forms.forEach(form => {
+ form.addEventListener('submit', async function(e) {
+ e.preventDefault();
+
+ const formData = new FormData(this);
+ const submitButton = this.querySelector('button[type="submit"]');
+ // Loading-State
+ submitButton.disabled = true;
+ submitButton.textContent = 'saving ...';
+
+ try {
+ const response = await fetch('save-data.php', {
+ method: 'POST',
+ body: formData,
+ credentials: 'include', // Cookies mitsenden
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest'
+ }
+ });
+
+ const result = await response.json();
+
+ if (result.success) {
+ showMessage('Data saved successfully!', 'success');
+ this.reset(); // Formular zurücksetzen
+ } else {
+ showMessage('Error: ' + result.message, 'error');
+ }
+
+ } catch (error) {
+ showMessage('Network error: ' + error.message, 'error');
+ } finally {
+ // Button zurücksetzen
+ submitButton.disabled = false;
+ submitButton.textContent = 'Save';
+ }
+ });
+ });
+
+ function showMessage(text, type) {
+ const messageDiv = document.getElementById('responseMessage');
+ messageDiv.textContent = text;
+ messageDiv.className = type;
+ messageDiv.style.display = 'block';
+
+ // Nachricht nach 5 Sekunden ausblenden
+ setTimeout(() => {
+ messageDiv.style.display = 'none';
+ }, 5000);
+ }
+});
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html lang="de">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Login - Athletik Training</title>
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
+ <link rel="stylesheet" href="css/athletik.css">
+ <style>
+ .login-container {
+ min-height: 100vh;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20px;
+ }
+ .login-card {
+ background: white;
+ border-radius: 20px;
+ box-shadow: 0 15px 35px rgba(0,0,0,0.1);
+ width: 100%;
+ max-width: 400px;
+ overflow: hidden;
+ }
+ .login-header {
+ background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%);
+ color: white;
+ text-align: center;
+ padding: 30px 20px;
+ }
+ .login-body {
+ padding: 30px;
+ }
+ .form-control {
+ border-radius: 10px;
+ padding: 12px 20px;
+ border: 2px solid #e9ecef;
+ transition: all 0.3s ease;
+ }
+ .form-control:focus {
+ border-color: #667eea;
+ box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
+ }
+ .btn-login {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border: none;
+ border-radius: 10px;
+ padding: 12px;
+ color: white;
+ font-weight: 600;
+ transition: all 0.3s ease;
+ }
+ .btn-login:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
+ }
+ .social-login {
+ display: flex;
+ gap: 10px;
+ margin: 20px 0;
+ }
+ .btn-social {
+ flex: 1;
+ border-radius: 8px;
+ padding: 10px;
+ text-align: center;
+ border: 1px solid #dee2e6;
+ transition: all 0.3s ease;
+ }
+ .btn-social:hover {
+ transform: translateY(-1px);
+ }
+ .register-link {
+ color: #667eea;
+ text-decoration: none;
+ font-weight: 600;
+ }
+ .register-link:hover {
+ text-decoration: underline;
+ }
+ .password-toggle {
+ cursor: pointer;
+ position: absolute;
+ right: 15px;
+ top: 50%;
+ transform: translateY(-50%);
+ color: #6c757d;
+ }
+ .input-group {
+ position: relative;
+ }
+ .alert {
+ border-radius: 10px;
+ border: none;
+ }
+ @media (max-width: 576px) {
+ .login-container {
+ padding: 10px;
+ }
+ .login-body {
+ padding: 20px;
+ }
+ }
+ </style>
+</head>
+<body>
+ <div class="login-container">
+ <div class="login-card">
+ <!-- Header -->
+ <div class="login-header">
+ <i class="fas fa-dumbbell fa-3x mb-3"></i>
+ <h3 class="mb-1">Athletik Training</h3>
+ <p class="mb-0">Willkommen zurück</p>
+ </div>
+
+ <!-- Body -->
+ <div class="login-body">
+ <!-- Login Form -->
+ <form id="loginForm" style="display: block;">
+ <div class="alert alert-danger" id="loginError" style="display: none;">
+ <i class="fas fa-exclamation-circle me-2"></i>
+ <span id="errorMessage"></span>
+ </div>
+
+ <div class="mb-3">
+ <label for="username" class="form-label">Benutzername</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-user"></i>
+ </span>
+ <input type="text" class="form-control" id="username" placeholder="Dein Benutzername" required>
+ </div>
+ </div>
+
+ <div class="mb-3">
+ <label for="password" class="form-label">Passwort</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-lock"></i>
+ </span>
+ <input type="password" class="form-control" id="password" placeholder="Dein Passwort" required>
+ <span class="password-toggle" onclick="togglePassword()">
+ <i class="fas fa-eye"></i>
+ </span>
+ </div>
+ </div>
+
+ <div class="mb-3 form-check">
+ <input type="checkbox" class="form-check-input" id="rememberMe">
+ <label class="form-check-label" for="rememberMe">Eingeloggt bleiben</label>
+ <a href="#forgot-password" class="float-end text-decoration-none" onclick="showForgotPassword()">
+ Passwort vergessen?
+ </a>
+ </div>
+
+ <button type="submit" class="btn btn-login w-100 mb-3">
+ <i class="fas fa-sign-in-alt me-2"></i>Anmelden
+ </button>
+
+ <div class="text-center">
+ <p class="mb-0">Noch keinen Account?
+ <a href="#" class="register-link" onclick="showRegister()">Jetzt registrieren</a>
+ </p>
+ </div>
+ </form>
+
+ <!-- Register Form -->
+ <form id="registerForm" style="display: none;">
+ <div class="alert alert-danger" id="registerError" style="display: none;">
+ <i class="fas fa-exclamation-circle me-2"></i>
+ <span id="registerErrorMessage"></span>
+ </div>
+
+ <div class="mb-3">
+ <label for="regUsername" class="form-label">Benutzername</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-user"></i>
+ </span>
+ <input type="text" class="form-control" id="regUsername" placeholder="Wähle einen Benutzernamen" required>
+ </div>
+ </div>
+
+ <div class="mb-3">
+ <label for="regFullname" class="form-label">Vollständiger Name</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-id-card"></i>
+ </span>
+ <input type="text" class="form-control" id="regFullname" placeholder="Vor- und Nachname" required>
+ </div>
+ </div>
+
+ <div class="mb-3">
+ <label for="regEmail" class="form-label">E-Mail Adresse</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-envelope"></i>
+ </span>
+ <input type="email" class="form-control" id="regEmail" placeholder="deine@email.de" required>
+ </div>
+ </div>
+
+ <div class="mb-3">
+ <label for="regPassword" class="form-label">Passwort</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-lock"></i>
+ </span>
+ <input type="password" class="form-control" id="regPassword" placeholder="Sicheres Passwort" required>
+ <span class="password-toggle" onclick="toggleRegisterPassword()">
+ <i class="fas fa-eye"></i>
+ </span>
+ </div>
+ <div class="form-text">Mindestens 8 Zeichen, Groß-/Kleinbuchstaben und Zahlen</div>
+ </div>
+
+ <div class="mb-3">
+ <label for="regPasswordConfirm" class="form-label">Passwort bestätigen</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-lock"></i>
+ </span>
+ <input type="password" class="form-control" id="regPasswordConfirm" placeholder="Passwort wiederholen" required>
+ </div>
+ </div>
+
+ <div class="mb-3 form-check">
+ <input type="checkbox" class="form-check-input" id="acceptTerms" required>
+ <label class="form-check-label" for="acceptTerms">
+ Ich akzeptiere die <a href="#" class="text-decoration-none">AGB</a> und
+ <a href="#" class="text-decoration-none">Datenschutzbestimmungen</a>
+ </label>
+ </div>
+
+ <button type="submit" class="btn btn-login w-100 mb-3">
+ <i class="fas fa-user-plus me-2"></i>Registrieren
+ </button>
+
+ <div class="text-center">
+ <p class="mb-0">Bereits Account?
+ <a href="#" class="register-link" onclick="showLogin()">Zum Login</a>
+ </p>
+ </div>
+ </form>
+
+ <!-- Forgot Password Form -->
+ <form id="forgotPasswordForm" style="display: none;">
+ <div class="alert alert-info">
+ <i class="fas fa-info-circle me-2"></i>
+ Gib deine E-Mail Adresse ein, um ein neues Passwort anzufordern.
+ </div>
+
+ <div class="mb-3">
+ <label for="forgotEmail" class="form-label">E-Mail Adresse</label>
+ <div class="input-group">
+ <span class="input-group-text">
+ <i class="fas fa-envelope"></i>
+ </span>
+ <input type="email" class="form-control" id="forgotEmail" placeholder="deine@email.de" required>
+ </div>
+ </div>
+
+ <button type="submit" class="btn btn-login w-100 mb-3">
+ <i class="fas fa-paper-plane me-2"></i>Passwort anfordern
+ </button>
+
+ <div class="text-center">
+ <a href="#" class="register-link" onclick="showLogin()">
+ <i class="fas fa-arrow-left me-1"></i>Zurück zum Login
+ </a>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
+ <script>
+ // Formular-Wechsel
+ function showRegister() {
+ document.getElementById('loginForm').style.display = 'none';
+ document.getElementById('registerForm').style.display = 'block';
+ document.getElementById('forgotPasswordForm').style.display = 'none';
+ resetErrors();
+ }
+
+ function showLogin() {
+ document.getElementById('loginForm').style.display = 'block';
+ document.getElementById('registerForm').style.display = 'none';
+ document.getElementById('forgotPasswordForm').style.display = 'none';
+ resetErrors();
+ }
+
+ function showForgotPassword() {
+ document.getElementById('loginForm').style.display = 'none';
+ document.getElementById('registerForm').style.display = 'none';
+ document.getElementById('forgotPasswordForm').style.display = 'block';
+ resetErrors();
+ }
+
+ function resetErrors() {
+ document.getElementById('loginError').style.display = 'none';
+ document.getElementById('registerError').style.display = 'none';
+ }
+
+ // Password Toggle
+ function togglePassword() {
+ const passwordInput = document.getElementById('password');
+ const toggleIcon = document.querySelector('.password-toggle i');
+
+ if (passwordInput.type === 'password') {
+ passwordInput.type = 'text';
+ toggleIcon.className = 'fas fa-eye-slash';
+ } else {
+ passwordInput.type = 'password';
+ toggleIcon.className = 'fas fa-eye';
+ }
+ }
+
+ function toggleRegisterPassword() {
+ const passwordInput = document.getElementById('regPassword');
+ const toggleIcon = document.querySelector('#registerForm .password-toggle i');
+
+ if (passwordInput.type === 'password') {
+ passwordInput.type = 'text';
+ toggleIcon.className = 'fas fa-eye-slash';
+ } else {
+ passwordInput.type = 'password';
+ toggleIcon.className = 'fas fa-eye';
+ }
+ }
+
+ // Login Form Submission
+ document.getElementById('loginForm').addEventListener('submit', async function(e) {
+ e.preventDefault();
+
+ const username = document.getElementById('username').value;
+ const password = document.getElementById('password').value;
+ const rememberMe = document.getElementById('rememberMe').checked;
+
+ try {
+ const response = await fetch('/api/auth/login', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&remember-me=${rememberMe}`
+ });
+
+ if (response.ok) {
+ window.location.href = '/training';
+ } else {
+ const error = await response.text();
+ showLoginError(error);
+ }
+ } catch (error) {
+ showLoginError('Netzwerkfehler. Bitte versuche es später erneut.');
+ }
+ });
+
+ // Register Form Submission
+ document.getElementById('registerForm').addEventListener('submit', async function(e) {
+ e.preventDefault();
+
+ if (!validateRegistration()) {
+ return;
+ }
+
+ const userData = {
+ username: document.getElementById('regUsername').value,
+ fullname: document.getElementById('regFullname').value,
+ email: document.getElementById('regEmail').value,
+ pass: document.getElementById('regPassword').value
+ };
+
+ try {
+ const response = await fetch('/api/auth/register', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(userData)
+ });
+
+ if (response.ok) {
+ const user = await response.json();
+ showRegisterSuccess();
+ } else {
+ const error = await response.text();
+ showRegisterError(error);
+ }
+ } catch (error) {
+ showRegisterError('Netzwerkfehler. Bitte versuche es später erneut.');
+ }
+ });
+
+ // Forgot Password Form Submission
+ document.getElementById('forgotPasswordForm').addEventListener('submit', async function(e) {
+ e.preventDefault();
+
+ const email = document.getElementById('forgotEmail').value;
+
+ try {
+ const response = await fetch('/api/auth/forgot-password', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ email: email })
+ });
+
+ if (response.ok) {
+ alert('Eine E-Mail mit weiteren Anweisungen wurde gesendet.');
+ showLogin();
+ } else {
+ alert('Fehler beim Senden der E-Mail. Bitte überprüfe deine E-Mail Adresse.');
+ }
+ } catch (error) {
+ alert('Netzwerkfehler. Bitte versuche es später erneut.');
+ }
+ });
+
+ // Validation Functions
+ function validateRegistration() {
+ const password = document.getElementById('regPassword').value;
+ const passwordConfirm = document.getElementById('regPasswordConfirm').value;
+
+ if (password !== passwordConfirm) {
+ showRegisterError('Passwörter stimmen nicht überein');
+ return false;
+ }
+
+ if (password.length < 8) {
+ showRegisterError('Passwort muss mindestens 8 Zeichen lang sein');
+ return false;
+ }
+
+ if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(password)) {
+ showRegisterError('Passwort muss Groß- und Kleinbuchstaben sowie Zahlen enthalten');
+ return false;
+ }
+
+ return true;
+ }
+
+ function showLoginError(message) {
+ const errorDiv = document.getElementById('loginError');
+ const errorMessage = document.getElementById('errorMessage');
+
+ errorMessage.textContent = message;
+ errorDiv.style.display = 'block';
+ }
+
+ function showRegisterError(message) {
+ const errorDiv = document.getElementById('registerError');
+ const errorMessage = document.getElementById('registerErrorMessage');
+
+ errorMessage.textContent = message;
+ errorDiv.style.display = 'block';
+ }
+
+ function showRegisterSuccess() {
+ alert('Registrierung erfolgreich! Du kannst dich jetzt einloggen.');
+ showLogin();
+ }
+
+ // URL Parameter auswerten (für direkte Registrierung)
+ document.addEventListener('DOMContentLoaded', function() {
+ const urlParams = new URLSearchParams(window.location.search);
+ if (urlParams.get('register') === 'true') {
+ showRegister();
+ }
+ });
+ </script>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+@charset "UTF-8";
+
+BODY {
+ font-family: sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
+ 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
+ 'Helvetica Neue';
+ line-height: 1.5;
+ font-size: 1rem;
+ margin: 0;
+}
+
+HEADER, SECTION {
+ margin-left: 15em;
+ padding: 0 0 0 1rem;
+}
+
+NAV {
+ background: #f0f0f0;
+ height: 100%;
+ position: fixed;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ width: 15em;
+ overflow-x: hidden;
+}
+
+OL {
+ margin: 1.25em 0;
+}
+
+UL.navbar {
+ list-style-type: none;
+}
+
+.navbar li a {
+ text-decoration: none;
+ color: #333;
+ padding: 0.5rem 1rem;
+ display: block;
+ font-size: 2em;
+}
+
+.navbar li a:active, .navbar li a:hover {
+ background: #ddd;
+ transition: background 0.2s ease;
+}
+
+P.muscle {
+ border-top: 0.2em solid black;
+ padding: 0.25em 0 0 0;
+}
+
+P.start {
+ font-size: 1.25rem;
+ padding: 0 0 1.5em 0;
+}
+
+LI, P {
+ font-size: 1rem;
+}
+
+A {
+ text-decoration: none;
+}
+
+.musclename {
+ font-weight: 600;
+ color: #933;
+ background-color: #ddd;
+ padding: 0.5em;
+}
+
+.important {
+ font-weight: 600;
+ color: red;
+}
+
+.fa {
+ font-size: 1.5em;
+}
+
+H1 {
+ text-align: center;
+ font-size: 4.5em;
+}
+
+H2 {
+ text-align: center;
+ font-size: 3em;
+ text-decoration: underline overline;
+}
+
+.totop {
+ background-color: #666;
+ color: #ccc;
+ padding: 0.5em 2em;
+}
+
+.totop A {
+ color: #ccc;
+ font-size: 0.75em;
+}
+
+.hidden { display: none; }
+.success {
+ background: #d4edda;
+ color: #155724;
+ padding: 10px;
+ margin: 10px 0;
+ border: 1px solid #c3e6cb;
+}
+.error {
+ background: #f8d7da;
+ color: #721c24;
+ padding: 10px;
+ margin: 10px 0;
+ border: 1px solid #f5c6cb;
+}
+
+button:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
\ No newline at end of file
--- /dev/null
+/* Zusätzliche Styles für die Training-Seite */
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .training-container {
+ padding: 10px;
+ }
+
+ .stats-card {
+ margin-bottom: 15px;
+ }
+
+ .exercise-card {
+ margin-bottom: 20px;
+ }
+}
+
+/* Animationen */
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(20px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+.exercise-card {
+ animation: fadeIn 0.5s ease;
+}
+
+/* Progress Bars */
+.progress {
+ height: 8px;
+ border-radius: 4px;
+}
+
+.progress-bar {
+ transition: width 0.3s ease;
+}
+
+/* Custom Scrollbar */
+.training-history::-webkit-scrollbar {
+ width: 6px;
+}
+
+.training-history::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 3px;
+}
+
+.training-history::-webkit-scrollbar-thumb {
+ background: #888;
+ border-radius: 3px;
+}
+
+.training-history::-webkit-scrollbar-thumb:hover {
+ background: #555;
+}
+
+/* Hover Effects */
+.btn:hover {
+ transform: translateY(-1px);
+ transition: transform 0.2s ease;
+}
+
+/* Loading States */
+.loading {
+ opacity: 0.6;
+ pointer-events: none;
+}
+
+/* Notification System */
+.notification {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ padding: 15px 20px;
+ border-radius: 8px;
+ color: white;
+ z-index: 1000;
+ animation: slideIn 0.3s ease;
+}
+
+.notification.success {
+ background: #28a745;
+}
+
+.notification.error {
+ background: #dc3545;
+}
+
+@keyframes slideIn {
+ from { transform: translateX(100%); opacity: 0; }
+ to { transform: translateX(0); opacity: 1; }
+}
\ No newline at end of file
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.triathlon-coaching.product</groupId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
- <name>${product.artifactId}</name>
+ <name>${project.artifactId}</name>
<description>Athletik Training</description>
<modules>
<module>athletik-web</module>
<module>athletik-db</module>
+ <module>athletik-service</module>
+ <module>athletik-webapp</module>
</modules>
+ <properties>
+ <java.version>17</java.version>
+
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+<!-- Plugin Versions-->
+ <maven.compiler.source>${java.version}</maven.compiler.source>
+ <maven.compiler.target>${java.version}</maven.compiler.target>
+
+ <maven-enforcer-plugin.version>3.3.0</maven-enforcer-plugin.version>
+
+ <maven-source-plugin.version>3.2.1</maven-source-plugin.version>
+ <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
+ <maven-surefire-plugin.version>3.0.0</maven-surefire-plugin.version>
+
+ <maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
+ <maven-war-plugin.version>3.3.2</maven-war-plugin.version>
+ <maven-ear-plugin.version>3.3.0</maven-ear-plugin.version>
+ <maven-assembly-plugin.version>3.5.0</maven-assembly-plugin.version>
+ <maven-dependency-plugin.version>3.5.0</maven-dependency-plugin.version>
+
+ <maven-release-plugin.version>3.0.0</maven-release-plugin.version>
+ <maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
+ <maven-javadoc-plugin.version>3.5.0</maven-javadoc-plugin.version>
+ <maven-site-plugin.version>4.0.0-M6</maven-site-plugin.version>
+
+ <!-- Versions -->
+
+ <junit.version>4.13.2</junit.version>
+
+ <tomcat7-maven-plugin.version>2.2</tomcat7-maven-plugin.version>
+ <utillib.version>2.1.0</utillib.version>
+
+
+ <spring-boot.version>2.7.0</spring-boot.version>
+ <hibernate.version>5.6.9.Final</hibernate.version>
+ <postgresql.version>42.3.6</postgresql.version>
+ <thymeleaf.version>3.0.15.RELEASE</thymeleaf.version>
+ <hibernate-core.version>5.6.0.Final</hibernate-core.version>
+ <javax.mail.version>1.6.2</javax.mail.version>
+ <springframework.version>5.3.16</springframework.version>
+ <lombok.version>1.18.40</lombok.version>
+ <javax.servlet-api.version>4.0.1</javax.servlet-api.version>
+
+ <javadoc.opts>-Xdoclint:none</javadoc.opts>
+
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+
+ </dependencies>
+
+
<scm>
<connection>scm:git:ssh://laktatnebel.de/srv/git/swim.git</connection>
<developerConnection>scm:git:ssh://laktatnebel.de/srv/git/swim.git</developerConnection>