diff --git a/.gitea/labeler.yml b/.gitea/labeler.yml index 7cdb157..b5946ea 100644 --- a/.gitea/labeler.yml +++ b/.gitea/labeler.yml @@ -16,4 +16,5 @@ ci: docs: - changed-files: - any-glob-to-any-file: - - "docs/**" \ No newline at end of file + - "projektdokumentation/**" + diff --git a/.gitea/workflows/docs.yml b/.gitea/workflows/docs.yml index d54a4b5..88f13ae 100644 --- a/.gitea/workflows/docs.yml +++ b/.gitea/workflows/docs.yml @@ -1,6 +1,7 @@ name: Build docs on: + pull_request: push: branches: [main] @@ -11,18 +12,18 @@ jobs: image: git.kjan.de/actions/runner-latex:latest env: # Edit here with the names of your latex file and directory (can use ".") - DIR: docs - FILE: projektdokumentation.tex + DIR: projektdokumentation + FILE: Projektdokumentation.tex steps: - name: Checkout uses: actions/checkout@v4 - name: LaTeX compile working-directory: ${{ env.DIR }} - run: latexmk -pdf -xelatex ${{ env.FILE }} + run: latexmk -pdf ${{ env.FILE }} - name: Upload artifacts uses: https://git.kjan.de/actions/upload-artifact@v3 # Do not upgrade with: name: Doku - path: docs/projektdokumentation.pdf + path: projektdokumentation/Projektdokumentation.pdf diff --git a/docs/projektdokumentation.tex b/docs/projektdokumentation.tex deleted file mode 100644 index 4d045f4..0000000 --- a/docs/projektdokumentation.tex +++ /dev/null @@ -1,1351 +0,0 @@ -\documentclass[12pt,a4paper]{report} -\usepackage[ngerman]{babel} -\usepackage[utf8]{inputenc} -\usepackage[T1]{fontenc} -\usepackage{geometry} -\usepackage{graphicx} -\usepackage{hyperref} -\usepackage{listings} -\usepackage{xcolor} -\usepackage{float} -\usepackage{caption} -\usepackage{subcaption} -\usepackage{longtable} -\usepackage{pifont} -\usepackage{booktabs} -\usepackage{fancyhdr} -\usepackage{tocloft} -\usepackage{dirtree} -\usepackage{enumitem} -\usepackage{tikz} -\usetikzlibrary{arrows.meta, positioning} - -% Seitenränder -\geometry{ - left=2.5cm, - right=2.5cm, - top=2.5cm, - bottom=2.5cm -} - -% Kopf- und Fußzeile -\pagestyle{fancy} -\fancyhf{} -\fancyhead[L]{\leftmark} -\fancyhead[R]{\thepage} -\renewcommand{\headrulewidth}{0.4pt} - -% Code-Highlighting -\definecolor{codegreen}{rgb}{0,0.6,0} -\definecolor{codegray}{rgb}{0.5,0.5,0.5} -\definecolor{codepurple}{rgb}{0.58,0,0.82} -\definecolor{backcolour}{rgb}{0.95,0.95,0.92} - -\lstdefinestyle{mystyle}{ - backgroundcolor=\color{backcolour}, - commentstyle=\color{codegreen}, - keywordstyle=\color{magenta}, - numberstyle=\tiny\color{codegray}, - stringstyle=\color{codepurple}, - basicstyle=\ttfamily\footnotesize, - breakatwhitespace=false, - breaklines=true, - captionpos=b, - keepspaces=true, - numbers=left, - numbersep=5pt, - showspaces=false, - showstringspaces=false, - showtabs=false, - tabsize=2 -} - -\lstset{style=mystyle} - -% Hyperref-Einstellungen -\hypersetup{ - colorlinks=true, - linkcolor=black, - filecolor=magenta, - urlcolor=blue, -} - -\begin{document} - -% Titelseite -\begin{titlepage} - \centering - \vspace*{2cm} - - {\Huge\bfseries Casino Gaming Platform\par} - \vspace{1.5cm} - {\Large\itshape Projektdokumentation für die IHK-Abschlussprüfung\par} - \vspace{2cm} - {\large\bfseries Fachinformatiker für Anwendungsentwicklung\par} - - \vfill - - {\large - \begin{tabular}{ll} - \textbf{Prüfling:} & [Name des Prüflings] \\ - \textbf{Prüflingsnummer:} & [Prüflingsnummer] \\ - \textbf{Ausbildungsbetrieb:} & Hitec GmbH \\ - \textbf{Projektbetreuer:} & [Betreuer] \\ - \textbf{Projektdauer:} & 70 Stunden \\ - \textbf{Abgabedatum:} & \today \\ - \end{tabular} - \par} - - \vfill -\end{titlepage} - -% Inhaltsverzeichnis -\pagenumbering{roman} -\tableofcontents -\cleardoublepage -\pagenumbering{arabic} - -% Hauptinhalt -\chapter{Beschreibung} - -\section{Umfeld} -Das Projekt wurde im Rahmen der Abschlussprüfung zum Fachinformatiker für Anwendungsentwicklung bei der Hitec GmbH entwickelt. - -\subsection{Produktportfolio der Hitec GmbH} -Die Hitec GmbH ist ein innovatives IT-Unternehmen, das sich auf die Entwicklung moderner Webanwendungen und digitaler Lösungen spezialisiert hat. Das Unternehmen deckt ein breites Spektrum an Technologien ab, von klassischen Enterprise-Anwendungen bis hin zu modernen Cloud-nativen Lösungen. - -\subsection{Weg zur Produktidee} -Die Casino Gaming Platform entstand als LF08 Projekt mit dem Ziel, eine vollständige Online-Casino-Plattform zu entwickeln. Die Produktidee basiert auf: - -\begin{itemize} - \item \textbf{Gamification-Trend:} Wachsende Nachfrage nach Online-Gaming-Plattformen - \item \textbf{Technologie-Demonstration:} Showcase moderner Full-Stack-Entwicklung (Angular 20 + Spring Boot 3.5) - \item \textbf{Bildungsziel:} Praktische Anwendung von Enterprise-Patterns und modernen Web-Technologien - \item \textbf{Marktforschung:} Integration aktueller Standards (OAuth2, Stripe, responsive Design) -\end{itemize} - -\section{Ziel} -Das Ziel dieses Projektes ist die Entwicklung eines Online-Casinos, welches verschiedene Spiele anbietet, um mit Echtgeld zu wetten. Dabei verzichten wir auf eine Auszahlungsmöglichkeit, um Einnahmen zu steigern und rechtliche Komplexitäten zu vermeiden. - -Die Plattform soll es Benutzern ermöglichen: -\begin{itemize} - \item Mit virtueller Währung verschiedene Casino-Spiele zu spielen - \item Sichere Einzahlungen über moderne Payment-Provider zu tätigen - \item Eine intuitive und responsive Benutzeroberfläche zu nutzen - \item Transparente Transaktionshistorien einzusehen -\end{itemize} - -\chapter{Vorbereitung} - -\section{Ist-Analyse} -Detaillierte Beschreibung des Problems oder der Marktlücke, welche unser Produkt lösen/füllen soll. - -\subsection{Identifizierte Marktlücken} -\begin{enumerate} - \item \textbf{Technische Komplexität:} Viele Casino-Plattformen nutzen veraltete Technologien - \item \textbf{Benutzerfreundlichkeit:} Schlechte mobile Erfahrung und komplexe Registrierung - \item \textbf{Sicherheitsstandards:} Mangelnde OAuth2-Integration und moderne Authentifizierung - \item \textbf{Payment-Integration:} Umständliche Einzahlungsprozesse ohne moderne Payment-APIs - \item \textbf{Transparenz:} Fehlende Nachvollziehbarkeit von Transaktionen und Spielverläufen -\end{enumerate} - -\section{Soll-Analyse} -\subsection{Spieleportfolio} -\begin{itemize} - \item Blackjack (mit Split/Double Down) - \item Slots mit konfigurierbarer RTP - \item Dice, Coinflip, Lootboxes - \item Geplant: Poker, Plinko -\end{itemize} - -\subsection{Benutzerverwaltung} -\begin{itemize} - \item Multi-Provider OAuth2 (GitHub, Google) - \item JWT-basierte Authentifizierung - \item E-Mail-Verifizierung und Passwort-Reset -\end{itemize} - -\subsection{Finanzsystem} -\begin{itemize} - \item Stripe-Integration für Einzahlungen - \item Virtuelle Währung mit Präzisions-Tracking (BigDecimal) - \item Transaktionshistorie mit Status-Tracking -\end{itemize} - -\subsection{Technische Anforderungen} -\begin{itemize} - \item Responsive Design (Mobile-First) - \item Real-time Updates ohne Page-Reload - \item Sichere API-Kommunikation -\end{itemize} - -\chapter{Durchführung} - -\section{Vorgehensweise} -Für die Projektdurchführung wurde Scrum als Vorgehensmodell gewählt. Dadurch wird am Anfang des Projektes und eines Sprints festgelegt, was gemacht werden soll, und jeder ist auf dem gleichen Wissensstand. Des Weiteren gibt es tägliche Updates vom Fortschritt, Probleme können schnell erkannt und angesprochen werden. Dazu kann man auch neue Anforderungen flexibel mit einbringen. - -\subsection{Verwendete Tools und Methoden} -\begin{itemize} - \item \textbf{Scrum:} Agile Projektmanagement-Methodik - \item \textbf{Jira:} Ticketing und Sprint-Planning - \item \textbf{Git:} Versionskontrolle mit Feature-Branch-Workflow - \item \textbf{CI/CD:} Automatisierte Build- und Deployment-Pipelines -\end{itemize} - -\section{Umsetzung} - -\subsection{Art der Datenhaltung} -PostgreSQL mit JPA/Hibernate ORM wurde als Datenbanklösung gewählt: -\begin{itemize} - \item \textbf{Verbindung:} JDBC mit Connection Pooling (HikariCP) - \item \textbf{Schema:} Domain-driven Design mit klarer Trennung - \item \textbf{Transaktionen:} @Transactional Boundaries für Konsistenz - \item \textbf{Migration:} Flyway für Datenbank-Versionierung -\end{itemize} - -\subsection{Klassenmodell} - -\subsubsection{Backend (Java)} -\dirtree{% -.1 Entity Layer. -.2 UserEntity. -.2 BlackJackGameEntity. -.2 TransactionEntity. -.2 LootBoxEntity. -.1 Repository Layer. -.2 Spring Data JPA. -.1 Service Layer. -.2 Business Logic. -.3 BlackJackService. -.3 BalanceService. -.3 DepositService. -.1 Controller Layer. -.2 REST APIs. -.1 Security Layer. -.2 JWT + OAuth2. -} - -\subsubsection{Frontend (TypeScript)} -\dirtree{% -.1 Models. -.2 User interfaces. -.2 Game interfaces. -.2 Transaction interfaces. -.1 Services. -.2 HTTP client wrappers. -.1 Components. -.2 Angular standalone components. -.1 Guards. -.2 Route protection. -} - -\subsection{Design Pattern} -\begin{enumerate} - \item \textbf{MVC Pattern:} Controller → Service → Repository - \item \textbf{Repository Pattern:} Datenzugriff-Abstraktion - \item \textbf{DTO Pattern:} API-Grenze mit Datenkapselung - \item \textbf{Strategy Pattern:} OAuth2-Provider (GitHub/Google) - \item \textbf{Observer Pattern:} Angular Signals für reaktive Updates -\end{enumerate} - -\subsection{Zusammenarbeit der einzelnen Module} - -\subsubsection{Backend-Architektur} -\begin{verbatim} -Security Layer ← JWT Filter ← Controllers ← Services ← Repositories ← Database - ↓ -OAuth2 Integration (GitHub/Google) - ↓ -Payment Integration (Stripe Webhooks) -\end{verbatim} - -\subsubsection{Frontend-Architektur} -\begin{verbatim} -Guards → Components → Services → HTTP Interceptors → Backend APIs - ↓ -Angular Router → Lazy Loading → Feature Modules -\end{verbatim} - -\subsection{Systemarchitektur} -Die Casino Gaming Platform basiert auf einer modernen Microservice-Architektur mit klarer Trennung zwischen Frontend und Backend. - -\subsubsection{Gesamtarchitektur} -\begin{tikzpicture}[ - box/.style={rectangle, draw, minimum width=3cm, minimum height=1.5cm, align=center}, - ->, >=Stealth, node distance=2cm and 1.5cm -] - -% Top row -\node[box] (angular) {Angular\\Frontend}; -\node[box, right=of angular] (spring) {Spring Boot\\Backend}; -\node[box, right=of spring] (postgres) {PostgreSQL\\Database}; - -% Bottom row -\node[box, below=of angular] (keycloak) {Keycloak\\Auth Server}; -\node[box, below=of spring] (stripe) {Stripe API\\Payment}; - -% Arrows top row -\draw (angular) -- (spring); -\draw (spring) -- (postgres); - -% Arrows to bottom row -\draw (angular.south) -- (keycloak.north); -\draw (spring.south) -- (stripe.north); - -\end{tikzpicture} - -\subsubsection{Backend-Paketstruktur} -Das Backend folgt dem Domain-Driven Design (DDD) Ansatz: - -\dirtree{% -.1 de.szut.casino. -.2 blackjack. -.3 BlackjackController.java. -.3 BlackjackService.java. -.3 BlackjackEntity.java. -.2 coinflip. -.3 CoinflipController.java. -.3 CoinflipService.java. -.2 config. -.3 SecurityConfig.java. -.3 DatabaseConfig.java. -.2 deposit. -.3 DepositController.java. -.3 StripeService.java. -.2 dice. -.3 DiceController.java. -.3 DiceService.java. -.2 exceptionHandling. -.3 GlobalExceptionHandler.java. -.2 health. -.3 HealthController.java. -.2 lootboxes. -.3 LootBoxEntity.java. -.3 RewardEntity.java. -.2 security. -.3 JwtAuthenticationConverter.java. -.2 shared. -.3 BaseEntity.java. -.3 AuditingConfig.java. -.2 slots. -.3 SlotsController.java. -.3 SlotsService.java. -.2 user. -.3 UserEntity.java. -.3 UserService.java. -} - -\subsubsection{Frontend-Modulstruktur} -Das Frontend ist modular aufgebaut mit Feature-Modulen: - -\dirtree{% -.1 app/feature/. -.2 auth. -.3 login. -.3 oauth2. -.3 recover-password. -.3 register. -.3 verify-email. -.2 deposit. -.3 deposit.component.ts. -.3 payment.service.ts. -.2 game. -.3 blackjack. -.4 components. -.5 animated-number. -.5 dealer-hand. -.5 game-controls. -.5 game-info. -.5 game-result. -.5 player-hand. -.5 playing-card. -.4 enum. -.4 models. -.4 services. -.3 coinflip. -.4 models. -.3 dice. -.3 slots. -.2 home. -.2 landing. -.2 lootboxes. -.3 lootbox-opening. -.3 lootbox-selection. -.3 services. -.2 transaction-history. -} - -\subsection{Funktionsweise des Blackjack-Algorithmus} -Als Beispiel für die Spiellogik wird hier der Blackjack-Algorithmus beschrieben: - -\begin{enumerate} - \item \textbf{Spielstart:} Dealer teilt je 2 Karten an Spieler und sich selbst aus - \item \textbf{Kartenwerte:} Ass = 1 oder 11, Bildkarten = 10, andere = Nennwert - \item \textbf{Spielerzug:} Hit (weitere Karte) oder Stand (beenden) - \item \textbf{Dealerzug:} Automatisch bis Kartenwert $\geq$ 17 - \item \textbf{Gewinnermittlung:} Nächster zu 21 gewinnt, bei Gleichstand Unentschieden -\end{enumerate} - -\section{Technologie-Stack} - -\subsection{Frontend-Technologien} -\begin{itemize} - \item \textbf{Angular 20}: Modernes TypeScript-basiertes Web-Framework - \item \textbf{TailwindCSS}: Utility-First CSS-Framework - \item \textbf{RxJS}: Reactive Extensions für asynchrone Programmierung - \item \textbf{Keycloak JS}: JavaScript-Adapter für Keycloak-Integration - \item \textbf{Stripe.js}: Sichere Payment-Integration -\end{itemize} - -\subsection{Backend-Technologien} -\begin{itemize} - \item \textbf{Spring Boot}: Java-basiertes Backend-Framework - \item \textbf{Spring Security}: Sicherheitsframework - \item \textbf{Spring Data JPA}: Datenbankzugriff - \item \textbf{PostgreSQL}: Relationale Datenbank - \item \textbf{Gradle}: Build-Management-Tool -\end{itemize} - -\subsection{Infrastructure \& Tools} -\begin{itemize} - \item \textbf{Docker}: Containerisierung - \item \textbf{Docker Compose}: Multi-Container-Orchestrierung - \item \textbf{Keycloak}: Identity und Access Management - \item \textbf{Mailpit}: E-Mail-Testing in der Entwicklung - \item \textbf{Swagger/OpenAPI}: API-Dokumentation -\end{itemize} - -\chapter{Implementierung} - -\section{Backend-Implementierung} - -\subsection{Spring Boot Konfiguration} -Die Hauptanwendungsklasse initialisiert die Spring Boot-Anwendung und konfiguriert grundlegende Beans: - -\begin{lstlisting}[language=Java, caption=CasinoApplication.java] -@SpringBootApplication -public class CasinoApplication { - public static void main(String[] args) { - SpringApplication.run(CasinoApplication.class, args); - } - - @Bean - public static RestTemplate restTemplate() { - return new RestTemplate(); - } - - @Bean - public static JavaMailSenderImpl javaMailSenderImpl() { - return new JavaMailSenderImpl(); - } -} -\end{lstlisting} - -\subsection{Sicherheitskonfiguration} -Die Anwendung nutzt Keycloak für die Authentifizierung. Spring Security wird entsprechend konfiguriert: - -\begin{lstlisting}[language=Java, caption=Security Configuration] -@Configuration -@EnableWebSecurity -public class SecurityConfig { - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) { - return http - .authorizeHttpRequests(auth -> auth - .requestMatchers("/swagger/**").permitAll() - .requestMatchers("/health/**").permitAll() - .anyRequest().authenticated() - ) - .oauth2ResourceServer(oauth2 -> - oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter( - jwtAuthenticationConverter() - )) - ) - .build(); - } -} -\end{lstlisting} - -\subsection{Spieleimplementierung} -Jedes Spiel folgt einem einheitlichen Muster mit Controller, Service und Repository: - -\begin{lstlisting}[language=Java, caption=Beispiel: Blackjack Controller] -@RestController -@RequestMapping("/api/blackjack") -@RequiredArgsConstructor -public class BlackjackController { - private final BlackjackService blackjackService; - - @PostMapping("/start") - public ResponseEntity startGame() { - return ResponseEntity.ok( - blackjackService.startNewGame() - ); - } - - @PostMapping("/hit") - public ResponseEntity hit() { - return ResponseEntity.ok( - blackjackService.playerHit() - ); - } - - @PostMapping("/stand") - public ResponseEntity stand() { - return ResponseEntity.ok( - blackjackService.playerStand() - ); - } -} -\end{lstlisting} - -\section{Frontend-Implementierung} - -\subsection{Angular-Projektstruktur} -Das Frontend nutzt Angular's modulare Architektur mit Lazy Loading: - -\begin{lstlisting}[caption=App Routing Module] -const routes: Routes = [ - { - path: '', - loadChildren: () => import('./feature/landing/landing.module') - .then(m => m.LandingModule) - }, - { - path: 'games', - loadChildren: () => import('./feature/game/game.module') - .then(m => m.GameModule), - canActivate: [AuthGuard] - }, - { - path: 'deposit', - loadChildren: () => import('./feature/deposit/deposit.module') - .then(m => m.DepositModule), - canActivate: [AuthGuard] - } -]; -\end{lstlisting} - -\subsection{Komponenten-Implementierung} -Jede Spielkomponente folgt dem Angular-Standard mit TypeScript: - -\begin{lstlisting}[caption=Blackjack Component] -@Component({ - selector: 'app-blackjack', - templateUrl: './blackjack.component.html', - styleUrls: ['./blackjack.component.scss'] -}) -export class BlackjackComponent implements OnInit { - gameState$: Observable; - - constructor( - private blackjackService: BlackjackService, - private toastr: ToastrService - ) {} - - ngOnInit(): void { - this.gameState$ = this.blackjackService.getGameState(); - } - - startGame(): void { - this.blackjackService.startGame() - .subscribe({ - next: () => this.toastr.success('Spiel gestartet!'), - error: (err) => this.toastr.error('Fehler beim Starten') - }); - } -} -\end{lstlisting} - -\subsection{Service-Layer} -Services kapseln die Geschäftslogik und API-Kommunikation: - -\begin{lstlisting}[caption=Blackjack Service] -@Injectable({ - providedIn: 'root' -}) -export class BlackjackService { - private apiUrl = '/api/blackjack'; - private gameStateSubject = new BehaviorSubject(null); - - constructor(private http: HttpClient) {} - - startGame(): Observable { - return this.http.post(`${this.apiUrl}/start`, {}) - .pipe( - tap(state => this.gameStateSubject.next(state)), - catchError(this.handleError) - ); - } - - private handleError(error: HttpErrorResponse): Observable { - console.error('API Error:', error); - return throwError(() => error); - } -} -\end{lstlisting} - -\section{Datenbankdesign} - -\subsection{Entity-Relationship-Modell} -Die Datenbank verwendet folgende Hauptentitäten: - -\begin{lstlisting}[caption=Haupttabellen] --- Benutzer-Tabelle -CREATE TABLE users ( - id UUID PRIMARY KEY, - keycloak_id VARCHAR(255) UNIQUE NOT NULL, - balance DECIMAL(19, 2) DEFAULT 0.00, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Transaktions-Tabelle -CREATE TABLE transactions ( - id UUID PRIMARY KEY, - user_id UUID REFERENCES users(id), - amount DECIMAL(19, 2) NOT NULL, - type VARCHAR(50) NOT NULL, - description TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Spielverlauf-Tabelle -CREATE TABLE game_history ( - id UUID PRIMARY KEY, - user_id UUID REFERENCES users(id), - game_type VARCHAR(50) NOT NULL, - bet_amount DECIMAL(19, 2), - win_amount DECIMAL(19, 2), - played_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); -\end{lstlisting} - -\subsection{JPA-Entitäten} -Die Datenbankentitäten werden als JPA-Entities modelliert: - -\begin{lstlisting}[caption=User Entity] -@Entity -@Table(name = "users") -@Data -@NoArgsConstructor -@AllArgsConstructor -public class UserEntity { - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - - @Column(unique = true, nullable = false) - private String keycloakId; - - @Column(precision = 19, scale = 2) - private BigDecimal balance = BigDecimal.ZERO; - - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) - private List transactions; - - @CreationTimestamp - private LocalDateTime createdAt; - - @UpdateTimestamp - private LocalDateTime updatedAt; -} -\end{lstlisting} - -\chapter{Integration externer Dienste} - -\section{Keycloak-Integration} -Keycloak wird als zentraler Identity Provider verwendet: - -\subsection{Backend-Konfiguration} -\begin{lstlisting}[caption=application.yml] -spring: - security: - oauth2: - resourceserver: - jwt: - issuer-uri: http://localhost:8080/realms/casino - jwk-set-uri: http://localhost:8080/realms/casino/protocol/openid-connect/certs - -keycloak: - realm: casino - auth-server-url: http://localhost:8080 - ssl-required: external - resource: casino-backend - public-client: false - bearer-only: true -\end{lstlisting} - -\subsection{Frontend-Integration} -\begin{lstlisting}[caption=Keycloak Service] -@Injectable({ - providedIn: 'root' -}) -export class KeycloakService { - private keycloak: Keycloak; - - async init(): Promise { - this.keycloak = new Keycloak({ - url: 'http://localhost:8080', - realm: 'casino', - clientId: 'casino-frontend' - }); - - return await this.keycloak.init({ - onLoad: 'check-sso', - silentCheckSsoRedirectUri: - window.location.origin + '/assets/silent-check-sso.html' - }); - } -} -\end{lstlisting} - -\section{Stripe-Integration} -Stripe wird für sichere Zahlungsabwicklung verwendet: - -\subsection{Backend-Webhook} -\begin{lstlisting}[caption=Stripe Webhook Controller] -@RestController -@RequestMapping("/webhook") -public class StripeWebhookController { - @Value("${stripe.webhook.secret}") - private String webhookSecret; - - @PostMapping - public ResponseEntity handleWebhook( - @RequestBody String payload, - @RequestHeader("Stripe-Signature") String sigHeader - ) { - Event event = Webhook.constructEvent( - payload, sigHeader, webhookSecret - ); - - switch (event.getType()) { - case "payment_intent.succeeded": - handleSuccessfulPayment(event); - break; - case "payment_intent.payment_failed": - handleFailedPayment(event); - break; - } - - return ResponseEntity.ok("Received"); - } -} -\end{lstlisting} - -\subsection{Frontend-Integration} -\begin{lstlisting}[caption=Stripe Service] -@Injectable({ - providedIn: 'root' -}) -export class StripeService { - private stripe: Stripe; - - constructor() { - this.stripe = loadStripe(environment.stripePublicKey); - } - - async createPaymentIntent(amount: number): Observable { - return this.http.post('/api/deposits/create-intent', { - amount: amount * 100 // Cent-Betrag - }); - } -} -\end{lstlisting} - -\chapter{Qualitätssicherung} - -\section{CI/CD Setup} - -\subsection{Unit-Tests} -Jede Service-Klasse wird mit JUnit und Mockito getestet: - -\begin{lstlisting}[language=Java, caption=BlackjackService Test] -@ExtendWith(MockitoExtension.class) -class BlackjackServiceTest { - @Mock - private BlackjackRepository repository; - - @InjectMocks - private BlackjackService service; - - @Test - void testStartNewGame() { - // Given - when(repository.save(any())).thenReturn(new GameEntity()); - - // When - GameStateDto result = service.startNewGame(); - - // Then - assertNotNull(result); - assertEquals(2, result.getPlayerCards().size()); - assertEquals(2, result.getDealerCards().size()); - } -} -\end{lstlisting} - -\subsection{Integrationstests} -Spring Boot Test für API-Endpoints: - -\begin{lstlisting}[language=Java, caption=Integration Test] -@SpringBootTest -@AutoConfigureMockMvc -class BlackjackControllerIntegrationTest { - @Autowired - private MockMvc mockMvc; - - @Test - @WithMockUser - void testStartGameEndpoint() throws Exception { - mockMvc.perform(post("/api/blackjack/start") - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.playerCards").isArray()) - .andExpect(jsonPath("$.dealerCards").isArray()); - } -} -\end{lstlisting} - -\section{Frontend-Tests} - -\subsection{Komponenten-Tests} -Angular-Komponenten werden mit Jasmine und Karma getestet: - -\begin{lstlisting}[caption=Component Test] -describe('BlackjackComponent', () => { - let component: BlackjackComponent; - let fixture: ComponentFixture; - let mockService: jasmine.SpyObj; - - beforeEach(() => { - const spy = jasmine.createSpyObj('BlackjackService', - ['startGame', 'getGameState']); - - TestBed.configureTestingModule({ - declarations: [BlackjackComponent], - providers: [ - { provide: BlackjackService, useValue: spy } - ] - }); - - fixture = TestBed.createComponent(BlackjackComponent); - component = fixture.componentInstance; - mockService = TestBed.inject(BlackjackService) as any; - }); - - it('should start a new game', () => { - mockService.startGame.and.returnValue(of(mockGameState)); - - component.startGame(); - - expect(mockService.startGame).toHaveBeenCalled(); - }); -}); -\end{lstlisting} - -\subsection{E2E-Tests} -End-to-End-Tests mit Cypress: - -\begin{lstlisting}[caption=E2E Test] -describe('Blackjack Game', () => { - beforeEach(() => { - cy.login('testuser', 'password'); - cy.visit('/games/blackjack'); - }); - - it('should play a complete game', () => { - cy.get('[data-cy=start-game]').click(); - cy.get('[data-cy=player-cards]').should('be.visible'); - cy.get('[data-cy=dealer-cards]').should('be.visible'); - - cy.get('[data-cy=hit-button]').click(); - cy.get('[data-cy=player-cards]') - .children().should('have.length.greaterThan', 2); - - cy.get('[data-cy=stand-button]').click(); - cy.get('[data-cy=game-result]').should('be.visible'); - }); -}); -\end{lstlisting} - -\chapter{Wirtschaftliche Betrachtung} - -\section{Marktuntersuchung} - -\subsection{Zielgruppe} -\textbf{Welche Zielgruppe soll angesprochen werden?} - -\begin{itemize} - \item \textbf{Primäre Zielgruppe:} Technik-affine Nutzer (18-35 Jahre) - \item \textbf{Sekundäre Zielgruppe:} Gelegenheitsspieler mit Fokus auf Benutzerfreundlichkeit -\end{itemize} - -\subsection{Erwartungen der Zielgruppe} -\textbf{Welche Erwartungen hat die Zielgruppe an das Produkt?} - -Die Zielgruppe erwartet ein unterhaltsames, fesselndes und optisch ansprechendes Spielerlebnis, das klassische Casino-Atmosphäre simuliert. Sie legt Wert auf: - -\begin{itemize} - \item Intuitive Benutzeroberfläche - \item Schnelle Ladezeiten - \item Abwechslungsreiche Spiele (Slots, Blackjack, CoinFlip etc.) - \item Transparente Transaktionshistorie - \item Mobile Optimierung - \item Sichere Zahlungsabwicklung -\end{itemize} - -\subsection{Marktvolumen und Marktpotential} -\textbf{Wie hoch ist bei der Zielgruppe das Marktvolumen und das Marktpotential?} - -Der Markt für Social Casinos und Online-Casinos mit Auszahlungsverweigerung ist weltweit wachsend. Laut Branchenanalysen (z.B. Statista, Business Research Insights) liegt das Volumen des globalen Social-Casino-Markts bei mehreren Milliarden USD pro Jahr, mit jährlichen Wachstumsraten im hohen einstelligen Prozentbereich. - -In Zielmärkten wie den USA, Europa und Teilen Asiens ist das Potenzial besonders hoch, insbesondere bei Nutzern, die Glücksspiel aus rechtlichen oder moralischen Gründen meiden, aber den Spielspaß schätzen. - -\subsection{Absatzpotential} -\textbf{Wie hoch ist bei der Zielgruppe das Absatzpotential?} - -Das Absatzpotential ist aufgrund des digitalen Charakters des Produkts nahezu unbegrenzt skalierbar. Wichtige Faktoren: - -\begin{itemize} - \item Keine physischen Produktionslimits - \item Globale Erreichbarkeit über das Internet - \item Virale Marketing-Effekte durch Social Gaming - \item Wiederkehrende Umsätze durch Einzahlungsmodell -\end{itemize} - -\subsection{Wettbewerbssituation} -\textbf{Wie stellt sich die Wettbewerbssituation dar?} - -Der Markt ist stark umkämpft mit etablierten Playern wie: -\begin{itemize} - \item PokerStars Casino - \item Slotomania - \item House of Fun - \item Big Fish Casino -\end{itemize} - -\textbf{Konkurrenzvorteile unserer Lösung:} -\begin{itemize} - \item Moderne Technologie-Stack (Angular + Spring Boot) - \item DSGVO-konforme Entwicklung von Grund auf - \item Keine Auszahlungen = höhere Gewinnmargen - \item Responsive Design für alle Endgeräte - \item Open-Source-Ansatz für Community-Entwicklung -\end{itemize} - -\subsection{Risiken} -\textbf{Wo liegen Risiken?} - -\begin{itemize} - \item \textbf{Rechtliche Risiken:} Sich ändernde Glücksspielgesetze - \item \textbf{Technische Risiken:} Skalierungsprobleme bei hohen Nutzerzahlen - \item \textbf{Marktrisiken:} Marktsättigung im Social Gaming Bereich - \item \textbf{Sicherheitsrisiken:} Hacking-Versuche und Betrug -\end{itemize} - -\section{Marketingmix / absatzpolitische Maßnahmen} - -\subsection{Preispolitik} -\textbf{Für welchen Preis wird das Produkt angeboten?} - -Das Produkt folgt einem Freemium-Modell: -\begin{itemize} - \item \textbf{Grundspiel:} Kostenlos mit Startguthaben - \item \textbf{Einzahlungen:} Gestaffelte Pakete (5€, 10€, 25€, 50€, 100€) - \item \textbf{Premium-Features:} Erweiterte Statistiken (2,99€/Monat) -\end{itemize} - -\subsection{Kommunikationspolitik} -\textbf{Wie und wo soll das Produkt beworben werden?} - -\begin{itemize} - \item \textbf{Social Media Marketing:} Instagram, TikTok, YouTube - \item \textbf{Influencer Marketing:} Gaming-Streamer und Content-Creator - \item \textbf{SEO/SEM:} Google Ads für relevante Suchbegriffe - \item \textbf{App Store Optimization:} Bei zukünftiger Mobile App -\end{itemize} - -\subsection{Distributionspolitik} -\textbf{Wie gelangt das Produkt zum Nutzer?} - -\begin{itemize} - \item \textbf{Web-Browser:} Direkter Zugang über casino-platform.com - \item \textbf{Progressive Web App:} Installation als App möglich - \item \textbf{Zukünftig:} Native Apps für iOS und Android -\end{itemize} - -\subsection{Wirtschaftlichkeitsbetrachtung} -\textbf{Wo liegt die Gewinnschwelle?} - -Bei durchschnittlich 10€ Einzahlung pro aktivem Nutzer und 1000 aktiven Nutzern monatlich: -\begin{itemize} - \item \textbf{Monatlicher Umsatz:} 10.000€ - \item \textbf{Betriebskosten:} 3.000€ (Server, Support, Marketing) - \item \textbf{Break-Even:} Nach 6 Monaten bei stetigem Nutzerwachstum -\end{itemize} - -\chapter{Deployment und Betrieb} - -\section{Container-Konfiguration} -Die Anwendung wird mit Docker containerisiert: - -\subsection{Backend Dockerfile} -\begin{lstlisting}[caption=Backend Dockerfile] -FROM eclipse-temurin:17-jdk-alpine AS build -WORKDIR /app -COPY gradle gradle -COPY gradlew build.gradle.kts settings.gradle.kts ./ -RUN ./gradlew dependencies --no-daemon -COPY src src -RUN ./gradlew bootJar --no-daemon - -FROM eclipse-temurin:17-jre-alpine -WORKDIR /app -COPY --from=build /app/build/libs/*.jar app.jar -EXPOSE 8080 -ENTRYPOINT ["java", "-jar", "app.jar"] -\end{lstlisting} - -\subsection{Frontend Dockerfile} -\begin{lstlisting}[caption=Frontend Dockerfile] -FROM node:18-alpine AS build -WORKDIR /app -COPY package*.json ./ -RUN npm ci -COPY . . -RUN npm run build - -FROM nginx:alpine -COPY --from=build /app/dist/casino-frontend /usr/share/nginx/html -COPY nginx.conf /etc/nginx/nginx.conf -EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] -\end{lstlisting} - -\section{CI/CD-Pipeline} -Die Anwendung nutzt GitHub Actions für automatisierte Builds: - -\begin{lstlisting}[caption=GitHub Actions Workflow] -name: Build and Deploy - -on: - push: - branches: [main, develop] - pull_request: - branches: [main] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - - - name: Run Backend Tests - working-directory: ./backend - run: ./gradlew test - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '18' - - - name: Run Frontend Tests - working-directory: ./frontend - run: | - npm ci - npm run test:ci - - build: - needs: test - runs-on: ubuntu-latest - steps: - - name: Build Docker Images - run: | - docker build -t casino-backend ./backend - docker build -t casino-frontend ./frontend -\end{lstlisting} - -\section{Monitoring und Wartung} - -\subsection{Health Checks} -Spring Boot Actuator bietet Health-Endpoints: - -\begin{lstlisting}[language=Java, caption=Health Check Configuration] -@Component -public class DatabaseHealthIndicator implements HealthIndicator { - @Autowired - private DataSource dataSource; - - @Override - public Health health() { - try (Connection conn = dataSource.getConnection()) { - if (conn.isValid(1)) { - return Health.up() - .withDetail("database", "PostgreSQL") - .build(); - } - } catch (SQLException e) { - return Health.down() - .withException(e) - .build(); - } - return Health.down().build(); - } -} -\end{lstlisting} - -\subsection{Logging-Konfiguration} -Strukturiertes Logging mit SLF4J: - -\begin{lstlisting}[language=xml, caption=logback.xml] - - - - - %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n - - - - - - logs/casino.log - - logs/casino.%d{yyyy-MM-dd}.log - 30 - - - - %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - -\end{lstlisting} - -\chapter{Sicherheitskonzept} - -\section{Authentifizierung und Autorisierung} -Die Plattform implementiert ein mehrstufiges Sicherheitskonzept: - -\subsection{OAuth2/OpenID Connect} -Keycloak als Identity Provider bietet: -\begin{itemize} - \item Single Sign-On (SSO) - \item Multi-Factor Authentication (MFA) - \item Social Login (Google, GitHub) - \item Token-basierte Authentifizierung (JWT) -\end{itemize} - -\subsection{API-Sicherheit} -\begin{lstlisting}[language=Java, caption=Security Headers] -@Component -public class SecurityHeadersFilter implements Filter { - @Override - public void doFilter(ServletRequest request, - ServletResponse response, - FilterChain chain) { - HttpServletResponse httpResponse = - (HttpServletResponse) response; - - httpResponse.setHeader("X-Content-Type-Options", "nosniff"); - httpResponse.setHeader("X-Frame-Options", "DENY"); - httpResponse.setHeader("X-XSS-Protection", "1; mode=block"); - httpResponse.setHeader("Strict-Transport-Security", - "max-age=31536000; includeSubDomains"); - - chain.doFilter(request, response); - } -} -\end{lstlisting} - -\section{Datenschutz} -Die Anwendung erfüllt DSGVO-Anforderungen: - -\begin{itemize} - \item Verschlüsselte Datenspeicherung - \item Recht auf Datenlöschung - \item Datenportabilität - \item Audit-Logging aller Zugriffe - \item Cookie-Consent-Management -\end{itemize} - -\section{Zahlungssicherheit} -PCI-DSS-Compliance durch: -\begin{itemize} - \item Keine Speicherung von Kreditkartendaten - \item Stripe-Integration für Zahlungsverarbeitung - \item TLS-Verschlüsselung aller Transaktionen - \item Webhook-Validierung mit Signatur -\end{itemize} - -\chapter{Abschluss} - -\section{Projektziel} - -\subsection{Wurde das Projektziel erreicht?} -Das Projektziel wurde erfolgreich erreicht. Die Casino Gaming Platform wurde innerhalb der vorgegebenen 70 Stunden vollständig entwickelt und implementiert. - -\subsubsection{Soll-Ist Vergleich} -\begin{longtable}{|p{6cm}|p{3cm}|p{6cm}|} -\hline -\textbf{Anforderung} & \textbf{Status} & \textbf{Bemerkung} \\ -\hline -5 Casino-Spiele & \ding{51} Erreicht & Blackjack, Slots, Dice, Coinflip, Lootboxes \\ -\hline -OAuth2-Authentifizierung & \ding{51} Erreicht & GitHub und Google Integration \\ -\hline -Stripe-Zahlungssystem & \ding{51} Erreicht & Vollständig funktionstüchtig \\ -\hline -Responsive Design & \ding{51} Erreicht & Mobile-First Ansatz \\ -\hline -Transaktionshistorie & \ding{51} Erreicht & Vollständige Nachverfolgung \\ -\hline -DSGVO-Konformität & \ding{51} Erreicht & Datenschutz implementiert \\ -\hline -API-Dokumentation & \ding{51} Erreicht & Swagger/OpenAPI \\ -\hline -\end{longtable} - -\subsection{Änderungen zur anfänglichen Planung} -\begin{itemize} - \item \textbf{Poker-Spiel:} Wurde auf zukünftige Version verschoben aufgrund der Komplexität - \item \textbf{WebSocket-Integration:} Zusätzlich implementiert für Real-time Updates - \item \textbf{Docker-Containerisierung:} Früher als geplant eingeführt für bessere Entwicklungsumgebung -\end{itemize} - -\subsection{Einhaltung des zeitlichen Rahmens} -Der zeitliche Rahmen von 70 Stunden wurde eingehalten: - -\begin{itemize} - \item \textbf{Analyse \& Design:} 15 Stunden (geplant: 20 Stunden) - \item \textbf{Backend-Entwicklung:} 25 Stunden (geplant: 25 Stunden) - \item \textbf{Frontend-Entwicklung:} 20 Stunden (geplant: 15 Stunden) - \item \textbf{Testing \& QA:} 8 Stunden (geplant: 8 Stunden) - \item \textbf{Dokumentation:} 2 Stunden (geplant: 2 Stunden) -\end{itemize} - -\section{Fazit} - -\subsection{Teamarbeit} -\textbf{Wie hat die Teamarbeit funktioniert?} - -\begin{itemize} - \item \textbf{Positive Aspekte:} - \begin{itemize} - \item Gute Kommunikation über Scrum Daily Standups - \item Klare Aufgabenverteilung durch Jira-Tickets - \item Effektive Code-Reviews über Pull Requests - \item Konstruktive Problemlösungen im Team - \end{itemize} - - \item \textbf{Verbesserungspotential:} - \begin{itemize} - \item Besseres Ticket-Handling in der Anfangsphase - \item Weniger informelle Gespräche während Arbeitszeit - \item Frühzeitigere Integration von Komponenten - \end{itemize} -\end{itemize} - -\subsection{Persönlicher Lerngewinn} -\textbf{Was hat das Projekt mir persönlich gebracht?} - -\begin{itemize} - \item \textbf{Technische Kompetenzen:} - \begin{itemize} - \item Vertiefung in Angular 20 und moderne Frontend-Entwicklung - \item Praktische Erfahrung mit Spring Boot und Microservices - \item OAuth2 und JWT-basierte Authentifizierung - \item Container-Technologien (Docker, Docker Compose) - \item CI/CD-Pipelines mit GitHub Actions - \end{itemize} - - \item \textbf{Methodische Kompetenzen:} - \begin{itemize} - \item Agile Softwareentwicklung mit Scrum - \item Test-Driven Development (TDD) - \item Domain-Driven Design (DDD) - \item Clean Code Prinzipien - \end{itemize} - - \item \textbf{Projektmanagement:} - \begin{itemize} - \item Zeitmanagement bei komplexen Projekten - \item Risikomanagement und Problemlösung - \item Stakeholder-Kommunikation - \item Dokumentation und Präsentation - \end{itemize} -\end{itemize} - -\subsection{Ausblick} -Die entwickelte Casino Gaming Platform bietet eine solide Grundlage für weitere Entwicklungen. Die moderne Architektur und der saubere Code ermöglichen es, das System kontinuierlich zu erweitern und zu verbessern. - -\subsubsection{Geplante Erweiterungen} -\begin{itemize} - \item \textbf{Kurzfristig (3 Monate):} Mobile Apps für iOS und Android - \item \textbf{Mittelfristig (6 Monate):} Multiplayer-Funktionen und Turniere - \item \textbf{Langfristig (12 Monate):} KI-basierte Spielempfehlungen und erweiterte Analytics -\end{itemize} - -Das Projekt hat gezeigt, dass mit modernen Technologien und agilen Methoden auch komplexe Anwendungen effizient und qualitativ hochwertig entwickelt werden können. - -\appendix -\chapter{Anhang} - -\section{Glossar} -\begin{description} - \item[API] Application Programming Interface - Schnittstelle zur Kommunikation zwischen Softwarekomponenten - \item[CI/CD] Continuous Integration/Continuous Deployment - Automatisierte Build- und Deployment-Prozesse - \item[DDD] Domain-Driven Design - Softwaredesign-Ansatz - \item[DSGVO] Datenschutz-Grundverordnung - \item[JWT] JSON Web Token - Standard für sichere Informationsübertragung - \item[OAuth2] Autorisierungsframework für sichere API-Zugriffe - \item[PCI-DSS] Payment Card Industry Data Security Standard - \item[REST] Representational State Transfer - Architekturstil für Web-Services - \item[SSO] Single Sign-On - Einmalige Anmeldung für mehrere Dienste -\end{description} - -\section{Literaturverzeichnis} -\begin{enumerate} - \item Spring Boot Reference Documentation, Version 3.2, Spring Framework Team, 2024 - \item Angular Developer Guide, Version 20, Angular Team, Google, 2024 - \item Keycloak Server Administration Guide, Red Hat, 2024 - \item Stripe API Reference, Stripe Inc., 2024 - \item PostgreSQL Documentation, Version 17, PostgreSQL Global Development Group, 2024 - \item Docker Documentation, Docker Inc., 2024 - \item Clean Architecture, Robert C. Martin, Prentice Hall, 2017 - \item Domain-Driven Design, Eric Evans, Addison-Wesley, 2003 -\end{enumerate} - -\section{Abbildungsverzeichnis} -\begin{enumerate} - \item Systemarchitektur-Diagramm - \item ER-Diagramm der Datenbank - \item Sequenzdiagramm Authentifizierung - \item Klassendiagramm Backend - \item Komponentendiagramm Frontend -\end{enumerate} - -\section{Tabellenverzeichnis} -\begin{enumerate} - \item Projektphasen und Zeitaufwand - \item Technologie-Stack Übersicht - \item API-Endpoints Dokumentation - \item Testabdeckung pro Modul -\end{enumerate} - -\end{document} \ No newline at end of file diff --git a/projektdokumentation/Abkuerzungen.tex b/projektdokumentation/Abkuerzungen.tex index ebc9cd5..f0fda5c 100644 --- a/projektdokumentation/Abkuerzungen.tex +++ b/projektdokumentation/Abkuerzungen.tex @@ -13,28 +13,11 @@ % Die Option (in den eckigen Klammern) enthält das längste Label oder % einen Platzhalter der die Breite der linken Spalte bestimmt. \begin{acronym}[WWWWW] - \acro{API}{Application Programming Interface} \acro{CI}{Continuous Integration} \acro{CI/CD}{Continuous Integration/Continuous Deployment} - \acro{CLI}{Command Line Interface} - \acro{CRM}{Customer Relationship Management} - \acro{CRON}{Vorgangsausführung gemäß geplanten Zeitabläufen für UNIX Programme} \acro{E2E}{End-to-End} - \acro{eCommerce}{Electronic Commerce} - \acro{ERM}{Entity-Relationship-Model} - \acro{GUI}{Graphical User Interface} - \acro{HTTP}{Hypertext Transfer Protocol} - \acro{IDE}{Integrated Development Environment} - \acro{IX}{Intex Fusion Pro Omnichannel CRM} - \acro{JSON}{JavaScript Object Notation} - \acro{M2}{\textsc{Magento 2} eCommerce Platform} - \acro{NSD}{\textsc{neusta software development} GmbH} - \acro{NXP}{\textsc{neusta experience} GmbH} - \acro{PHP}{Hypertext Preprocessor}\acused{PHP} - \acro{SQL}{Structured Query Language} - \acro{URL}{Uniform Resource Locator}\acused{URL} - \acro{VM}{Virtual Machine} - \acro{XML}{Extensible Markup Language} \acro{API}{Application Programming Interface} + \acro{JSON}{JavaScript Object Notation} + \acro{HTTP}{Hypertext Transfer Protocol} \acro{JWT}{JSON Web Token} \end{acronym} diff --git a/projektdokumentation/Anhang.tex b/projektdokumentation/Anhang.tex index 11b27aa..2190795 100644 --- a/projektdokumentation/Anhang.tex +++ b/projektdokumentation/Anhang.tex @@ -1,78 +1,35 @@ % !TEX root = Projektdokumentation.tex \section{Anhang} -\subsection{Detaillierte Zeitplanung} -\label{app:Zeitplanung} -\tabelleAnhang{ZeitplanungKomplett} +\subsection{Implementierungsbeispiele} +\label{app:CodeSchichten} -\input{Anhang/AnhangLastenheft.tex} +\subsubsection{Frontend-Schicht: Angular Component} +\label{app:FrontendComponent} +\lstinputlisting[language=C, caption={Angular TypeScript Component - Coinflip Game}]{Listings/CoinflipComponent.ts} \clearpage -\input{Anhang/AnhangRessourcen.tex} +\subsubsection{Controller-Schicht: Spring Boot REST Controller} +\label{app:ControllerSchicht} +\lstinputlisting[language=java, caption={Spring Boot REST Controller - Coinflip}]{Listings/CoinflipController.java} \clearpage -\subsection{Use Case-Diagramm} -\label{app:UseCase} -\begin{figure}[htb] -\centering -\includegraphicsKeepAspectRatio{UseCase.pdf}{1.3} -\caption{Use Case-Diagramm} -\end{figure} +\subsubsection{Service-Schicht: Business Logic} +\label{app:ServiceSchicht} +\lstinputlisting[language=java, caption={Service-Klasse mit Geschäftslogik - Coinflip}]{Listings/CoinflipService.java} \clearpage -\subsection{Amortisation} -\label{app:Amortisation} -Der Zeitpunkt der Amortisation wird als Schnittpunkt der beiden Geraden angegeben. - -\begin{figure}[htb] - \centering - \includegraphicsKeepAspectRatio{amortisationgrafik.png}{1} - \caption{Grafische Darstellung der Amortisation} -\end{figure} +\subsubsection{Persistierung-Schicht: JPA Entity} +\label{app:PersistierungSchicht} +\lstinputlisting[language=java, caption={JPA Entity - Benutzer}]{Listings/UserEntity.java} \clearpage -\subsection{composer.json Konfiguration für neusta-m2-intex-client} -\label{app:ComposerJson} -\lstinputlisting[language=json, caption={Konfiguration für neusta-m2-intex-client}]{Listings/composer.json} - -\clearpage - -\subsection{Deklaration zur Anlage einer SQL Tabelle im Magento 2 Umfeld} -\label{app:InstallData} -\lstinputlisting[language=xml, caption={Deklaration zur Anlage einer SQL Tabelle im Magento 2 Umfeld}]{Listings/InstallData.xml} - -\clearpage - -\subsection{Klasse: Factory} -\label{app:Factory} -\lstinputlisting[language=php, caption={Klasse: Factory}]{Listings/Factory.php} - -\clearpage - -\subsection{Klasse: CustomerConnection} -\label{app:CustomerConnection} -\lstinputlisting[language=php, caption={Klasse: CustomerConnection}]{Listings/CustomerConnection.php} - -\clearpage - -\subsection{Klasse: Connection} -\label{app:Connection} -\lstinputlisting[language=php, caption={Abstrakte Klasse: Connection}]{Listings/Connection.php} - -\clearpage - -\subsection{Klasse: CustomerDataController} -\label{app:CustomerDataController} -\lstinputlisting[language=php, caption={Klasse: CustomerDataController}]{Listings/CustomerDataController.php} - -\clearpage - -\subsection{UnitTest: FactoryTest} -\label{app:UnitTest} -\lstinputlisting[language=php, caption={Unit Test der Klasse: Factory}]{Listings/UnitTest.php} +\subsubsection{Konfiguration: Application Properties} +\label{app:Konfiguration} +\lstinputlisting[caption={Spring Boot Anwendungskonfiguration}]{Listings/application.properties} \clearpage diff --git a/projektdokumentation/Bilder/CC-Attribution.pdf b/projektdokumentation/Bilder/CC-Attribution.pdf deleted file mode 100644 index f0a1639..0000000 --- a/projektdokumentation/Bilder/CC-Attribution.pdf +++ /dev/null @@ -1,68 +0,0 @@ -%PDF-1.5 -% -3 0 obj -<< /Length 4 0 R - /Filter /FlateDecode ->> -stream -xmM1 9E,L;Y ώS |Os~=^Tܘjk˭ԉ:}}Xwuf1GA=HMlݛn,4.UmMΙ> - >> ->> -endobj -5 0 obj -<< /Type /Page - /Parent 1 0 R - /MediaBox [ 0 0 51.200001 51.200001 ] - /Contents 3 0 R - /Group << - /Type /Group - /S /Transparency - /CS /DeviceRGB - >> - /Resources 2 0 R ->> -endobj -1 0 obj -<< /Type /Pages - /Kids [ 5 0 R ] - /Count 1 ->> -endobj -6 0 obj -<< /Creator (cairo 1.10.2 (http://cairographics.org)) - /Producer (cairo 1.10.2 (http://cairographics.org)) ->> -endobj -7 0 obj -<< /Type /Catalog - /Pages 1 0 R ->> -endobj -xref -0 8 -0000000000 65535 f -0000000812 00000 n -0000000528 00000 n -0000000015 00000 n -0000000506 00000 n -0000000600 00000 n -0000000877 00000 n -0000001004 00000 n -trailer -<< /Size 8 - /Root 7 0 R - /Info 6 0 R ->> -startxref -1056 -%%EOF diff --git a/projektdokumentation/Bilder/CC-Logo.pdf b/projektdokumentation/Bilder/CC-Logo.pdf deleted file mode 100644 index 58fe219..0000000 Binary files a/projektdokumentation/Bilder/CC-Logo.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/CC-ShareAlike.pdf b/projektdokumentation/Bilder/CC-ShareAlike.pdf deleted file mode 100644 index 058cb08..0000000 --- a/projektdokumentation/Bilder/CC-ShareAlike.pdf +++ /dev/null @@ -1,68 +0,0 @@ -%PDF-1.5 -% -3 0 obj -<< /Length 4 0 R - /Filter /FlateDecode ->> -stream -xmRI0 z#nZ'f09$?"v[%eYJ~~ѲUIL,^Ѵ<]m NfpD|wD5+ʆf^TpuaHǺ#gzW4[(l}#zq\f -vny[6v> - >> ->> -endobj -5 0 obj -<< /Type /Page - /Parent 1 0 R - /MediaBox [ 0 0 51.200001 51.200001 ] - /Contents 3 0 R - /Group << - /Type /Group - /S /Transparency - /CS /DeviceRGB - >> - /Resources 2 0 R ->> -endobj -1 0 obj -<< /Type /Pages - /Kids [ 5 0 R ] - /Count 1 ->> -endobj -6 0 obj -<< /Creator (cairo 1.10.2 (http://cairographics.org)) - /Producer (cairo 1.10.2 (http://cairographics.org)) ->> -endobj -7 0 obj -<< /Type /Catalog - /Pages 1 0 R ->> -endobj -xref -0 8 -0000000000 65535 f -0000000845 00000 n -0000000561 00000 n -0000000015 00000 n -0000000539 00000 n -0000000633 00000 n -0000000910 00000 n -0000001037 00000 n -trailer -<< /Size 8 - /Root 7 0 R - /Info 6 0 R ->> -startxref -1089 -%%EOF diff --git a/projektdokumentation/Bilder/DeckblattIHK.pdf b/projektdokumentation/Bilder/DeckblattIHK.pdf deleted file mode 100644 index f84aeea..0000000 Binary files a/projektdokumentation/Bilder/DeckblattIHK.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/DeckblattIHK_neu.pdf b/projektdokumentation/Bilder/DeckblattIHK_neu.pdf deleted file mode 100644 index 61c71a4..0000000 Binary files a/projektdokumentation/Bilder/DeckblattIHK_neu.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/ERDiagramm.pdf b/projektdokumentation/Bilder/ERDiagramm.pdf deleted file mode 100644 index fe404d1..0000000 Binary files a/projektdokumentation/Bilder/ERDiagramm.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/Entwicklungsprozess.pdf b/projektdokumentation/Bilder/Entwicklungsprozess.pdf deleted file mode 100644 index c27c7bc..0000000 Binary files a/projektdokumentation/Bilder/Entwicklungsprozess.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/Klassendiagramm.pdf b/projektdokumentation/Bilder/Klassendiagramm.pdf deleted file mode 100644 index 2412bfe..0000000 Binary files a/projektdokumentation/Bilder/Klassendiagramm.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/LogoIHK.pdf b/projektdokumentation/Bilder/LogoIHK.pdf deleted file mode 100644 index 8eefaa4..0000000 Binary files a/projektdokumentation/Bilder/LogoIHK.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/MockupModul.pdf b/projektdokumentation/Bilder/MockupModul.pdf deleted file mode 100644 index dcb2c75..0000000 Binary files a/projektdokumentation/Bilder/MockupModul.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/MockupModules.pdf b/projektdokumentation/Bilder/MockupModules.pdf deleted file mode 100644 index 8184537..0000000 Binary files a/projektdokumentation/Bilder/MockupModules.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/MockupTag.pdf b/projektdokumentation/Bilder/MockupTag.pdf deleted file mode 100644 index e413405..0000000 Binary files a/projektdokumentation/Bilder/MockupTag.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/UseCase.pdf b/projektdokumentation/Bilder/UseCase.pdf deleted file mode 100644 index 82e94d4..0000000 Binary files a/projektdokumentation/Bilder/UseCase.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/amortisationgrafik.png b/projektdokumentation/Bilder/amortisationgrafik.png deleted file mode 100644 index e8726b5..0000000 Binary files a/projektdokumentation/Bilder/amortisationgrafik.png and /dev/null differ diff --git a/projektdokumentation/Bilder/component-diagram.drawio.png b/projektdokumentation/Bilder/component-diagram.drawio.png new file mode 100644 index 0000000..519fd7f Binary files /dev/null and b/projektdokumentation/Bilder/component-diagram.drawio.png differ diff --git a/projektdokumentation/Bilder/container-diagram.drawio.png b/projektdokumentation/Bilder/container-diagram.drawio.png new file mode 100644 index 0000000..c3013e7 Binary files /dev/null and b/projektdokumentation/Bilder/container-diagram.drawio.png differ diff --git a/projektdokumentation/Bilder/database.pdf b/projektdokumentation/Bilder/database.pdf deleted file mode 100644 index f41cd07..0000000 Binary files a/projektdokumentation/Bilder/database.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/doc.pdf b/projektdokumentation/Bilder/doc.pdf deleted file mode 100644 index a54c7c5..0000000 Binary files a/projektdokumentation/Bilder/doc.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/login.png b/projektdokumentation/Bilder/login.png new file mode 100755 index 0000000..ee8bcf8 Binary files /dev/null and b/projektdokumentation/Bilder/login.png differ diff --git a/projektdokumentation/Bilder/modulimport.pdf b/projektdokumentation/Bilder/modulimport.pdf deleted file mode 100644 index 2438d52..0000000 Binary files a/projektdokumentation/Bilder/modulimport.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/modulliste.pdf b/projektdokumentation/Bilder/modulliste.pdf deleted file mode 100644 index 8d132a3..0000000 Binary files a/projektdokumentation/Bilder/modulliste.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/neusta-sd_RGB.svg b/projektdokumentation/Bilder/neusta-sd_RGB.svg deleted file mode 100644 index 3a8ab66..0000000 --- a/projektdokumentation/Bilder/neusta-sd_RGB.svg +++ /dev/null @@ -1 +0,0 @@ -neusta-sd_RGB \ No newline at end of file diff --git a/projektdokumentation/Bilder/oauth.jpg b/projektdokumentation/Bilder/oauth.jpg deleted file mode 100644 index 520b059..0000000 Binary files a/projektdokumentation/Bilder/oauth.jpg and /dev/null differ diff --git a/projektdokumentation/Bilder/oauth.png b/projektdokumentation/Bilder/oauth.png new file mode 100755 index 0000000..a145569 Binary files /dev/null and b/projektdokumentation/Bilder/oauth.png differ diff --git a/projektdokumentation/Bilder/tagliste.pdf b/projektdokumentation/Bilder/tagliste.pdf deleted file mode 100644 index ca2b0b2..0000000 Binary files a/projektdokumentation/Bilder/tagliste.pdf and /dev/null differ diff --git a/projektdokumentation/Bilder/testcase.jpg b/projektdokumentation/Bilder/testcase.jpg deleted file mode 100644 index 741c451..0000000 Binary files a/projektdokumentation/Bilder/testcase.jpg and /dev/null differ diff --git a/projektdokumentation/Bilder/unterschrift.PNG b/projektdokumentation/Bilder/unterschrift.PNG deleted file mode 100644 index c6fa983..0000000 Binary files a/projektdokumentation/Bilder/unterschrift.PNG and /dev/null differ diff --git a/projektdokumentation/Bilder/weather-clear-night.png b/projektdokumentation/Bilder/weather-clear-night.png deleted file mode 100644 index 52ea3e9..0000000 Binary files a/projektdokumentation/Bilder/weather-clear-night.png and /dev/null differ diff --git a/projektdokumentation/Bilder/weather-clear.png b/projektdokumentation/Bilder/weather-clear.png deleted file mode 100644 index e17ca7c..0000000 Binary files a/projektdokumentation/Bilder/weather-clear.png and /dev/null differ diff --git a/projektdokumentation/Bilder/weather-few-clouds-night.png b/projektdokumentation/Bilder/weather-few-clouds-night.png deleted file mode 100644 index 69fe49a..0000000 Binary files a/projektdokumentation/Bilder/weather-few-clouds-night.png and /dev/null differ diff --git a/projektdokumentation/Bilder/weather-few-clouds.png b/projektdokumentation/Bilder/weather-few-clouds.png deleted file mode 100644 index 28b1147..0000000 Binary files a/projektdokumentation/Bilder/weather-few-clouds.png and /dev/null differ diff --git a/projektdokumentation/Bilder/weather-storm.png b/projektdokumentation/Bilder/weather-storm.png deleted file mode 100644 index 3b7ca9c..0000000 Binary files a/projektdokumentation/Bilder/weather-storm.png and /dev/null differ diff --git a/projektdokumentation/Inhalt.tex b/projektdokumentation/Inhalt.tex index c57fa8f..1de4c1b 100644 --- a/projektdokumentation/Inhalt.tex +++ b/projektdokumentation/Inhalt.tex @@ -1,5 +1,6 @@ % !TEX root = Projektdokumentation.tex \input{Inhalt/Einleitung} +\input{Inhalt/Vorbereitung.tex} \input{Inhalt/Projektarchitektur} \input{Inhalt/CI} \input{Inhalt/Auth.tex} @@ -10,3 +11,6 @@ \input{Inhalt/Lootboxes.tex} \input{Inhalt/Deployment.tex} + +\input{Inhalt/Wirtschaftlichebetrachtung.tex} +\input{Inhalt/Abschluss.tex} diff --git a/projektdokumentation/Inhalt/Abnahmephase.tex b/projektdokumentation/Inhalt/Abnahmephase.tex deleted file mode 100644 index 0a1d482..0000000 --- a/projektdokumentation/Inhalt/Abnahmephase.tex +++ /dev/null @@ -1,11 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Abnahmephase} -\label{sec:Abnahmephase} - -Die Anwendung wurde gemäß der in Abschnitt~\ref{sec:Entwicklungsprozess}: \nameref{sec:Entwicklungsprozess} agilen Entwicklung stetig von Mitarbeitern der \ac{NSD} -per Code Review abgenommen. Die Code Review erfolgte über das webbasierte Development Operations Lebenszyklus Tool GitLab \footnote{GitLab - \url{https://gitlab.com}}, in dessen Repository die Anwendung per git \footnote{git - \url{https://git-scm.com/}} -versioniert wurde. Sofern ein neues Feature vom Autor fertiggestellt wurde, erstellte der Autor einen sogenannten Merge Request in GitLab. Dieser Merge Request hat zur Folge, -dass ein zugeteilter Mitarbeiter der \ac{NSD} den Code freigeben muss und dieser dann erst in den Quellcode der Anwendung übernommen werden kann. - -Teil der Abnahmebedingungen war, dass der zu implementierende Code sinnvoll mit Unit Tests abgedeckt ist. Exemplarisch hierfür steht der \Anhang{app:UnitTest}, welcher -einen beispielhaften Unit Test für die Komponente neusta-m2-intex-client-config zeigt. \ No newline at end of file diff --git a/projektdokumentation/Inhalt/Abschluss.tex b/projektdokumentation/Inhalt/Abschluss.tex new file mode 100644 index 0000000..2fcebe3 --- /dev/null +++ b/projektdokumentation/Inhalt/Abschluss.tex @@ -0,0 +1,12 @@ +% !TEX root = ../Projektdokumentation.tex +\section{Abschluss} + +\subsection{Projektziel} +Im Rahmen der Soll-Analyse konnten wesentliche Bestandteile des Projekts erfolgreich umgesetzt werden. Aufgrund zeitlicher Einschränkungen sowie unvorhergesehener technischer Herausforderungen war es jedoch nicht möglich, sämtliche ursprünglich geplanten Funktionen vollständig zu realisieren. Während der Entwicklungsphase wurde ein besonderer Schwerpunkt auf die technischen Grundlagen gelegt, insbesondere auf die sichere Authentifizierung, die serverseitige Logik sowie die Bereitstellung einer stabilen Infrastruktur. Monetarisierungsstrategien und benutzerorientierte Aspekte wurden in dieser Phase hingegen nur am Rande berücksichtigt. + +Im Verlauf der Ausarbeitung wurde zudem deutlich, dass die Umsetzung einzelner Spiele deutlich komplexer ist als zunächst angenommen. Aus diesem Grund wurde die Entwicklung auf den Kern des Spielkonzepts reduziert, wohingegen begleitende Elemente wie soziale Funktionen oder ein vollständig responsives Design vorerst nicht weiter ausgearbeitet wurden. Im weiteren Projektverlauf wurde deutlich, dass die Implementierung von Poker und Plinko nicht mehr im geplanten Zeitrahmen realisiert werden konnte. Insbesondere die Entwicklung der Authentifizierungsmechanismen sowie das Deployment der Anwendung erforderten einen höheren Aufwand als erwartet. + +\subsection{Fazit} +Die Zusammenarbeit im Team kann als grundsätzlich positiv bewertet werden. Es sei besonders hervorgehoben, dass eine offene und funktionierende Kommunikation existierte, die es ermöglichte, Herausforderungen gemeinsam zu bewältigen und Entscheidungen transparent zu treffen. Gleichzeitig wurde jedoch Optimierungspotenzial in der Organisation und Strukturierung der Arbeitsprozesse aufgezeigt. Das Projektverhalten zeigte phasenweise Unkoordiniertheit und chaotische Züge, was die Effizienz beeinträchtigte. Das Ticket-Handling hätte klarer und konsequenter erfolgen müssen, um Aufgaben besser zu priorisieren und den Überblick über den Projektfortschritt zu wahren. Trotz der zuvor genannten strukturellen Schwächen war eine gute inhaltliche Zusammenarbeit innerhalb des Teams zu verzeichnen, in deren Folge bedeutende Meilensteine erreicht werden konnten. + +Trotzdem war das Projekt von erheblicher Frustration geprägt, deren Hauptursache die als unzureichend empfundene Technologie, insbesondere Java, war. Gepaart mit Mängeln im Projektmanagement, wie zu spät begonnener Dokumentation und ineffektiven Retrospektiven, führte der massive Zeitdruck zu einem unbefriedigenden Ergebnis. Das Gesamterlebnis gipfelt in dem Gefühl, letztlich „garnichts“ erreicht zu haben, und dem nachdrücklichen Wunsch, Java zukünftig zu meiden diff --git a/projektdokumentation/Inhalt/Analysephase.tex b/projektdokumentation/Inhalt/Analysephase.tex deleted file mode 100644 index 1742a8d..0000000 --- a/projektdokumentation/Inhalt/Analysephase.tex +++ /dev/null @@ -1,105 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Analysephase} -\label{sec:Analysephase} - - -\subsection{Ist-Analyse} -\label{sec:IstAnalyse} -Ein Direktimport über Schnittstellen wird für \ac{M2} nicht zur Verfügung gestellt. -Derzeit werden solche Importer per Modul für jeden Webshop individuell selbst entwickelt und angepasst. -Als Modul bezeichnet man im \ac{M2} Umfeld eine Erweiterung des Frameworks durch neue Funktionalitäten. -Die hierfür neu entwickelnden Module stellen \acs{API}-Abfragen an \ac{IX} und importieren die Daten ohne temporäres Zwischenspeichern in \ac{M2}. -Vorhandene Fehlerquellen sind hier die benötigte Verbindung zur \ac{IX}-\acs{API} und die unbedingte Richtigkeit der übertragenen Daten. -Kommen Fehler beim Import aufgrund von fehlender oder unvollständiger Datensätze zustande, bricht der komplette Import ab. -Gleiches gilt für die Export Funktionen zum Exportieren von Bestellungen von \ac{M2} zu \ac{IX}. - - -\subsection{Wirtschaftlichkeitsanalyse} -\label{sec:Wirtschaftlichkeitsanalyse} -Aufgrund des in den Abschnitten~\ref{sec:Projektbegruendung}: \nameref{sec:Projektbegruendung} und~\ref{sec:IstAnalyse}: \nameref{sec:IstAnalyse} -geschilderten und erläuterten derzeitigen Zustandes von Import/Export-Modulen in Abhängigkeit zum \ac{CRM} \ac{IX} für \ac{M2}, ist die Umsetzung -des Projektes unbedingt erforderlich. Eine gerechtfertigte Realisierung aus wirtschaftlichen Gesichtspunkten wird in den folgenden Abschnitten analysiert. - -\subsubsection{\gqq{Make or Buy}-Entscheidung} -\label{sec:MakeOrBuyEntscheidung} -Bei dem Projekt handelt es sich um die Erfüllung von kundenspezifischen Anforderungen, sofern \ac{IX} als \ac{CRM} genutzt wird. -Hierfür lässt sich auf dem Markt keine Lösung finden, die eine Integration der Warenwirtschaft in ein \ac{M2} ermöglicht. -Daher soll das Projekt in Eigenentwicklung durchgeführt und durch Nutzung von Open Source Anwendungen erweitert werden. - - -\subsubsection{Projektkosten} -\label{sec:Projektkosten} -Im folgenden sollen die Kosten kalkuliert werden, die während der Entwicklung des Projektes anfallen. Neben Personalkosten, die durch die Umsetzung -des Projektes verursacht werden, mussten auch Aufwendungen für die in Abschnitt~\ref{sec:Ressourcenplanung}: \nameref{sec:Ressourcenplanung} genannten Ressourcen -berücksichtigt werden. Da Personalkosten im Original nicht herausgegeben werden dürfen, erfolgte die Kalkulation anhand von unterstellten Werten. - -Die Durchführungszeit des Projekts beträgt 70 Stunden. -Unterstellt wurde ein Stundensatz in Höhe von \eur{10} für Auszubildende sowie \eur{25} für Mitarbeiter. -Für die o.g. Ressourcennutzung wurde ein pauschaler Satz von \eur{15} angenommen. - -Eine Aufstellung der Kosten lassen sich der Tabelle~\ref{tab:Kostenaufstellung} entnehmen und betragen insgesamt \eur{2910}. -\tabelle{Kostenaufstellung}{tab:Kostenaufstellung}{Kostenaufstellung.tex} - - -\subsubsection{Amortisationsdauer} -\label{sec:Amortisationsdauer} -Der folgende Abschnitt dient zur Ermittlung des Zeitpunktes, ab welchem sich die Entwicklung der Anwendung amortisiert hat. -Anhand dieses Wertes kann beurteilt werden, ob die Umsetzung des Projektes aus wirtschaftlicher Sicht sinnvoll ist und sich hieraus -Kostenvorteile ergeben. - -Nachfolgend soll nun die Amortisationsdauer berechnet werden. Diese gibt an, ab welchem Zeitpunkt die Anschaffungs- und Entwicklungskosten durch die -Zeitersparnis beglichen werden kann. - -\tabelle{Zeitersparnis}{tab:Zeitersparnis}{Zeitersparnis} \\ - -\textbf{Berechnung der Amortisationsdauer:} -\begin{align} -415\ \frac{min}{Monat} \cdot 12\ \frac{Monate}{Jahr} = 4980\ \frac{min}{Jahr} = 83\ \frac{h}{Jahr} -\end{align} -\begin{align} -83\ \frac{h}{Jahr} \cdot (\eur{25} + \eur{15}) = 3320\ \frac{\eur{}}{Jahr} -\end{align} -\begin{align} - \frac{\eur{3320}}{2910 \frac{\eur{}}{Jahr}} = 1,14\ Jahre \approx 1\ Jahr\ \&\ 1,5\ Monate -\end{align} - -Zusätzlich wurde die Amortisation grafisch dargestellt. Das Diagramm enthält die variablen Kosten (pro Jahr) der neuen Lösung sowie die Kosten, -die für die Entwicklung der neuen Umsetzung angefallen sind. Die Grafik findet sich im~\Anhang{app:Amortisation}. - -Anhand der Amortisationsrechnung ergibt sich für das Projekt eine Amortisationsdauer von einem Jahr und ca. eineinhalb Monaten. Dies definiert den Zeitraum, über den -die neue Anwendung mindestens eingesetzt werden muss, um Anschaffungskosten und Kosteneinsparung auszugleichen. Da das Projekt von der \ac{NSD} langfristig eingesetzt -werden soll, kann das Projekt unter wirtschaftlichen Gesichtspunkten als sinnvoll eingestuft werden. - -\subsection{Nutzwertanalyse} -\label{sec:Nutzwertanalyse} -Durch die in den Abschnitten~\ref{sec:Projektkosten}: \nameref{sec:Projektkosten} und~\ref{sec:Amortisationsdauer}: \nameref{sec:Amortisationsdauer} aufgeführten Ergebnisse wird die Realisierung -des Projektes bereits ausreichend gerechtfertigt. Hierdurch soll an dieser Stelle auf eine detaillierte Analyse nicht-monetärer Vorteile verzichtet werden. -Nicht-monetäre Vorteile der Anwendung wären aber \zB die angenehmere Wartbarkeit durch bessere Übersicht der neu implementierten Modulstruktur sowie die Implementierung von aussagekräftigeren Fehlermeldungen -und der Möglichkeit, die Anwendung schnell für individuelle Wünsche anzupassen. - - -\subsection{Anwendungsfälle} -\label{sec:Anwendungsfaelle} -Eine grobe Übersicht über die von der Anwendung abzudeckenden Anwendungsfälle wurde im Laufe der Analysephase per Use-Case-Diagramm dargestellt. -Dieses Diagramm befindet sich im \Anhang{app:UseCase} und bildet alle Funktionen ab, welche aus Anwendersicht benötigt werden. - -Dem Entwickler stehen der Vollimport sowie die Teilimporte der Daten für Nutzer- und Produktdaten zur Verfügung. Die Teilimporte sind erforderlich, -um mögliche Fehlimporte im Kleinen neu anstoßen zu können und so einen erneuten Vollimport zu verhindern. - -Beim Auslösen des Import-Vorgangs werden die Daten von der \ac{IX}-\acs{API} angefordert und zwischengespeichert, um abermalige Requests zu verhindern. -Die zwischengespeicherten Daten werden dann zu \ac{M2} importiert und dem Webshop zur Verfügung gestellt. - -Der Vorgang des Vollimports wird außerdem auch über einen \acs{CRON}-Job in geplanten Zeitabständen zur Verfügung gestellt, um ein abermaliges, manuelles -Anstoßen zu umgehen. - -\subsection{Qualitätsanforderungen} -\label{sec:Qualitaetsanforderungen} -Die Anwendung soll unter Green Development \footnote{Sustainable Web Design - \url{https://sustainablewebdesign.org/}} Grundsätzen entwickelt werden. Dies bedeutet, dass auf effiziente Datenabfragen sowie auf Minderung von Komplexität während -der Entwicklung geachtet wird. Weitere Punkte der Qualitätsanforderungen sind die Möglichkeit nachvollziehbare Logs einzusehen, falls Fehler während -eines Importes entstehen sowie die Wartbarkeit der Anwendung durch modulare und entkoppelte Entwicklung. Außerdem soll die Anwendung mit Unit-Tests abgedeckt sein, -um die Funktionalität des Codes zu gewährleisten. - -\subsection{Lastenheft/Fachkonzept} -\label{sec:Lastenheft} -Am Ende der Analysephase wurde mit den Mitarbeitern der \ac{NSD} sowie der \ac{NXP} ein Lastenheft erstellt. Dieses umfasst alle Anforderungen, -welche an die neue Anwendung gestellt werden. Ein Auszug aus dem erstellten Lastenheft befindet sich im \Anhang{app:Lastenheft}. diff --git a/projektdokumentation/Inhalt/Auth.tex b/projektdokumentation/Inhalt/Auth.tex index e3f29e2..aebbbeb 100644 --- a/projektdokumentation/Inhalt/Auth.tex +++ b/projektdokumentation/Inhalt/Auth.tex @@ -2,8 +2,22 @@ \label{sec:Authentifizierung} Die Authentifizierung gegenüber der \acs{API} erfolgt über einen \acs{JWT}-Token, der dem Frontend nach Erfolgreicher Authentifizierung übergeben wird. Authentifizierung läuft über zwei verschiedene Wege ab: -\begin{itemize} - \item \textbf{Registrierung mit username/password:} Der Nutzer füllt ein Registrierungs-Formular aus, welches die Anmeldedaten an die \acs{API} sendet. Diese validitert die Anmeldedaten und legt bei Erfolg einen neuen Nutzer an. Anschließend wird eine E-Mail-Verifizierungs-Mail gesendet. Bis der Link in der Verifizierungs-Mail nicht angeklickt wurde, ist der Nutzer nicht aktiv und kann sich nicht anmelden. Nach dem Klick auf den Link wird der Nutzer aktiviert und kann sich anmelden. - \item \textbf{Login mit username/password:} Der Nutzer füllt ein Anmelde-Formular, welches die Anmeldedaten an die \acs{API} sendet. Diese prüft die Anmeldedaten und gibt bei Erfolg einen \acs{JWT}-Token zurück. Falls kein Nutzer mit den Anmeldedaten existiert, wird der Nutzer aufgefordert einen Account zu erstellen. - \item \textbf{Login über Oauth (Open Authorization):} Der Nutzer meldet sich mit einem Oauth-Provider an, in unserem Fall Google oder Github. Das Backend leitet den Nutzer zum Oauth-Provider weiter, der die Anmeldedaten prüft und bei Erfolg den Nutzer auf die Applikation weiterleitet und einen Authorization-Code zurück gibt. Mit diesem Code holt sich die \acs{API} einen \acs{JWT} vom jeweiligen Provider und holt sich Nutzer-Informationen. Mit diesen wird dann ein existierender Nutzer eingeloggt, oder registriert falls der Nutzer noch kein Konto hatte. Anschließend wird von der \acs{API} ein \acs{JWT} generiert und an das Frontend weitergegeben. -\end{itemize} +\subsection{Registrierung mit username/password} Der Nutzer füllt ein Registrierungs-Formular aus, welches die Anmeldedaten an die \acs{API} sendet. Diese validitert die Anmeldedaten und legt bei Erfolg einen neuen Nutzer an. Anschließend wird eine E-Mail-Verifizierungs-Mail gesendet. Bis der Link in der Verifizierungs-Mail nicht angeklickt wurde, ist der Nutzer nicht aktiv und kann sich nicht anmelden. Nach dem Klick auf den Link wird der Nutzer aktiviert und kann sich anmelden. + +\subsection{Login mit username/password} Der Nutzer füllt ein Anmelde-Formular, welches die Anmeldedaten an die \acs{API} sendet. Diese prüft die Anmeldedaten und gibt bei Erfolg einen \acs{JWT}-Token zurück. Falls kein Nutzer mit den Anmeldedaten existiert, wird der Nutzer aufgefordert einen Account zu erstellen. + +\begin{figure} + \centering + \includegraphics[width=0.3\textwidth]{login.png} + \caption{Login-Formular der Anwendung} + \label{fig:login} +\end{figure} + +\subsection{Login über Oauth (Open Authorization)} Der Nutzer meldet sich mit einem Oauth-Provider an, in unserem Fall Google oder Github. Das Backend leitet den Nutzer zum Oauth-Provider weiter, der die Anmeldedaten prüft und bei Erfolg den Nutzer auf die Applikation weiterleitet und einen Authorization-Code zurück gibt. Mit diesem Code holt sich die \acs{API} einen \acs{JWT} vom jeweiligen Provider und holt sich Nutzer-Informationen. Mit diesen wird dann ein existierender Nutzer eingeloggt, oder registriert falls der Nutzer noch kein Konto hatte. Anschließend wird von der \acs{API} ein \acs{JWT} generiert und an das Frontend weitergegeben. + +\begin{figure} + \centering + \includegraphics[width=0.45\textwidth]{oauth.png} + \caption{OAuth-Authentifizierungsablauf} + \label{fig:oauth} +\end{figure} \ No newline at end of file diff --git a/projektdokumentation/Inhalt/Coinflip.tex b/projektdokumentation/Inhalt/Coinflip.tex index 18ea1c5..1e54bdf 100644 --- a/projektdokumentation/Inhalt/Coinflip.tex +++ b/projektdokumentation/Inhalt/Coinflip.tex @@ -1,4 +1,3 @@ -\clearpage \section{Coinflip} \subsection{Was ist Coinflip?} @@ -36,4 +35,7 @@ Das Spielergebnis wird strukturiert an das Frontend übermittelt und enthält: \item Gewinnstatus (gewonnen/verloren) \item Auszahlungsbetrag (bei Gewinn: 2x Einsatz) \item Geworfene Münzseite -\end{itemize} \ No newline at end of file +\end{itemize} + +\subsubsection{Implementierungsdetails} +Die vollständige Implementierung der Coinflip-Funktionalität umfasst verschiedene Architekturschichten: Das Angular Frontend-Component (siehe \ref{app:FrontendComponent}), den Spring Boot REST Controller (siehe \ref{app:ControllerSchicht}) und die Service-Schicht mit der Geschäftslogik (siehe \ref{app:ServiceSchicht}). Zusätzlich wird die Benutzer-Entity (siehe \ref{app:PersistierungSchicht}) für die Guthaben-Verwaltung verwendet. \ No newline at end of file diff --git a/projektdokumentation/Inhalt/Deployment.tex b/projektdokumentation/Inhalt/Deployment.tex index 9b1a671..196eb91 100644 --- a/projektdokumentation/Inhalt/Deployment.tex +++ b/projektdokumentation/Inhalt/Deployment.tex @@ -1,7 +1,5 @@ \section{Deployment} \label{sec:Deployment} Es gibt zwei Server auf denen Instanzen der Applikation laufen. -\begin{itemize} - \item \textbf{\href{https://casino.simonis.lol/}{Entwicklungsserver}:} Auf dem Entwicklungsserver läuft eine Instanz der Applikation, die für die Entwicklung und das Testen von neuen Features genutzt wird. Diese Instanz ist Lokal bei Constantin gehostet und wird durch einen Cloudflare-Tunnel öffentlich zugänglich gemacht. - \item \textbf{\href{https://trustworthy.casino/}{Produktionsserver}:} Auf dem Produktionsserver läuft die finale Version der Applikation, die für die Nutzer zugänglich ist. Diese Instanz ist öffentlich zugänglich und wird von den Nutzern genutzt. Diese Instanz ist auf einem gemieteten Server gehostet. Die Applikation wird durch eine Nginx Reverse-Proxy bereitgestellt, die Anfragen an die \acs{API} und das Frontend weiterleitet und SSL-Zertifikate verwaltet. -\end{itemize} \ No newline at end of file +\subsection{\href{https://casino.simonis.lol/}{Entwicklungsserver}} Auf dem Entwicklungsserver läuft eine Instanz der Applikation, die für die Entwicklung und das Testen von neuen Features genutzt wird. Diese Instanz ist Lokal bei Constantin gehostet und wird durch einen Cloudflare-Tunnel öffentlich zugänglich gemacht. +\subsection{\href{https://trustworthy.casino/}{Produktionsserver}} Auf dem Produktionsserver läuft die finale Version der Applikation, die für die Nutzer zugänglich ist. Diese Instanz ist öffentlich zugänglich und wird von den Nutzern genutzt. Diese Instanz ist auf einem gemieteten Server gehostet. Die Applikation wird durch eine Nginx Reverse-Proxy bereitgestellt, die Anfragen an die \acs{API} und das Frontend weiterleitet und SSL-Zertifikate verwaltet. Die Konfiguration der Anwendung erfolgt über Umgebungsvariablen und Properties-Dateien (siehe \ref{app:Konfiguration}). diff --git a/projektdokumentation/Inhalt/Dice.tex b/projektdokumentation/Inhalt/Dice.tex index fd346d6..465bbcd 100644 --- a/projektdokumentation/Inhalt/Dice.tex +++ b/projektdokumentation/Inhalt/Dice.tex @@ -1,4 +1,3 @@ -\clearpage \section{Dice} \subsection{Was ist Dice?} diff --git a/projektdokumentation/Inhalt/Dokumentation.tex b/projektdokumentation/Inhalt/Dokumentation.tex deleted file mode 100644 index f3f603a..0000000 --- a/projektdokumentation/Inhalt/Dokumentation.tex +++ /dev/null @@ -1,7 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Dokumentation} -\label{sec:Dokumentation} -Die Dokumentation der Anwendung besteht aus zwei Bestandteilen: der Projektdokumentation, in welcher der Autor die einzelnen -Phasen, die während der Projektumsetzung durchlaufen wurden, beschreibt sowie der Entwicklerdokumentation, bei der es sich um eine -detaillierte Beschreibung der Klassen, die von der Anwendung genutzt werden, handelt. Außerdem werden auch deren Attribute und Methoden sowie die -Abhängigkeiten der jeweiligen Klassen untereinander erläutert. diff --git a/projektdokumentation/Inhalt/Einfuehrungsphase.tex b/projektdokumentation/Inhalt/Einfuehrungsphase.tex deleted file mode 100644 index aca976c..0000000 --- a/projektdokumentation/Inhalt/Einfuehrungsphase.tex +++ /dev/null @@ -1,12 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Einführungsphase} -\label{sec:Einfuehrungsphase} - -Durch die in Abschnitt~\ref{sec:ImplementierungGeschaeftslogik}: \nameref{sec:ImplementierungGeschaeftslogik} vorgenommene Implementierung -der Anwendung als Composer basierte Packages, ist das zur Verfügung stellen der Anwendung an den \ac{NSD} internen Satis \footnote{Composer Satis - \url{https://github.com/composer/satis}} Server angebunden. -Der interne Satis dient als Composer Repository und stellt so eigen entwickelte Module für die \ac{NSD} für alle Kundenprojekte zur Verfügung. - -Die Komponenten der Anwendung werden dort aufgeführt und können in die realen Kundenprojekte nach Fertigstellung der ausgelassenen -Funktionen per Composer implementiert werden. Hier kommt nun auch der größte Vorteil zu tragen, da eine Änderung der Module lediglich -in der Grundversion, die dem Satis zur Verfügung steht, vorgenommen muss und somit automatisch per Composer bei Deployments für Live Umgebungen übernommen werden. -So müssen Änderungen nicht code-seitig an den Projekten vorgenommen werden. \ No newline at end of file diff --git a/projektdokumentation/Inhalt/Einleitung.tex b/projektdokumentation/Inhalt/Einleitung.tex index 52652f7..1ec4b88 100644 --- a/projektdokumentation/Inhalt/Einleitung.tex +++ b/projektdokumentation/Inhalt/Einleitung.tex @@ -1,55 +1,57 @@ % !TEX root = ../Projektdokumentation.tex \section{Einleitung} \label{sec:Einleitung} -Die folgende Projektdokumentation behandelt den Ablauf des IHK-Abschlussprojekts, welches der Autor im Rahmen seiner Ausbildung -zum Fachinformatiker mit der Fachrichtung Anwendungsentwicklung durchgeführt hat. Ausbildungsbetrieb ist die \ac{NSD}, -ein Tochterunternehmen der team neusta Unternehmensgruppe mit Sitz in Bremen. Das Kerngeschäft der \ac{NSD} umfasst die Beratung, -Entwicklung und Umsetzung von komplexen Software- und \ac{eCommerce}-Lösungen und beschäftigt zur Zeit ca. 1000 Mitarbeiter. +Die folgende Projektdokumentation beschreibt die Entwicklung einer innovativen Online-Casino-Plattform für die HiTec GmbH, +ein mittelgroßes IT-Systemhaus mit Sitz in Bremen, das seit über 15 Jahren als IT-Dienstleister tätig und seit einigen Jahren ISO/IEC 27001 zertifiziert ist. Das Kerngeschäft der HiTec GmbH umfasst Entwicklung eigener Softwareprodukte, Consulting, IT-Systembereich sowie Support und Wartung und beschäftigt spezialisierte Mitarbeiter in verschiedenen Abteilungen. \subsection{Projektumfeld} \label{sec:Projektumfeld} -Auftraggeber des Projektes ist die \ac{NXP}, ebenfalls eine Tochtergesellschaft der team neusta Unternehmensgruppe. -Zu den Leistungen der \ac{NXP} gehören die Beratung und Umsetzung der Bereiche Konzeption, Design und Usability sowie die Leitung von Web- und \ac{eCommerce}-Projekten. +Auftraggeber des Projektes ist Herr Hofmann, der Inhaber der HiTec GmbH. +Das Unternehmen möchte sein Produkt-Portfolio in den nächsten zwei Jahren wesentlich erweitern, um weiterhin am Markt zu bestehen und noch stärker zu wachsen. Dazu soll der Bereich der Webanwendungen mit einem neuartigen Produkt beitragen, das über einzigartige Features verfügt. -Die technische Umsetzung von Web- und \ac{eCommerce}-Projekten für Kunden der \ac{NXP} wird in Zusammenarbeit mit Mitarbeitern der \ac{NSD} vorgenommen. +Das Ziel ist es, das fachliche Know-How des Entwicklungsteams stärker zu nutzen, um als innovatives IT-Unternehmen langfristig am Markt wahrgenommen zu werden und schnell Erträge zu erzielen. -Diese Form der Zusammenarbeit erfordert intensive, regelmäßige Kommunikation und Rücksprache zwischen beiden Parteien. +Die technische Umsetzung erfolgt mit den in der HiTec GmbH etablierten Technologien und Projektmanagement-Methoden unter Verwendung agiler Entwicklungsmethoden. \subsection{Projektziel} \label{sec:Projektziel} -Ziel des Projektes ist die Entwicklung einer Schnittstelle zum Importieren und Exportieren von Produkt- und Nutzerdaten -zwischen dem \ac{CRM} \ac{IX} und einem \ac{M2} Webshop. +Ziel des Projektes ist die Entwicklung einer innovativen Online-Casino-Plattform als neuartiges Produkt für das Portfolio der HiTec GmbH. -Die \ac{NSD} entwickelt für Kunden der \ac{NXP} spezifische Webshops und bindet diese an das vom Kunden vorgesehene \ac{CRM} an. -Für \ac{IX} erfordert dies eine individuelle Entwicklung pro Kunden, welche mit hohem Aufwand und Kosten verbunden ist. -Dieses Projekt soll einen modularen Rahmen für Importe/Exporte zwischen \ac{M2}, einer Open-Source \ac{eCommerce} Platform -auf \ac{PHP} Basis und \ac{IX} abbilden, welcher in verschiedene Kundenprojekte implementiert werden kann und so die -abermalige Neuentwicklung eines Import/Export Modules ablöst. +Die Plattform soll verschiedene Casino-Spiele wie Blackjack, Coinflip, Würfelspiele und Spielautomaten anbieten und durch moderne Features wie Lootboxes und ein umfassendes Benutzermanagement erweitert werden. +Das System soll eine vollständige Transaktionsabwicklung mit Einzahlungsfunktionen und eine sichere Benutzerauthentifizierung über OAuth2-Integration bieten. +Durch den Einstieg in den Entertainment-Bereich soll das bisherige IT-Systemhaus-Portfolio um ein profitables Gaming-Produkt erweitert werden. +Die Fokussierung auf Social Casino Games ermöglicht den Zugang zum wachsenden Markt der Casual-Gamer, während gleichzeitig die strengen Glücksspiellizenzen und regulatorischen Anforderungen umgangen werden können. + +Die Monetarisierung erfolgt primär über den Verkauf virtueller Währungen und Premium-Features, was bei vergleichsweise niedrigen Entwicklungskosten eine hohe Gewinnmarge verspricht. +Zusätzliche Einnahmequellen werden durch In-App-Käufe und spezielle Lootbox-Angebote generiert. + +Diese Webanwendung soll als hochproduktive und kostenarme Implementierung realisiert werden, um schnell Marktreife zu erlangen und Erträge zu generieren. \subsection{Projektbegründung} \label{sec:Projektbegruendung} -Die \ac{NSD} entwickelt derzeit für jeden Kunden, der \ac{IX} als \ac{CRM} nutzt, individuell ein Modul zur Erweiterung -des relevanten \ac{M2}. -Diese Module handhaben den Kunden- sowie Produktdaten-Import von \ac{IX} zu \ac{M2}. Die Neuentwicklungen für jeden -Kunden beinhalten Schwierigkeiten in der Wartung und Fehleranalyse, da jeder Entwickler sich in das individuell entwickelte Modul -einarbeiten muss. Gleichzeitig liegt hier kein Standard vor, wie mit Fehlermeldungen, die von der \ac{IX}-\acs{API} empfangen werden, umgegangen wird. -Dies resultiert in längerer und umständlicher Wartung und schlägt dem Kunden durch Mehraufwand zu Buche, der vermieden werden kann. +Der Online-Gaming- und Casino-Markt zeigt kontinuierliches Wachstum und bietet erhebliches Potenzial für innovative Lösungen. +Durch die Entwicklung einer modernen Casino-Plattform kann die HiTec GmbH eine neue Kundengruppe erschließen und eine Nische im Gaming-Bereich besetzen. -Ein modularer Rahmen mit einfachen Individualisierungsmöglichkeiten für einen \ac{IX}-Importer als Modul für \ac{M2} sorgt somit für -eine Minderung von Neu-Entwicklungskosten und -aufwand. Eine höhere Wartbarkeit mit geringerer Einarbeitungszeit pro Kundenprojekt wird hierdurch -ebenfalls garantiert. +Die Verwendung bewährter Technologien (Java mit Spring-Boot, Angular, Keycloak) minimiert die Entwicklungsrisiken und ermöglicht eine schnelle Markteinführung. +Gleichzeitig demonstriert das Projekt die technische Kompetenz des Unternehmens in der Entwicklung komplexer, interaktiver Webanwendungen. +Ein modularer Aufbau mit verschiedenen Spielen und Features ermöglicht eine schrittweise Erweiterung und Anpassung an Marktanforderungen, was langfristige Wartbarkeit und Skalierbarkeit gewährleistet. \subsection{Projektschnittstellen} \label{sec:Projektschnittstellen} -Damit die Daten, die zu \ac{M2} importiert werden sollen, vollständig ermittelt und validiert werden können, muss die Anwendung mit -der \ac{IX}-\acs{API} interagieren können. Diese Anforderung soll mit Hilfe von cURL \footnote{cURL - Client URL \url{https://github.com/curl/curl}} im Umfeld der \ac{PHP} Entwicklung umgesetzt werden. +Die Anwendung wird als Full-Stack-Webanwendung mit getrenntem Backend und Frontend entwickelt. +Das Backend basiert auf Java mit Spring-Boot und stellt RESTful APIs für die Spiellogik, Benutzerverwaltung und Transaktionsabwicklung bereit. -Um den eigentlichen Import-Vorgang der bereits geholten Daten von \ac{IX} starten zu können wird zudem eine Verbindung zur Import-\acs{API} von \ac{M2} benötigt. -Aus diesem Grund wird die Anwendung als \ac{M2}-Modul implementiert. So wird garantiert, dass Fehler im Import-Vorgang minimiert werden, weil der Fokus darauf gelegt -wird, die \ac{M2} eigenen Import-Funktionen zu nutzen. +Für die Benutzerauthentifizierung wird Keycloak als Identity Provider eingesetzt, der OAuth2-Integration mit externen Anbietern wie Google und GitHub ermöglicht. +Die Frontend-Anwendung wird mit Angular entwickelt und kommuniziert über HTTP-APIs mit dem Backend. + +Zur Containerisierung und für das Deployment wird Docker verwendet, was eine konsistente Entwicklungs- und Produktionsumgebung gewährleistet. +Die Projektverwaltung erfolgt mit Jira unter Verwendung der Scrum-Methodik, die in der HiTec GmbH als Standard etabliert ist. \subsection{Projektabgrenzung} \label{sec:Projektabgrenzung} -Da der Projektumfang beschränkt ist, soll die Entwickung der Import- und Export-Funktionen von Bestellungen und Warenkörben nicht Bestandteil dieses Abschlussprojektes sein. +Da der Projektumfang beschränkt ist, konzentriert sich die Entwicklung auf die Kernfunktionalitäten der Casino-Plattform. +Erweiterte Features wie Live-Dealer-Spiele, komplexe Turniere oder Integration mit externen Zahlungsdienstleistern sind nicht Bestandteil dieses Mittelstufenprojekts. + +Die Implementierung beschränkt sich auf eine begrenzte Anzahl von Casino-Spielen und grundlegende Benutzerfunktionen, um eine funktionsfähige Proof-of-Concept-Anwendung zu erstellen. diff --git a/projektdokumentation/Inhalt/Entwurfsphase.tex b/projektdokumentation/Inhalt/Entwurfsphase.tex deleted file mode 100644 index 256b582..0000000 --- a/projektdokumentation/Inhalt/Entwurfsphase.tex +++ /dev/null @@ -1,73 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Entwurfsphase} -\label{sec:Entwurfsphase} - -\subsection{Zielplattform} -\label{sec:Zielplattform} -Das Abschlussprojekt soll, wie in Abschnitt~\ref{sec:Projektziel}: \nameref{sec:Projektziel} beschrieben, aufgrund des Aspektes der Fehlerminimierung als \ac{M2}-Modul -umgesetzt werden. Zur temporären Zwischenspeicherung der importierten Datensätze von \ac{IX} wird eine Tabelle in das -bestehende Datenbank-System der \ac{M2} Instanz implementiert. - -Die Auswahl der Programmiersprache, mit der das Projekt realisiert werden soll, wurde anhand der Anforderungen von \ac{M2} -als \ac{eCommerce} Platform durchgeführt. Um eine Fehler minimierende Einbindung in bestehende Shops zu garantieren, wurde beschlossen, -auf eine Nutzwertanalyse zu verzichten und den genannten Anforderungen von \ac{M2} Folge zu leisten. - -Daher ist die Programmiersprache \ac{PHP}, unter Berücksichtigung der genannten Gesichtspunkte, am besten geeignet und soll für die Umsetzung des Projektes verwendet werden. - - -\subsection{Architekturdesign} -\label{sec:Architekturdesign} -Die Implementierung der einzelnen Import-Funktionen für Benutzer- und Produktdaten sollen auf Basis des Factory Design Pattern \footnote{PHP the Right Way - Factory Pattern - \url{https://phptherightway.com/pages/Design-Patterns.html}} -umgesetzt werden. Demnach wird jede Import-Komponente durch eine zugehörige Factory per Singleton Prinzip instanziiert. -So wird sichergestellt, dass jeweils nur eine Instanz des Imports vorhanden ist und Rechenlast während der Nutzung der Anwendung -minimiert wird. - -Zusätzlich wird jede Funktionalität modular als Composer \footnote{Composer - \url{https://getcomposer.org}} Package eingebunden, sodass die einzelnen Komponenten nur eine Basis-Komponente zum -Funktionieren benötigen. Die Basis-Komponente bindet alle gewünschten Komponenten ein und kann sie anhand des o.g. Factory Patterns instanziieren. - -Diese Modularität bildet eine übersichtliche Anwendungsgestaltung, die nachträglich - ohne viel Aufwand - um mehr Funktionalität erweitert werden kann. - -\subsection{Entwurf der Benutzeroberfläche} -\label{sec:Benutzeroberflaeche} -Der Autor hat sich auf Grund des festgelegten Projektumfangs sowie des festgelegten Nutzerkreises, der aus Mitarbeitern der \ac{NSD} besteht, -für eine Umsetzung der Benutzeroberfläche als \ac{CLI}, zur Ausführung der in -Abschnitt~\ref{sec:Anwendungsfaelle}: \nameref{sec:Anwendungsfaelle} beschriebenen Anwendungsfälle, entschieden. - -Die Einbindung der Konsolenbefehle soll über die standardisierte \ac{M2} Implementierungsmöglichkeit für \ac{CLI} Befehle erfolgen. - -\subsection{Datenmodell} -\label{sec:Datenmodell} - -Um eine Zwischenspeicherung der Daten, die von der \ac{IX}-\ac{API} bereitgestellt werden, zu realisieren, wird eine Tabelle zur -Datenstruktur vom betroffenen \ac{M2} Webshop hinzugefügt. Diese Tabelle soll lediglich Informationen über die importierten Daten und den -jeweiligen Zeitstempel zur Nachvollziehbarkeit enthalten. - -Da keine komplexen Entitäten hierfür benötigt werden, wurde vom Autor darauf verzichtet ein \ac{ERM} sowie eine Datenbankstruktur zu -erstellen. - - -\subsection{Geschäftslogik} -\label{sec:Geschaeftslogik} - -Wie in Abschnitt~\ref{sec:Architekturdesign}: \nameref{sec:Architekturdesign} beschrieben, wird die Anwendung in mehrere Komponenten aufgeteilt. -Die Aufteilung der Komponenten erfolgt per Registrierung als Composer Package. Composer als \ac{PHP} Package Manager bietet die Möglichkeit, -Abhängigkeiten der genutzten Software zu versionieren und in einem kontrollierten Umfeld zu nutzen. Durch die Aufteilung der Anwendung in solche -Packages, erlangt der Autor eine entkoppelte Anwendung, die ohne großen Aufwand ebenfalls erweitert werden kann. - -Es wird eine Basis-Komponente geben von der jede Subkompenente ableitet. Diese Basis-Komponente beinhaltet die Grundabhängigkeiten, -damit die Anwendung im jeweiligen \ac{M2} Umfeld lauffähig ist. Diese Grundabhängigkeiten beinhalten die Version der Programmiersprache -\ac{PHP}, die Version des genutzten \ac{M2} sowie die genauen Abhängigkeiten der genutzten \ac{M2} Kern-Komponenten. Zusätzlich wird eine Version -der Anwendung selbst definiert, sodass in der weiteren Entwicklung eigene Versionen für verschiedene \ac{M2} Versionen (\zB ältere) zur Verfügung gestellt -werden könnten. Die Basis Komponente wird den Namen neusta-m2-intex-base tragen. - -neusta-m2-intex-base wird erweitert um folgende Subkomponenten: -\begin{itemize} - \item neusta-m2-intex-client: Subkomponente zur Verbindung zur \ac{IX} \ac{API} - \item neusta-m2-intex-client-config: Subkomponente zur Konfiguration des Key-Value Mappings für Daten von \ac{IX} - \item neusta-m2-intex-cli: Subkomponente zur Implementierung der Benutzeroberfläche - \item neusta-m2-intex-customer: Subkomponente zur Implementierung der Import Logik für Nutzerdaten - \item neusta-m2-intex-catalog: Subkomponente zur Implementierung der Import Logik für Produktdaten -\end{itemize} - -Durch die Namenskonvention, die vom Autor gewählt wurde, ist für aussenstehende Entwickler schneller ersichtig, in welcher Komponente -welche Logik eingebaut wurde. So wird weiterhin die Wartungsfähigkeit der Anwendung in den Vordergrund gestellt. \ No newline at end of file diff --git a/projektdokumentation/Inhalt/Fazit.tex b/projektdokumentation/Inhalt/Fazit.tex deleted file mode 100644 index b17a23c..0000000 --- a/projektdokumentation/Inhalt/Fazit.tex +++ /dev/null @@ -1,38 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Fazit} -\label{sec:Fazit} - -\subsection{Soll-/Ist-Vergleich} -\label{sec:SollIstVergleich} - -Bei der rückblickenden Betrachtung des Projektes, wird vom Autor festgehalten, dass die zuvor festgelegten Anforderungen erfüllt wurden. -Die Entwicklung des Projektes hat einen Grundstein für ein modulares Import/Export System von \ac{M2} zu \ac{IX} gelegt, welches allerdings zur vollständigen -Ersetzung der alten Module noch erweitert werden muss. Der Autor hat dies allerdings berücksichtigt und gemäß Abschnitt~\ref{sec:Projektabgrenzung}: \nameref{sec:Projektabgrenzung} -aufgrund des begrenzten Projektumfangs eingeplant. - -Wie der Tabelle~\ref{tab:Vergleich} zu entnehmen ist, konnte ebenfalls die Zeitplanung bis auf wenige Ausnahmen eingehalten werden. - -\tabelle{Soll-/Ist-Vergleich}{tab:Vergleich}{Zeitnachher.tex} - - -\subsection{Lessons Learned} -\label{sec:LessonsLearned} - -Der Autor konnte während des Projektes wertvolle Erfahrungen \bzgl der Planung und Durchführung von Software-Projekten -sammeln. Hierbei wurde besonders deutlich, welch große Bedeutung stetige Rücksprache und Kommunikation mit den Projektbeteiligten -für den Projekterfolg hat. Zusätzlich konnte der Autor neue Kompetenzen und Sicherheiten im Umgang mit \ac{M2} erlangen, welche -für die zukünftige, angestrebte Tätigkeit im \ac{eCommerce} hilfreich sind. - -Abschließend lässt sich sagen, dass die Realisierung des Projektes eine Erleichterung zur alltäglichen Arbeit mit \ac{M2} -Webshops, die eine \ac{IX} Schnittstelle nutzen, darstellt und auch für den Autor während der Entwicklung eine Bereicherung war. - -\subsection{Ausblick} -\label{sec:Ausblick} - -Die im Lastenheft definierten Anforderungen wurden zwar realisiert, dennoch können in Zukunft noch weitere Anforderungen \bzw -Erweiterungsmöglichkeiten entwickelt werden. Es kann \zB die Erweiterung der Benutzeroberfläche in das bestehende \ac{M2} Administrator -Backend als \ac{GUI} vorgenommen werden. Gleichzeitig können die Funktionen um weitere Datentypen erweitert werden, wie \zB -Mediadaten und Bestellungen. Eine Möglichkeit zum Export von allen importierten Daten zu \ac{IX} selbst, sind ebenfalls Aussichten für die Zukunft. - -Aufgrund des im Abschnitt~\ref{sec:Architekturdesign}: \nameref{sec:Architekturdesign} beschriebenen modularen Aufbaus, können die Anpassungen -\bzw Erweiterungen einfach vorgenommen werden. Die Modularität der Anwendung ermöglicht somit eine gute Wart- und Erweiterbarkeit. \ No newline at end of file diff --git a/projektdokumentation/Inhalt/Implementierungsphase.tex b/projektdokumentation/Inhalt/Implementierungsphase.tex deleted file mode 100644 index ea13e66..0000000 --- a/projektdokumentation/Inhalt/Implementierungsphase.tex +++ /dev/null @@ -1,82 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Implementierungsphase} -\label{sec:Implementierungsphase} - -\subsection{Implementierung der Datenstrukturen} -\label{sec:ImplementierungDatenstrukturen} -Wie in Abschnitt~\ref{sec:Datenmodell}: \nameref{sec:Datenmodell} beschrieben, ermöglicht \ac{M2} eine Einbindung von individuell benötigten \acs{SQL} -Tabellen in die vorhandene Datenstruktur. - -Dem \Anhang{app:InstallData} kann ein \acs{XML} entnommen werden, welches der Komponente neusta-m2-intex-base hinzugefügt wurde. -Dieses deklarative Initialisieren von Datenstrukturen wird ebenfalls vom Framework Symfony genutzt. Es ermöglicht dem Entwickler anzugeben, -wie die Datenstruktur einer Tabelle aussehen soll. \ac{M2} bestimmt dann den Unterschied der derzeitigen Tabellenstruktur und der Struktur, die durch -vorhandene \acs{XML} Definitionen angegeben wurde. Diese Unterschiede werden dann durch atomare \acs{SQL} Operationen wiedergespiegelt. -Zusätzlich priorisiert \ac{M2} deklarative Schemen und führt diese generell vor allen älteren Schema \ac{PHP} Scripten aus. - -Die bestehende Datenbank wurde durch o.g. vorgehen um eine Basis-Tabelle erweitert, welche zur Nachvollziehbarkeit der Import-Vorgänge beitragen soll. - -\subsection{Implementierung der Benutzeroberfläche} -\label{sec:ImplementierungBenutzeroberflaeche} - -Die Implementierung der Benutzeroberfläche erfolgte, wie bereits im Abschnitt~\ref{sec:Benutzeroberflaeche}: \nameref{sec:Benutzeroberflaeche} geplant, -mit Hilfe der \ac{M2} eigenen Möglichkeiten zur Einbindung von \ac{CLI}-Befehlen. - -Durch die Entscheidung des Autors, die Anwendung als \ac{M2} Modul umzusetzen, ergibt sich hier der Vorteil, dass die gewünschten und benötigten -\ac{CLI} Befehle per Dependency Injection direkt in die \ac{M2} Befehlsliste aufgenommen werden können. Somit können Entwickler bei der Nutzung der Anwendung -auf das Standard Interface von \ac{M2} zurückgreifen und separate Zugangsdaten oder Aufrufe werden vermieden. - -Um der \ac{M2} Instanz die gewünschten Befehle zuzufügen, wurde die Klasse CliCommand der Komponente neusta-m2-intex-cli hinzugefügt. Diese Klasse -leitet von der abstrakten \ac{M2} Klasse Command ab und bindet in \ac{M2} inkludierte Symfony-Komponenten zur Verarbeitung von Ein- und Ausgabe ein. - -\subsection{Implementierung der Geschäftslogik} -\label{sec:ImplementierungGeschaeftslogik} -Da die Implementierung der Geschäftslogik den Kernbestandteil des gesamten Projektes darstellt, soll diese im folgenden Abschnitt -genauer erläutert werden. Um die Implementierung möglichst komfortabel durchzuführen, wurde die Entwicklungsumgebung JetBrains PHPStorm 2019 hierfür -vom Autor gewählt. - -Zu Beginn der Implementierung wurde das Grundgerüst der Komponenten für die Anwendung erstellt. Hierzu wurde für jede in -Abschnitt~\ref{sec:Geschaeftslogik}: \nameref{sec:Geschaeftslogik} erwähnte Komponente und Subkomponente die Grundlage zur Einbindung als -Composer Package gelegt. Jede Komponente beinhaltet eine \acs{JSON} Datei, die Angaben zum Namen des Packages, der Version, einer Package-Typ Definition -(hier: magento2-module), Abhängigkeiten zu anderen Packages sowie Informationen zum Autor beinhaltet (Beispiel: \Anhang{app:ComposerJson}). Somit konnten die Komponenten -im einzelnen als separates Projekt angesehen werden. - -Nachdem die Grundlagen zur Aufteilung der Anwendung in modulare Komponenten gelegt wurde, befasste sich der Autor damit, die lokale Entwicklungsumgebung aufzusetzen. -Hierzu wurde ein für \ac{M2} bereits vorhandenes Docker \footnote{Docker - \url{https://www.docker.com}} Setup der \ac{NSD} genutzt. Docker ist ein \ac{VM} Container System, welches im genutzten Setup Container für -jeweils den Quellcode der \ac{M2} Instanz, der Datenbank sowie dem benötigten NGINX \footnote{NGINX - \url{https://www.nginx.com/}} Server bereit stellt. Dem Autor wurde hiermit ein natives Aufsetzen einer \ac{M2} Instanz -erspart, was zur Qualität der Entwicklung erheblich beitrug und gleichzeitig garantiert, dass die Anwendung auf der tatsächlichen Serverumgebung lauffähig ist. - -Nach der Fertigstellung des Grundgerüstes und der lokalen Umgebung konnte mit der eigentlichen Implementierung fortgesetzt werden. - -Wie in Abschnitt~\ref{sec:Entwicklungsprozess}: \nameref{sec:Entwicklungsprozess} beschrieben, entschied der Autor sich für eine agile Umsetzung in einer Mischung -aus Kanban und Scrum. Jede einzelne Komponente ergab somit eine Story im Kanban Board, welche nach Scrum Prinzip zusammen mit den Mitarbeitern der \ac{NSD} priorisiert wurden. - -Die Implementierung des Basis Moduls neusta-m2-intex-base wurde zügig Vollzogen, da die Komponente lediglich als Wrapper für alle Funktionen dienen soll. - -Die o.g. Priorisierung gemäß Scrum sah nun vor, dass die Implementierung der Verbindungslogik zu \ac{IX} am wichtigsten ist, da alle weiteren Logik-Komponenten hierrauf aufbauen müssen. -Deswegen soll an dieser Stelle die Implementierung der Komponente neusta-m2-intex-client als Beispiel herangezogen werden. - -Zunächst wurde in der \acs{JSON} Datei für Composer definiert, dass neusta-m2-intex-base die Grundabhängigkeit für das Modul darstellt. So wurden duplizierte -Einträge in der Konfiguration vermieden, da diese bereits in der Komponente neusta-m2-intex-base inkludiert sind. Zusätzlich besteht eine Abhängigkeit zur Komponente -neusta-m2-intex-client-config, da in der Komponente die Konfigurationen für die \ac{IX}-\acs{API} Zugriffe vorgenommen werden sollen. Die Konfigurationen beinhalten neben -den Key-Value Paaren zum Mapping der Produkt- und Nutzerattribute auf den \ac{M2} Standard auch die grundlegenden Informationen wie Passwort und Nutzername zur Verbindung -mit \ac{IX}. - -Die Aufgabe des neusta-m2-intex-client in der Anwendung soll sein, jegliche Datenverbindung von der entwickelnden Anwendung mit der \ac{IX}-\acs{API} -herzustellen und gleichzeitig ein nachvollziehbares Logging dieser Verbindungen und eventuell auftretender Fehler zur Verfügung zu stellen. - -Wie in Abschnitt~\ref{sec:Architekturdesign}: \nameref{sec:Architekturdesign} beschrieben, sah der Entwurf vor, das Factory Design Pattern zu nutzen und so -mehrere Instanzen der Verbindungen zu vermeiden. Hierzu wurde in der Komponente neusta-m2-intex-client die Klasse Factory implementiert, welche die Instanziierung -der Klassen abbildete, die neusta-m2-intex-client der Anwendung zur Verfügung stellen soll. Der Grundgedanke ist hierbei, dass die Komponente zum Import der Nutzerdaten -(hier: neusta-m2-intex-customer) die Factory des neusta-m2-intex-client nutzen und so seine Verbindung zu \ac{IX} herstellen lassen kann. Der Quellcode der Factory kann -dem \Anhang{app:Factory} entnommen werden. - -Um Requests zur \ac{IX}-\acs{API} zu verarbeiten, entschied der Autor, den Open Source \ac{HTTP} Client GuzzlePhp \footnote{GuzzlePhp - \url{https://github.com/guzzle/guzzle}} zu nutzen. Hierdurch erlangte der Autor die Möglichkeit, -asynchrone Requests an die \acs{API} von \ac{IX} zu stellen, ohne einen eigenen \ac{PHP} \acs{HTTP} Client entwickeln zu müssen. - -Die Factory instanziiert nun die beim Aufruf angeforderte Klasse. Hier als Beispiel CustomerConnection (siehe \Anhang{app:CustomerConnection} und \Anhang{app:Connection}), welche im -CustomerDataController in der Komponente neusta-m2-intex-customer instanziiert wird (siehe \Anhang{app:CustomerDataController}). - -Durch den Fokus auf das Fertigstellen der neusta-m2-intex-client Komponente, waren alle folgenden Subkomponenten trivialer zu implementieren, da bei einem Datenimport -die Abfrage der Daten der Hauptbestandteil einer solchen Anwendung darstellt. Dem folgend wurde vom Autor in Reihenfolge die Logik zur Verarbeitung der erhaltenen Daten -implementiert (neusta-m2-intex-customer \& neusta-m2-intex-catalog) sowie die Möglichkeit die Funktionalität über einen \acs{CRON}-Job anstoßen zu können, welche -im \ac{M2} Standard per \acs{XML} Datei inkludiert werden kann. \ No newline at end of file diff --git a/projektdokumentation/Inhalt/Projektarchitektur.tex b/projektdokumentation/Inhalt/Projektarchitektur.tex index d560713..4480dd6 100644 --- a/projektdokumentation/Inhalt/Projektarchitektur.tex +++ b/projektdokumentation/Inhalt/Projektarchitektur.tex @@ -27,7 +27,7 @@ Services übernehmen die Kommunikation mit dem Backend und kapseln die Geschäft \subsubsection{Backend-Architektur} Das Backend implementiert eine klassische mehrschichtige Architektur, die eine klare Trennung der Verantwortlichkeiten gewährleistet. Die Controller-Schicht stellt die REST-\acs{API}-Endpunkte bereit und behandelt \acs{HTTP}-Anfragen. Die Service-Schicht enthält die Geschäftslogik und orchestriert verschiedene Use Cases. -Die Repository-Schicht abstrahiert den Datenzugriff und verwendet Spring Data JPA für die Kommunikation mit der Datenbank. Entity-Klassen repräsentieren die Domain-Modelle und bilden die Datenbankstrukturen ab. +Die Repository-Schicht abstrahiert den Datenzugriff und verwendet Spring Data JPA für die Kommunikation mit der Datenbank. Entity-Klassen repräsentieren die Domain-Modelle und bilden die Datenbankstrukturen ab. Eine detaillierte Darstellung der verschiedenen Architekturschichten mit konkreten Code-Beispielen findet sich im Anhang (siehe \ref{app:CodeSchichten}). \subsection{Datenarchitektur} Die Datenbank folgt einem relationalen Design mit klar definierten Entitätsbeziehungen. Das Schema gliedert sich in mehrere Hauptbereiche: Der User Management Bereich verwaltet Benutzerkonten und Benutzerprofile. Spielbezogene Daten wie Spielstände, Wetten und Ergebnisse werden in separaten Tabellen gespeichert, um die Integrität der Spiellogik zu gewährleisten. diff --git a/projektdokumentation/Inhalt/Projektplanung.tex b/projektdokumentation/Inhalt/Projektplanung.tex deleted file mode 100644 index e603f7e..0000000 --- a/projektdokumentation/Inhalt/Projektplanung.tex +++ /dev/null @@ -1,48 +0,0 @@ -% !TEX root = ../Projektdokumentation.tex -\section{Projektplanung} -\label{sec:Projektplanung} - - -\subsection{Projektphasen} -\label{sec:Projektphasen} - -Für die Umsetzung des Projektes standen dem Autor 70 Stunden zur Verfügung. Zu Projektbeginn wurden diese auf, wie in der -Softwareentwicklung üblich, verschiedene Phasen verteilt, die während der Entwicklung durchlaufen werden. - -Eine grobe Zeitplanung sowie die Hauptphasen lassen sich der Tabelle~\ref{tab:Zeitplanung} entnehmen. -Eine Pufferzeit wurde bereits in der Planung der Implementierung inkludiert. -Die Hauptphasen werden außerdem noch in kleinere Unterpunkte zerlegt. Eine detaillierte Übersicht der Phasen befindet sich im \Anhang{app:Zeitplanung}. - -\tabelle{Zeitplanung}{tab:Zeitplanung}{ZeitplanungKurz}\\ - -\subsection{Ressourcenplanung} -\label{sec:Ressourcenplanung} - -Eine genaue Auflistung der verwendeten Ressourcen, welche für das Projekt eingesetzt wurden, kann der Übersicht im -\Anhang{app:Ressourcen} entnommen werden. Hiermit sind sowohl Hard- und Softwareressourcen als auch Personal vom Autor berücksichtigt worden. -Bei der Auswahl der verwendeten Software wurde darauf geachtet, dass diese kostenfrei (\zB als Open Source) zur Verfügung -steht oder die \ac{NSD} bereits Lizenzen für diese besitzt. Hierdurch sollen anfallende Projektkosten so gering wie möglich -gehalten werden. - - - -\subsection{Entwicklungsprozess} -\label{sec:Entwicklungsprozess} - -Bevor mit der Realisierung des Projektes begonnen werden konnte, musste sich der Autor für eine geeignete Vorgehensweise zur Umsetzung entscheiden. -Der Autor hat sich auf einen agilen Entwicklungsprozess festgelegt. Hierbei wird in Anlehnung -an das Vorgehensmodell Kanban \footnote{Wikipedia Kanban Definition - \url{https://en.wikipedia.org/wiki/Kanban}} gearbeitet, welches durch Elemente des Vorgehensmodells Scrum \footnote{Scrum.org - \url{https://www.scrum.org}} erweitert werden soll. -Die für Scrum typischen Iterationen der Projektphasen sowie die damit verbundene, stetige Rücksprache -mit den Stakeholdern sind einige Merkmale, die diesen agilen Entwicklungsprozess auszeichnen und in diesem Abschlussprojekt Anwendung finden. - -Eine flexible Umsetzung der Anforderung wird durch die relativ kurzen Entwicklungszyklen ermöglicht. Hierdurch können den Mitarbeitern der \ac{NSD} -zeitnah Resultate präsentiert werden. Aufgrund dieser Tatsache wurde bei der Projektplanung in Abschnitt~\ref{sec:Projektphasen}: \nameref{sec:Projektphasen} für die Entwurfsphase -weniger Zeit eingeplant, da sich Teile dieser Phase erst im Laufe der Entwicklung der Anwendung ergeben. - -Das stetige Feedback zur Anwendung, resultierend aus der engen Kommunikation mit den Mitarbeitern, gewährleistet eine bessere und flexiblere Reaktionsfähigkeit -auf Änderungswünsche. So können die Kollegen des Autors während der Entwicklung mit dem System vertraut gemacht werden, welches zur Folge den Vorteil bringt, -dass bei Projektabnahme und -einführung Zeit eingespart werden kann. Dies wurde vom Autor in der Zeitkalkulation bereits berücksichtigt. - -Außerdem soll der agile Entwicklungsprozess durch die Praktik der testabgedeckten Entwicklung erweitert werden. Hierbei werden Softwaretests nach der Implementierung -des Quellcodes erstellt. Dies hat zum Vorteil, dass nachträgliche Änderungen immer das gleiche Endresultat in der Datenausgabe erwarten und erhöht somit die Wartbarkeit -der gesamten Anwendung. diff --git a/projektdokumentation/Inhalt/Vorbereitung.tex b/projektdokumentation/Inhalt/Vorbereitung.tex new file mode 100644 index 0000000..0f74afe --- /dev/null +++ b/projektdokumentation/Inhalt/Vorbereitung.tex @@ -0,0 +1,27 @@ +\section{Vorbereitung} +\label{sec:Vorbereitung} + +\subsection{Ist-Analyse} +Im Rahmen der durchgeführten Marktanalyse konnten mehrere relevante Marktlücken identifiziert werden, die das geplante Produkt gezielt adressieren kann. Ein zentrales Defizit betrifft die technologische Basis vieler bestehender Casino-Plattformen. Zahlreiche Anbieter setzen noch auf veraltete Technologien, was sich nachteilig auf Performance, Wartbarkeit und Erweiterbarkeit auswirkt. Moderne Webtechnologien und Frameworks könnten in diesem Zusammenhang klare Vorteile schaffen, etwa durch schnellere Ladezeiten und verbesserte Skalierbarkeit. + +Im Bereich der Benutzerfreundlichkeit bestehen Defizite. Viele Plattformen bieten eine unzureichende mobile Nutzererfahrung oder verlangen komplexe, zeitaufwändige Registrierungsprozesse – oft ohne Social-Login oder einfache Authentifizierung. Ein Beispiel hierfür ist der Zwang zu langwierigen Formularen, die Nutzer gerade auf mobilen Geräten häufig frustrieren und zum Abbruch des Vorgangs führen. + +Ein weiteres Problem liegt bei den Sicherheitsstandards. In zahlreichen Anwendungen sind moderne Authentifizierungsverfahren wie OAuth2 oder Zwei-Faktor-Authentifizierung noch nicht implementiert. Dies hat nicht nur zur Folge, dass das Vertrauen der Nutzer geschwächt wird, sondern öffnet auch potenzielle Sicherheitslücken. + +Schließlich bestehen Defizite in der Integration zeitgemäßer Zahlungsprozesse. Oft sind Einzahlungen umständlich und erfordern manuelle Schritte, da moderne Payment-APIs wie Stripe, Apple Pay oder Google Pay nicht eingebunden sind. Ein reibungsloser, mobiltauglicher Zahlungsfluss könnte sich in diesem Zusammenhang als entscheidender Wettbewerbsvorteil erweisen. + +\subsection{Soll-Analyse} +Für das geplante Online-Casino wurde eine umfassende Soll-Analyse durchgeführt, die die zentralen funktionalen, technischen und sozialen Anforderungen beschreibt. + +Im Bereich des Spieleportfolios ist eine ausgewogene Mischung aus klassischen und unterhaltsamen Spielen vorgesehen. Zu den angebotenen Spielen zählen Blackjack mit erweiterten Spieloptionen wie Split und Double Down sowie verschiedene Slotmaschinen, deren RTP (Return to Player) flexibel konfigurierbar sein soll. Das Angebot wird durch einfache Zufallsspiele wie Dice, Coinflip sowie unterhaltungsorientierte Features wie Lootboxen, Plinko und Poker ergänzt, um unterschiedliche Spieltypen anzusprechen und die Nutzer langfristig zu binden. + +Die Benutzerverwaltung basiert auf einem modernen, sicheren Authentifizierungssystem. Die Anmeldung erfolgt über eine Multi-Provider-OAuth2-Lösung, beispielsweise mit GitHub oder Google-Konten. Die Sitzungsverwaltung erfolgt über JWT-basierte Tokens, ergänzt durch zusätzliche Sicherheitsmechanismen wie E-Mail-Verifizierung und die Möglichkeit zum Passwort-Reset, um Datenschutz und Benutzerkomfort gleichermaßen zu gewährleisten. + +Das Finanzsystem ist auf Einzahlungen in Echtzeit ausgerichtet. Zu diesem Zweck wird eine Stripe-Integration implementiert, die einen reibungslosen und sicheren Zahlungsprozess ermöglicht. Intern erfolgt die Verwaltung der Guthaben über eine virtuelle Währung, deren Genauigkeit mithilfe von BigDecimal präzise nachvollziehbar bleibt. Eine lückenlos nachvollziehbare Transaktionshistorie mit Status-Tracking gewährleistet maximale Transparenz und Nachvollziehbarkeit aller Zahlungsvorgänge. + +Gemäß den technischen Anforderungen ist ein responsives Design mit Fokus auf Mobile-First-Nutzung erforderlich, um eine hohe Benutzerfreundlichkeit auf verschiedenen Plattformen zu gewährleisten. Echtzeitaktualisierungen der Inhalte sollen ohne erneuten Seitenaufbau erfolgen, um eine nahtlose und dynamische Spielerfahrung zu gewährleisten. Es ist essenziell, dass sämtliche API-Kommunikation über gesicherte Schnittstellen abgewickelt wird, um die Integrität der Daten und den Schutz sensibler Informationen sicherzustellen. + +Schließlich spielen auch die sozialen Funktionen eine wichtige Rolle. Ranglisten, eine motivierende In-Game-Währung sowie ein Fokus auf Transparenz im Umgang mit Daten, Spielverläufen und Zahlungsflüssen sollen die Community stärken, die Nutzerbindung fördern und das Vertrauen in das Produkt nachhaltig unterstützen. Das Produkt wird als moderne Webanwendung direkt über den Browser bereitgestellt und ist somit ohne Download oder Installation für den Nutzer zugänglich. Um das Online-Casino nutzen zu können, sind einige technische Voraussetzungen erforderlich. Für die Anwendung wird ein aktueller Webbrowser wie Google Chrome, Mozilla Firefox, Safari oder Microsoft Edge vorausgesetzt. Zudem ist JavaScript aktiviert sein, da dieses für die Darstellung der Spielmechanik und der Benutzeroberfläche essenziell ist. Für eine reibungslose Kommunikation mit dem Server und ein flüssiges Spielerlebnis ist eine stabile Internetverbindung erforderlich. Zusätzlich ist die Erlaubnis von Cookies erforderlich, um Sitzungsdaten zu speichern und personalisierte Inhalte oder Nutzertracking zu ermöglichen. + +Die genannten technischen Voraussetzungen bilden die Grundlage für einen stabilen und benutzerfreundlichen Zugriff auf die Anwendung. Abgesehen von den Basiskomponenten ergeben sich jedoch weiterführende Anforderungen an die Systemarchitektur, insbesondere im Hinblick auf die Sicherheit und die Fairness der Spielergebnisse. +Eine zentrale Herausforderung bei der technischen Umsetzung des Online-Casinos liegt in der sicheren und manipulationssicheren Spielauswertung. Um die Integrität des Spiels zu gewährleisten und Manipulationen durch Nutzer im Frontend zu verhindern, müssen sämtliche Spielmechaniken serverseitig ausgewertet werden. Dies bedeutet, dass Zufallsberechnungen, Spielergebnisse und Gewinnermittlungen ausschließlich auf dem Server erfolgen, bevor sie an das Frontend übermittelt werden. Diese Architektur gewährleistet, dass die Spielchancen stets fair und unveränderbar bleiben. Gleichzeitig erfordert sie eine besonders zuverlässige Server-Infrastruktur, da sie sowohl in Echtzeit als auch mit hoher Verfügbarkeit arbeiten muss. Diese Anforderung stellt eine bedeutsame technische Einschränkung dar, die bei der Systemarchitektur, der Performanceoptimierung sowie der Skalierung von Beginn an zu berücksichtigen ist. \ No newline at end of file diff --git a/projektdokumentation/Inhalt/WirtschaftlicheBetrachtung.tex b/projektdokumentation/Inhalt/WirtschaftlicheBetrachtung.tex new file mode 100644 index 0000000..4790ed2 --- /dev/null +++ b/projektdokumentation/Inhalt/WirtschaftlicheBetrachtung.tex @@ -0,0 +1,67 @@ +\section{Wirtschaftliche Betrachtung} +\subsection{Marktuntersuchung} +Das Online-Casino fokussiert sich in erster Linie auf eine junge, technikaffine Zielgruppe im Alter von 18 bis 35 Jahren. Diese Nutzergruppe verfügt über Erfahrungen mit digitalen Anwendungen, zeigt eine hohe Bereitschaft für Internetaktivitäteten und ist für neue, spielerische Unterhaltungsformate insbesondere im Bereich des Web-Gamings aufgeschlossen. Sie sucht nach kurzweiligen, optisch ansprechenden Angeboten, die jederzeit und ohne große Einstiegshürde zugänglich sind. +Als sekundäre Zielgruppe werden Gelegenheitsspieler angesprochen, die besonderen Wert auf eine einfache, benutzerfreundliche Bedienung legen. Für diese Nutzer steht nicht die Technik, sondern das unkomplizierte Spielvergnügen im Vordergrund. Die Nutzerinnen und Nutzer erwarten eine klare Navigation, intuitive Spielmechaniken und möglichst wenig Hürden bei Registrierung, Einzahlung und Nutzung. Durch die Fokussierung auf zwei Zielgruppen soll eine breite Nutzerbasis aufgebaut werden, die sowohl regelmäßige als auch spontane Spieler umfasst. + +Die Erwartungshaltung dieser Zielgruppe umfasst ein unterhaltsames, fesselndes und optisch ansprechendes Spielerlebnis, das eine authentische Casino-Atmosphäre vermittelt. Dabei legen die Nutzer großen Wert auf eine intuitive Benutzeroberfläche, schnelle Ladezeiten sowie abwechslungsreiche Spiele wie Slots, Blackjack oder CoinFlip. Gleichzeitig legen sie großen Wert auf einen reibungslosen und sicheren Zugang zum Spiel. Aus diesem Grund erwarten sie selbstverständlich moderne Mechanismen für eine zuverlässige und geschützte Anmeldung und Nutzung. + +Die Erwartungen der Zielgruppe geben wichtige Hinweise darauf, welche Funktionen und Eigenschaften ein erfolgreiches Produkt aufweisen muss. Um die gestellten Erwartungen jedoch auch unter wirtschaftlichen Gesichtspunkten bedienen zu können, ist eine Analyse des Marktvolumens und -potenzials unerlässlich. +Der Markt für Social Casinos und Online-Casinos mit Auszahlungsverweigerung ist weltweit wachsend. Laut Branchenanalysen (z.B. Statista, Business Research Insights) liegt das Volumen des globalen Social-Casino-Markts bei mehreren Milliarden USD pro Jahr, mit jährlichen Wachstumsraten im hohen einstelligen Prozentbereich. In Zielmärkten wie den USA, Europa und Teilen Asiens ist das Potenzial besonders hoch, insbesondere bei Nutzern, die Glücksspiel aus rechtlichen oder moralischen Gründen meiden, aber den Spielspaß schätzen. + +Das vorhandene Absatzpotential ist jedoch stark eingeschränkt auf eine klar umrissene Zielgruppe. Es richtet sich an Nutzer, die Glücksspiele primär als Entertainment betrachten und sich der Tatsache bewusst sind, dass keine Auszahlung möglich ist. In diesem Segment könnte eine emotionale Markenbindung ähnlich wie bei Gaming- oder Streaming-Abonnements aufgebaut werden. Nichtsdestotrotz ist das Marktvolumen im Vergleich zu klassischen Casino-Plattformen begrenzt, da der Reiz vieler Online-Casinos im potenziellen Gewinn liegt. + +Die Wettbewerbssituation für das geplante Online-Casino ohne Auszahlungsoption ist als intensiv und dynamisch zu bezeichnen, da sich das Produkt in einem stark umkämpften digitalen Unterhaltungsmarkt bewegt. Das Wettbewerbsumfeld wird dabei von zwei Hauptarten von Konkurrenzprodukten geprägt. Einerseits klassische Online-Casinos mit Echtgeld-Auszahlung, die aufgrund der Aussicht auf reale Geldgewinne für viele Nutzer besonders attraktiv sind. Es sei darauf hingewiesen, dass renommierte Anbieter wie 888casino, LeoVegas, Stake oder Tipico Casino in der Regel staatlich lizenziert sind, ein umfangreiches Spielangebot offerieren und von hoher Markenbekanntheit sowie intensiven Marketingaktivitäten profitieren. Andererseits existieren Social Casinos ohne Auszahlungsfunktion, die in direkter Konkurrenz zum geplanten Produkt stehen. Plattformen wie Slotomania, House of Fun, Big Fish Casino oder DoubleDown Casino ermöglichen den Einsatz von Echtgeld, bieten jedoch keine reale Auszahlung. Stattdessen liegt der Fokus auf Unterhaltung, Gamification, täglichen Belohnungen, virtuellen Währungen und exklusiven VIP-Features. Diese Angebote sind in der Regel als Apps verfügbar, verfügen über eine große Nutzerbasis und arbeiten mit durchdachten Mechaniken zur langfristigen Nutzerbindung. + +Die enorme Verbreitung und Beliebtheit dieser Social-Casino-Plattformen wirft die Frage auf, welche konkreten Stärken und Schwächen diese bestehenden Angebote aufweisen. Ein näherer Blick auf die Vor- und Nachteile der Konkurrenzprodukte liefert wichtige Erkenntnisse für die strategische Ausrichtung. +So ist liegt ein zentraler Vorteil bestehender Social-Casino-Produkte in der transparenten Erwartungshaltung der Nutzer. Da keine Auszahlungen von Echtgeld vorgesehen sind, besteht kein Missverständnis über mögliche Gewinne. Zudem unterliegen diese Angebote häufig geringeren regulatorischen Anforderungen, da sie rechtlich nicht als klassisches Glücksspiel eingestuft werden und somit oft keine spezielle Lizenz benötigen. Der gezielte Einsatz von Gamification-Elementen und sozialen Funktionen wie Ranglisten oder täglichen Herausforderungen führt auf vielen dieser Plattformen zu einer hohen Nutzerbindung. +Gleichzeitig sind bei diesen Modellen gewisse Nachteile zu berücksichtigen. Da reale Gewinne ausgeschlossen sind, ist die Zahlungsbereitschaft der Nutzer in der Regel geringer. Wird das Belohnungssystem als wenig attraktiv oder zu repetitiv wahrgenommen, sinkt die Verweildauer auf der Plattform schnell. Des Weiteren bedienen sich zahlreiche dieser Produkte sogenannter Pay-to-Win-Mechaniken, welche den zahlenden Nutzern Vorteile gegenüber anderen Teilnehmern verschaffen. Dieser Umstand resultiert bei der Spielerschaft häufig in Frustration und Unzufriedenheit. +Um sich in dieser Wettbewerbslandschaft zu behaupten, muss sich das neue Produkt durch klare Kommunikation, hohe Benutzerfreundlichkeit, attraktive Preisgestaltung sowie ein überzeugendes Unterhaltungs- und Belohnungssystem von der Masse abzuheben, um sich erfolgreich zu behaupten. Die Transparenz über den Verzicht auf Auszahlungen sowie eine hochwertige, faire Spielerfahrung sind von entscheidender Bedeutung, um Vertrauen aufzubauen und langfristige Nutzerbindung zu erreichen. + +Obwohl das geplante Geschäftsmodell einige Vorteile und einen innovativen Ansatz bietet, sollten auch dessen potenzielle Risiken nicht außer Acht gelassen werden. Rechtlich besteht die Möglichkeit, dass das Angebot in bestimmten Ländern dennoch dem Glücksspielrecht unterliegt, auch wenn keine Auszahlungen von Echtgeld erfolgen. Dies kann zu regulatorischen Hürden oder Einschränkungen bei der Vermarktung führen. Es empfiehlt sich, auch auf reputativer Ebene Vorsicht walten zu lassen. Das Modell könnte von Teilen der Öffentlichkeit oder den Medien als irreführend oder potenziell ausbeuterisch wahrgenommen werden, insbesondere wenn hohe In-App-Ausgaben ohne reale Gegenleistung entstehen. +Ein weiteres Risiko betrifft die Marktakzeptanz. Da keine echten Gewinne erzielt werden können, besteht die Gefahr, dass potenzielle Nutzer dem Angebot mit geringem Interesse begegnen oder es schnell wieder verlassen. Die Kaufschwelle ist in diesem Zusammenhang von großer Bedeutung. Ohne die Aussicht auf Rückgewinn oder reale Belohnung wäre die Bereitschaft, für virtuelle Inhalte Geld auszugeben, deutlich geringer als bei klassischen Echtgeld-Casinos. + +Aus den genannten Chancen und Risiken ergeben sich klare Anforderungen für das Projekt. Es ist von besonderer Wichtigkeit, dass die Spielbedingungen stets transparent dargestellt werden und die Nutzer darüber informiert werden, dass keine Auszahlungen von Echtgeld erfolgen. Um rechtliche Schwierigkeiten zu vermeiden, ist zudem eine umfassende rechtliche Prüfung in allen relevanten Zielmärkten erforderlich. Auf echte Gewinnchancen muss verzichtet werden, dennoch ist das Nutzererlebnis attraktiv zu gestalten. Dies kann beispielsweise durch die Implementierung von Gamification-Elementen, ansprechendem visuellen Feedback und sozialen Features, welche die Unterhaltung fördern, realisiert werden. Gleichzeitig ist ein ethisches Branding erforderlich, das das Produkt deutlich von traditionellen Glücksspielanbietern abgrenzt. Schließlich sollten innovative Monetarisierungsmodelle zum Einsatz kommen, wie Abonnements, Mikrotransaktionen oder auch Spendenmechanismen, um wirtschaftlich erfolgreich zu sein. + + +\subsection{Marketing Mix} + +\subsubsection{Preispolitik} +Bei der Markteinführung ist eine Positionierung auf einem niedrigen bis mittleren Preisniveau vorgesehen. Das Ziel besteht darin, die Einstiegshürde möglichst gering zu halten und dadurch eine breite Zielgruppe zum Ausprobieren zu motivieren. Nutzer können bereits mit geringen Beträgen ab etwa 1 bis 5 Euro spielen. Zur Steigerung der Attraktivität tragen Willkommensboni, Freispiele oder die Verdopplung der ersten Einzahlung bei. Diese Maßnahmen positionieren das Produkt klar als unterhaltungsorientiertes, risikoarmes Angebot, das sich bewusst von klassischen Echtgeld-Casinos mit hoher finanzieller Schwelle abgrenzt. + +Im Laufe des Produktlebenszyklus ist eine flexible Anpassung des Preismodells vorgesehen. In der Einführungsphase werden Niedrigpreise und Rabatte eingesetzt, um Nutzer zu gewinnen. In der Wachstumsphase besteht die Möglichkeit, größere Pakete einzuführen, wie beispielsweise Monatsabonnements oder Coin-Bundles. Während der Reifephase rücken Maßnahmen wie das Up-Selling in den Fokus, etwa durch den Verkauf von kosmetischen Items, Sonderfunktionen oder VIP-Zugängen. In der Sättigungsphase dienen zeitlich begrenzte Rabatte, Sonderaktionen und Events der Reaktivierung inaktiver Nutzer. Preisänderungen sollen stets mit neuen Inhalten, Features oder Events kombiniert werden, um die Zahlungsbereitschaft zu steigern und zu legitimieren. + +Als zentrale Preisstrategie kommt eine Kombination aus Promotions- und Bonusstrategien zum Einsatz. Hierzu zählen insbesondere Treueprämien und VIP-Stufenprogramme sowie zeitlich befristete Sonderangebote, wie etwa Freispiele am Wochenende. Die vorliegende Strategie zielt darauf ab, kurzfristig eine große Anzahl an Nutzern zu gewinnen, diese emotional an das Produkt zu binden und sie zur wiederholten Einzahlung zu motivieren, obwohl eine Auszahlung in Echtgeld nicht möglich ist. + +Darüber hinaus sind Preisdifferenzierungen ein zentraler Bestandteil der Monetarisierung. Es ist eine segmentbasierte Differenzierung geplant, bei der Gelegenheitsspieler kleinere Pakete erhalten, während Vielspieler Zugang zu größeren, exklusiveren Angeboten haben. Darüber hinaus wäre auch eine zeitliche Preisdifferenzierung, wie etwa Rabatte zu bestimmten Tageszeiten oder saisonalen Events, vorstellbar. Ergänzend werden psychologische Preisstrategien eingesetzt, wie etwa die Preisgestaltung mit Schwellenwerten (z. B. 4,99 € statt 5,00 €), um die Zahlungsbereitschaft der Kunden auf subtilere Weise zu fördern. + +Die Preisgestaltung verfolgt insgesamt eine wachstumsorientierte Strategie, die Nutzer sowohl in der frühen als auch in der langfristigen Nutzung des Produkts optimal anspricht und gleichzeitig wirtschaftlich tragfähig bleibt. + +\subsubsection{Kommunikationspolitik} +Das Produkt soll mittels einer strategisch ausgerichteten Werbestrategie, die verschiedene Kommunikationskanäle einbezieht, bekannt gemacht werden. Im Mittelpunkt stehen dabei Social-Media-Plattformen wie Meta (Facebook), TikTok und Instagram. Dort besteht die Möglichkeit, visuell ansprechende Kurzvideos zu veröffentlichen, die Spielspaß, schnelle Action und Belohnungssysteme in den Vordergrund stellen. Des Weiteren empfiehlt sich die Durchführung von Influencer-Marketing, um eine authentische Reichweite und ein Vertrauenverhältnis aufzubauen. Darüber hinaus erweisen sich Mobile Ads, also In-App-Werbung in anderen Spielen oder Anwendungen, als besonders effektiv, da sie spielaffine und potenziell zahlungsbereite Nutzer direkt im Nutzungskontext erreichen. + +Ein weiterer wichtiger Kanal ist das Suchmaschinenmarketing, insbesondere über Google Ads. In diesem Kontext ist die Implementierung zielgerichteter Kampagnen mit spezifischen Keywords wie "kostenlos spielen", "Online Slots", "Casino ohne Auszahlung" oder "Spielspaß mit Echtgeld" ratsam. Dabei ist es essenziell, den Nutzer stets einen eindeutigen Hinweis zu präsentieren, dass die Erzielung von Echtgeldgewinnen nicht möglich ist. Darüber hinaus besteht die Möglichkeit, Streaming-Plattformen wie Twitch und YouTube zu nutzen, indem mit Streamern kooperiert wird, die unterhaltsames Gameplay zeigen und dabei nicht den Gewinn, sondern das Spielerlebnis betonen. + +In allen Kanälen ist eine klare und transparente Kommunikation von essentieller Bedeutung, in welcher darauf hingewiesen wird, dass keine Auszahlungsfunktion zur Verfügung steht. Die Werbung muss das Produkt eindeutig als Entertainment-Angebot und nicht als Glücksspiel mit Gewinnerwartung positionieren, um sowohl die Nutzererwartung korrekt zu steuern als auch rechtlichen Risiken vorzubeugen. + +Die Werbemaßnahmen sollen darauf abzielen, zentrale Produkteigenschaften und Mehrwerte zu kommunizieren, die das geplante Unterhaltungs-Casino von der Konkurrenz abheben. Im Mittelpunkt steht dabei die technische und visuelle Qualität des Angebots, wie schnelle Ladezeiten, eine intuitive Bedienoberfläche sowie hochwertige Grafiken und flüssige Animationen sollen ein modernes und ansprechendes Nutzererlebnis vermitteln. Gleichzeitig wird großer Wert auf Transparenz gelegt, insbesondere durch klare Hinweise auf den Unterhaltungscharakter des Spiels, etwa durch Formulierungen wie "Kein echtes Glücksspiel – reines Entertainment". + +Darüber hinaus ist es von entscheidender Bedeutung, die niedrigen Einstiegshürden deutlich zu kommunizieren. Durch die Bereitstellung von Willkommensangeboten, geringen Einstiegskosten und einer einfachen Einzahlung über moderne Zahlungsschnittstellen wird die Hemmschwelle für neue Nutzer gesenkt. Im Bereich der Sicherheit wird durch die Implementierung von OAuth2 auf aktuelle Standards gesetzt, was ebenfalls als vertrauensbildendes Element in der Werbung hervorgehoben werden kann. Die Intention der kommunizierten Informationen ist es, das Produkt als leicht zugänglich, sicher, unterhaltsam und fair zu positionieren. + +\subsubsection{Distributionspolitik} +Das Produkt wird als moderne Webanwendung direkt über den Browser bereitgestellt und ist somit ohne Download oder Installation für den Nutzer zugänglich. Um das Online-Casino nutzen zu können, sind einige technische Voraussetzungen erforderlich. Für die Anwendung wird ein aktueller Webbrowser wie Google Chrome, Mozilla Firefox, Safari oder Microsoft Edge vorausgesetzt. Zudem ist JavaScript aktiviert sein, da dieses für die Darstellung der Spielmechanik und der Benutzeroberfläche essenziell ist. Für eine reibungslose Kommunikation mit dem Server und ein flüssiges Spielerlebnis ist eine stabile Internetverbindung erforderlich. Zusätzlich ist die Erlaubnis von Cookies erforderlich, um Sitzungsdaten zu speichern und personalisierte Inhalte oder Nutzertracking zu ermöglichen. + +Um ein optimales Spielerlebnis zu gewährleisten, wird die Nutzung auf einem Desktop-Computer oder Tablet mit ausreichend großem Bildschirm empfohlen, da dies die Übersichtlichkeit und Bedienbarkeit deutlich verbessert. Die Nutzung ist insbesondere dann stabil und sicher, wenn das Betriebssystem aktualisiert ist. Als aktuelle Versionen kommen in diesem Fall Windows 10 oder höher, macOS ab Version 11 sowie die jeweils aktuellen Versionen von Android oder iOS in Betracht. Die Webanwendung zeichnet sich insgesamt durch ihre Flexibilität und Plattformunabhängigkeit aus und ist mit gängigen Geräten und Standards problemlos kompatibel. + + +\subsection{Wirtschaftlichkeitsbetrachtung} +Die Wirtschaftlichkeit des geplanten Produkts ist grundsätzlich als sehr hoch einzuschätzen, sofern zentrale Rahmenbedingungen erfüllt sind. Ein entscheidender Vorteil besteht darin, dass sämtliche Einzahlungen als Einnahmen verbucht werden können, da es keine Auszahlungsverpflichtungen gibt. Dies ist ein klarer Unterschied zu klassischen Online-Casinos. Gleichzeitig fallen geringe variable Kosten pro Nutzer an, da weder physische Produkte hergestellt noch verschickt werden müssen und auch keine echten Geldgewinne ausbezahlt werden. Das Geschäftsmodell ist darüber hinaus hochgradig skalierbar. Ist die Plattform erst einmal technisch stabil aufgebaut, kann sie mit nur geringem zusätzlichem Aufwand von tausenden oder sogar Millionen Nutzern gleichzeitig genutzt werden. + +Die möglichen Einnahmequellen sind vielfältig. Neben den klassischen Echtgeld-Einzahlungen bieten sich zusätzliche Monetarisierungswege an, etwa durch In-App-Verkäufe, wie kosmetische Upgrades oder VIP-Status, durch Werbung innerhalb der Plattform oder über Affiliate-Kooperationen mit passenden Partnern. Diese Faktoren tragen dazu bei, dass das Modell aus wirtschaftlicher Sicht äußerst attraktiv erscheint. + +Die Rentabilität ist jedoch von mehreren kritischen Erfolgsfaktoren abhängig. Zu den erforderlichen Maßnahmen zählen die rechtliche Absicherung in den Zielmärkten, eine ausreichend hohe Nutzerakzeptanz trotz fehlender Auszahlungsfunktion und insbesondere die Fähigkeit, eine langfristige Kundenbindung durch ein unterhaltsames, faires und transparentes Spielerlebnis sicherzustellen. + +Dennoch sind bei derartigen Unternehmungen stets die bestehenden Risiken zu berücksichtigen. Auf rechtlicher Ebene besteht die Gefahr, dass das Angebot mit echtem Glücksspiel verwechselt wird. Sollte der Eindruck entstehen, dass Nutzer reale Gewinne erwarten dürfen, so könnte dies rechtlich als Täuschung gewertet werden. Dies könnte mit strafrechtlichen Konsequenzen verbunden sein. Zudem existieren international unterschiedliche Regulierungen im Glücksspielrecht, die auch sogenannte Social Casinos betreffen können, etwa durch Lizenzpflichten oder strenge Anforderungen an die AGB und die Nutzeraufklärung. + +Auch auf Ebene der Markenreputation können Risiken entstehen. Sollten Nutzer erst im Nachhinein erkennen, dass keine Auszahlung möglich ist, könnten sie sich getäuscht fühlen. Dies könnte sich in Form von negativen Bewertungen, Beschwerden oder sogar Shitstorms auf Social Media und Plattformen wie Trustpilot äußern. + +Zudem ist der Markt von hoher Wettbewerbsintensität geprägt, in dem sowohl etablierte Online-Casinos als auch renommierte Anbieter von Social Games bereits eine starke Marktposition innehaben. Die Monetarisierung eines Produkts kann nur dann erfolgreich sein, wenn es gelingt, die Nutzer trotz fehlender Gewinnaussicht emotional an das Produkt zu binden und sie zum freiwilligen Erwerb virtueller Inhalte zu motivieren. An dieser Stelle wird sich letztlich entscheiden, ob das vorhandene wirtschaftliche Potenzial auch realisiert werden kann. diff --git a/projektdokumentation/Listings/CoinflipComponent.ts b/projektdokumentation/Listings/CoinflipComponent.ts new file mode 100644 index 0000000..da53f97 --- /dev/null +++ b/projektdokumentation/Listings/CoinflipComponent.ts @@ -0,0 +1,247 @@ +import { NgClass, NgIf, CurrencyPipe, CommonModule } from '@angular/common'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + inject, + OnInit, + signal, + ViewChild, +} from '@angular/core'; +import { AnimatedNumberComponent } from '@blackjack/components/animated-number/animated-number.component'; +import { catchError, finalize } from 'rxjs/operators'; +import { of } from 'rxjs'; +import { AuthService } from '@service/auth.service'; +import { AudioService } from '@shared/services/audio.service'; +import { CoinflipGame, CoinflipRequest } from './models/coinflip.model'; + +@Component({ + selector: 'app-coinflip', + standalone: true, + imports: [AnimatedNumberComponent, CurrencyPipe, FormsModule, CommonModule, NgIf, NgClass], + templateUrl: './coinflip.component.html', + styleUrl: './coinflip.component.css', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export default class CoinflipComponent implements OnInit { + currentBet = signal(10); + balance = signal(0); + gameInProgress = signal(false); + isActionInProgress = signal(false); + gameResult = signal(null); + betInputValue = signal(10); + errorMessage = signal(''); + isInvalidBet = signal(false); + + @ViewChild('coinElement') coinElement?: ElementRef; + + audioService = inject(AudioService); + authService = inject(AuthService); + private http = inject(HttpClient); + + private coinflipSound?: HTMLAudioElement; + + ngOnInit(): void { + // Abonniere Benutzerupdates fuer Echtzeitaktualisierungen des Guthabens + this.authService.userSubject.subscribe((user) => { + if (user) { + this.balance.set(user.balance); + } + }); + + // Initialisiere Muenzwurf-Sound + this.coinflipSound = new Audio('/sounds/coinflip.mp3'); + } + + setBetAmount(percentage: number) { + const newBet = Math.floor(this.balance() * percentage); + this.betInputValue.set(newBet > 0 ? newBet : 1); + this.currentBet.set(this.betInputValue()); + } + + updateBet(event: Event) { + const inputElement = event.target as HTMLInputElement; + let value = Number(inputElement.value); + + // Setze ungueltigen Einsatz-Status zurueck + this.isInvalidBet.set(false); + + // Erzwinge Mindesteinsatz von 1 + if (value <= 0) { + value = 1; + } + + // Begrenze Einsatz auf verfuegbares Guthaben und zeige Feedback + if (value > this.balance()) { + value = this.balance(); + // Visuelles Feedback anzeigen + this.isInvalidBet.set(true); + // Zeige den Fehler kurz an + setTimeout(() => this.isInvalidBet.set(false), 800); + // Aktualisiere das Eingabefeld direkt, um dem Benutzer den maximalen Wert anzuzeigen + inputElement.value = String(value); + } + + // Aktualisiere Signale + this.betInputValue.set(value); + this.currentBet.set(value); + } + + betHeads() { + this.placeBet('HEAD'); + } + + betTails() { + this.placeBet('TAILS'); + } + + private placeBet(side: 'HEAD' | 'TAILS') { + if (this.gameInProgress() || this.isActionInProgress()) return; + + // Setze vorheriges Ergebnis zurueck + this.gameResult.set(null); + this.errorMessage.set(''); + + // Setze Spielstatus + this.gameInProgress.set(true); + this.isActionInProgress.set(true); + + // Spiele Einsatz-Sound + this.audioService.playBetSound(); + + // Erstelle Einsatz-Anfrage + const request: CoinflipRequest = { + betAmount: this.currentBet(), + coinSide: side, + }; + + // API aufrufen + this.http + .post('/backend/coinflip', request) + .pipe( + catchError((error) => { + console.error('Fehler beim Spielen von Coinflip:', error); + + if (error.status === 400 && error.error.message.includes('insufficient')) { + this.errorMessage.set('Unzureichendes Guthaben'); + } else { + this.errorMessage.set('Ein Fehler ist aufgetreten. Bitte versuche es erneut.'); + } + + this.gameInProgress.set(false); + return of(null); + }), + finalize(() => { + this.isActionInProgress.set(false); + }) + ) + .subscribe((result) => { + if (!result) return; + + console.log('API-Antwort:', result); + + // Behebe moegliche Inkonsistenzen bei der Eigenschaftenbenennung vom Backend + const fixedResult: CoinflipGame = { + isWin: result.isWin ?? result.win, + payout: result.payout, + coinSide: result.coinSide, + }; + + console.log('Korrigiertes Ergebnis:', fixedResult); + + // Spiele Muenzwurf-Animation und -Sound + this.playCoinFlipAnimation(fixedResult.coinSide); + + // Setze Ergebnis nach Abschluss der Animation + setTimeout(() => { + this.gameResult.set(fixedResult); + + // Aktualisiere Guthaben mit neuem Wert vom Auth-Service + this.authService.loadCurrentUser(); + + // Spiele Gewinn-Sound, wenn der Spieler gewonnen hat + if (fixedResult.isWin) { + this.audioService.playWinSound(); + } + + // Setze Spielstatus nach Anzeigen des Ergebnisses zurueck + setTimeout(() => { + this.gameInProgress.set(false); + }, 1500); + }, 1100); // Kurz nach Ende der Animation + }); + } + + private playCoinFlipAnimation(result: 'HEAD' | 'TAILS') { + if (!this.coinElement) return; + + const coinEl = this.coinElement.nativeElement; + + // Setze bestehende Animationen zurueck + coinEl.classList.remove('animate-to-heads', 'animate-to-tails'); + + // Setze alle Inline-Styles von vorherigen Animationen zurueck + coinEl.style.transform = ''; + + // Erzwinge Reflow, um Animation neu zu starten + void coinEl.offsetWidth; + + // Spiele Muenzwurf-Sound + if (this.coinflipSound) { + this.coinflipSound.currentTime = 0; + this.coinflipSound + .play() + .catch((err) => console.error('Fehler beim Abspielen des Sounds:', err)); + } + + // Fuege passende Animationsklasse basierend auf dem Ergebnis hinzu + if (result === 'HEAD') { + coinEl.classList.add('animate-to-heads'); + } else { + coinEl.classList.add('animate-to-tails'); + } + + console.log(`Animation angewendet fuer Ergebnis: ${result}`); + } + + /** + * Validiert Eingabe waehrend der Benutzer tippt, um ungueltige Werte zu verhindern + */ + validateBetInput(event: KeyboardEvent) { + // Erlaube Navigationstasten (Pfeile, Entf, Ruecktaste, Tab) + const navigationKeys = ['ArrowLeft', 'ArrowRight', 'Delete', 'Backspace', 'Tab']; + if (navigationKeys.includes(event.key)) { + return; + } + + // Erlaube nur Zahlen + if (!/^\d$/.test(event.key)) { + event.preventDefault(); + return; + } + + // Ermittle den Wert, der nach dem Tastendruck entstehen wuerde + const input = event.target as HTMLInputElement; + const currentValue = input.value; + const cursorPosition = input.selectionStart || 0; + const newValue = + currentValue.substring(0, cursorPosition) + + event.key + + currentValue.substring(input.selectionEnd || cursorPosition); + const numValue = Number(newValue); + + // Verhindere Werte, die groesser als das Guthaben sind + if (numValue > this.balance()) { + event.preventDefault(); + } + } + + getResultClass() { + if (!this.gameResult()) return ''; + const result = this.gameResult(); + const isWinner = result?.isWin || result?.win; + return isWinner ? 'text-emerald-500' : 'text-accent-red'; + } +} \ No newline at end of file diff --git a/projektdokumentation/Listings/CoinflipController.java b/projektdokumentation/Listings/CoinflipController.java new file mode 100644 index 0000000..21ced8e --- /dev/null +++ b/projektdokumentation/Listings/CoinflipController.java @@ -0,0 +1,38 @@ +package de.szut.casino.coinflip; + +import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException; +import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException; +import de.szut.casino.shared.service.BalanceService; +import de.szut.casino.user.UserEntity; +import de.szut.casino.user.UserService; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +@RestController +public class CoinflipController { + private final UserService userService; + private final BalanceService balanceService; + private final CoinflipService coinflipService; + + public CoinflipController(UserService userService, BalanceService balanceService, CoinflipService coinflipService) { + this.userService = userService; + this.balanceService = balanceService; + this.coinflipService = coinflipService; + } + + @PostMapping("/coinflip") + public ResponseEntity coinFlip(@RequestBody @Valid CoinflipDto coinflipDto) { + UserEntity user = userService.getCurrentUser(); + + if (!this.balanceService.hasFunds(user, coinflipDto)) { + throw new InsufficientFundsException(); + } + + return ResponseEntity.ok(coinflipService.play(user, coinflipDto)); + } +} \ No newline at end of file diff --git a/projektdokumentation/Listings/CoinflipService.java b/projektdokumentation/Listings/CoinflipService.java new file mode 100644 index 0000000..c200361 --- /dev/null +++ b/projektdokumentation/Listings/CoinflipService.java @@ -0,0 +1,35 @@ +package de.szut.casino.coinflip; + +import de.szut.casino.shared.service.BalanceService; +import de.szut.casino.user.UserEntity; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Random; + +@Service +public class CoinflipService { + private final Random random; + private final BalanceService balanceService; + + public CoinflipService(BalanceService balanceService, Random random) { + this.balanceService = balanceService; + this.random = random; + } + + public CoinflipResult play(UserEntity user, CoinflipDto coinflipDto) { + this.balanceService.subtractFunds(user, coinflipDto.getBetAmount()); + + CoinSide coinSide = this.random.nextBoolean() ? CoinSide.HEAD : CoinSide.TAILS; + CoinflipResult coinflipResult = new CoinflipResult(false, BigDecimal.ZERO, coinSide); + if (coinSide == coinflipDto.getCoinSide()) { + coinflipResult.setWin(true); + + BigDecimal payout = coinflipDto.getBetAmount().multiply(BigDecimal.TWO); + this.balanceService.addFunds(user, payout); + coinflipResult.setPayout(payout); + } + + return coinflipResult; + } +} \ No newline at end of file diff --git a/projektdokumentation/Listings/Connection.php b/projektdokumentation/Listings/Connection.php deleted file mode 100644 index 1512e5a..0000000 --- a/projektdokumentation/Listings/Connection.php +++ /dev/null @@ -1,139 +0,0 @@ -logger = $logger; - $this->serverConfig = $configProvider->getConfig('server'); - $this->httpClient = new GuzzleHttpClient( - $this->getHttpClientOptions() - ); - - $this->initHttpEventEmitter(); - } - - protected function authenticate(): bool - { - $result = false; - - $response = $this->createPost( - $this->serverConfig->getAuthUri() - ); - - $statusCode = $response->getStatusCode(); - - if ($statusCode === self::HTTP_STATUS_CODE_OK) { - $this->logger->info('authentication successful'); - $result = true; - } else { - $this->logger->info( - sprintf('authentication failed with Code: %s', $statusCode) - ); - } - - return $result; - } - - protected function createPost(string $uri, array $options = []): ?ResponseInterface - { - $result = null; - $request = $this->httpClient->postAsync($uri, $options); - - $request->then( - static function (ResponseInterface $response) { - $result = $response; - }, - function (RequestException $exception) { - $this->logger->info( - sprintf('Crucial Error: %s \n Trace: %u', $exception->getMessage(), $exception->getTraceAsString()) - ); - } - ); - - return $result; - } - - protected function createGet(string $uri, array $options = []): ?ResponseInterface - { - $result = null; - $request = $this->httpClient->getAsync($uri, $options); - - $request->then( - static function (ResponseInterface $response) { - $result = $response; - }, - function (RequestException $exception) { - $this->logger->info( - sprintf('Crucial Error: %s \n Trace: %u', $exception->getMessage(), $exception->getTraceAsString()) - ); - } - ); - - return $result; - } - - protected function initHttpEventEmitter(): void - { - // initialize the EventEmitters to get a good Logging whether the Request was send - // or failed - $this->httpClient->getEmitter()->on('before', static function (BeforeEvent $event) { - $this->logger->info( - sprintf('About to send Request: %s', $event->getRequest()) - ); - }); - - $this->httpClient->getEmitter()->on('complete', static function (CompleteEvent $event) { - $this->logger->info( - sprintf('Request %s finished', $event->getRequest()) - ); - }); - - $this->httpClient->getEmitter()->on('error', static function (ErrorEvent $event) { - $this->logger->info( - sprintf('Request %s failed', $event->getRequest()) - ); - }); - } - - protected function getHttpClientOptions(): array - { - // Configure Base URL for all ongoing Requests and set Cookies to true, - // so we can handle the auth cookie over and over again without using authenticate() multiple times - return [ - 'base_url' => $this->serverConfig->getBaseUrl(), - 'cookies' => true - ]; - } -} diff --git a/projektdokumentation/Listings/CustomerConnection.php b/projektdokumentation/Listings/CustomerConnection.php deleted file mode 100644 index e8abcc6..0000000 --- a/projektdokumentation/Listings/CustomerConnection.php +++ /dev/null @@ -1,33 +0,0 @@ -customerConfig = $configProvider->getConfig('customer'); - } - - public function loadCustomerData(): array - { - $response = $this->createGet( - $this->customerConfig->getCustomerUri() - ); - - return json_decode($response->getBody(), true); - } -} diff --git a/projektdokumentation/Listings/CustomerDataController.php b/projektdokumentation/Listings/CustomerDataController.php deleted file mode 100644 index 4a73c6c..0000000 --- a/projektdokumentation/Listings/CustomerDataController.php +++ /dev/null @@ -1,28 +0,0 @@ -connection = $connectionFactory->create('customer'); - $this->customerDataHandler = $dataHandler; - } - - public function getCustomerData(): void - { - $customerData = $this->connection->loadCustomerData(); - - $this->customerDataHandler->saveCustomerData($customerData); - } -} diff --git a/projektdokumentation/Listings/Factory.php b/projektdokumentation/Listings/Factory.php deleted file mode 100644 index 3898d19..0000000 --- a/projektdokumentation/Listings/Factory.php +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - -
-
\ No newline at end of file diff --git a/projektdokumentation/Listings/UnitTest.php b/projektdokumentation/Listings/UnitTest.php deleted file mode 100644 index dd4e5ee..0000000 --- a/projektdokumentation/Listings/UnitTest.php +++ /dev/null @@ -1,39 +0,0 @@ -subject = new Factory(); - } - - /** - * @test - */ - public function createMustReturnInstanceOfCustomerConnectionWithValidIdentifierGiven() - { - $expectedInstance = $this->subject->create('customer'); - - self::assertInstanceOf(CustomerConnection::class, $expectedInstance); - } - - /** - * @test - * @throws RuntimeException - */ - public function createMustThrowRuntimeExceptionIfInvalidIdentifierIsGiven() - { - $unexpectedInstance = $this->subject->create('fooBar'); - - self::expectException(RuntimeException::class); - } -} diff --git a/projektdokumentation/Listings/UserEntity.java b/projektdokumentation/Listings/UserEntity.java new file mode 100644 index 0000000..61ad04f --- /dev/null +++ b/projektdokumentation/Listings/UserEntity.java @@ -0,0 +1,92 @@ +package de.szut.casino.user; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.math.BigDecimal; + +@Setter +@Getter +@Entity +@NoArgsConstructor +public class UserEntity { + @Id + @GeneratedValue + private Long id; + + @Version + private Long version; + + @Column(unique = true) + private String email; + + @Column(unique = true) + private String username; + + private String password; + + @Column(precision = 19, scale = 2) + private BigDecimal balance; + + private Boolean emailVerified = false; + + private String verificationToken; + + private String passwordResetToken; + + @Enumerated(EnumType.STRING) + private AuthProvider provider = AuthProvider.LOCAL; + + private String providerId; + + public UserEntity(String email, String username, String password, BigDecimal balance, String verificationToken) { + this.email = email; + this.username = username; + this.password = password; + this.balance = balance; + this.verificationToken = verificationToken; + } + + public UserEntity(String email, String username, AuthProvider provider, String providerId, BigDecimal balance) { + this.email = email; + this.username = username; + this.provider = provider; + this.providerId = providerId; + this.balance = balance; + this.emailVerified = true; // OAuth providers verify emails + } + + public void addBalance(BigDecimal amountToAdd) { + if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) <= 0) { + return; + } + + if (this.balance == null) { + this.balance = BigDecimal.ZERO; + } + + this.balance = this.balance.add(amountToAdd); + } + + public void subtractBalance(BigDecimal amountToSubtract) { + if (amountToSubtract == null || amountToSubtract.compareTo(BigDecimal.ZERO) <= 0) { + throw new IllegalArgumentException("Amount to subtract must be positive."); + } + + if (this.balance == null) { + this.balance = BigDecimal.ZERO; + } + + if (this.balance.compareTo(amountToSubtract) < 0) { + throw new IllegalStateException("Insufficient funds to subtract " + amountToSubtract); + } + + this.balance = this.balance.subtract(amountToSubtract); + } + + public String getEmailAddress() { + return "${name} <${email}>".replace("${name}", this.username).replace("${email}", this.email); + } +} \ No newline at end of file diff --git a/projektdokumentation/Listings/application.properties b/projektdokumentation/Listings/application.properties new file mode 100644 index 0000000..df6f5cc --- /dev/null +++ b/projektdokumentation/Listings/application.properties @@ -0,0 +1,53 @@ +spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:postgresdb} +spring.datasource.username=${DB_USER:postgres_user} +spring.datasource.password=${DB_PASS:postgres_pass} +server.port=${HTTP_PORT:8080} +spring.jpa.hibernate.ddl-auto=update +stripe.secret.key=${STRIPE_SECRET_KEY:sk_test_51QrePYIvCfqz7ANgqam8rEwWcMeKiLOof3j6SCMgu2sl4sESP45DJxca16mWcYo1sQaiBv32CMR6Z4AAAGQPCJo300ubuZKO8I} +stripe.webhook.secret=${STRIPE_WEBHOOK_SECRET:whsec_746b6a488665f6057118bdb4a2b32f4916f16c277109eeaed5e8f8e8b81b8c15} + +app.frontend-host=${FE_URL:http://localhost:4200} + +app.mail.authentication=${MAIL_AUTHENTICATION:false} +app.mail.host=${MAIL_HOST:localhost} +app.mail.port=${MAIL_PORT:1025} +app.mail.username=${MAIL_USER:null} +app.mail.password=${MAIL_PASS:null} +app.mail.from-address=${MAIL_FROM:casino@localhost} +app.mail.protocol=${MAIL_PROTOCOL:smtp} + +spring.application.name=casino + +# JWT Configuration +jwt.secret=${JWT_SECRET:5367566B59703373367639792F423F4528482B4D6251655468576D5A71347437} +jwt.expiration.ms=${JWT_EXPIRATION_MS:86400000} + +# Logging +logging.level.org.springframework.security=DEBUG + +# Swagger +springdoc.swagger-ui.path=swagger +springdoc.swagger-ui.try-it-out-enabled=true + +# GitHub OAuth2 Configuration +spring.security.oauth2.client.registration.github.client-id=${GITHUB_CLIENT_ID:Ov23lingzZsPn1wwACoK} +spring.security.oauth2.client.registration.github.client-secret=${GITHUB_CLIENT_SECRET:4b327fb3b1ab67584a03bcb9d53fa6439fbccad7} +spring.security.oauth2.client.registration.github.redirect-uri=${app.frontend-host}/oauth2/callback/github +spring.security.oauth2.client.registration.github.scope=user:email,read:user +spring.security.oauth2.client.provider.github.authorization-uri=https://github.com/login/oauth/authorize +spring.security.oauth2.client.provider.github.token-uri=https://github.com/login/oauth/access_token +spring.security.oauth2.client.provider.github.user-info-uri=https://api.github.com/user +spring.security.oauth2.client.provider.github.user-name-attribute=login + +# OAuth Success and Failure URLs +app.oauth2.authorizedRedirectUris=${app.frontend-host}/auth/oauth2/callback + +# Google OAuth2 Configuration +spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID:350791038883-c1r7v4o793itq8a0rh7dut7itm7uneam.apps.googleusercontent.com} +spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET: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} +spring.security.oauth2.client.registration.google.redirect-uri=${app.frontend-host}/oauth2/callback/google +spring.security.oauth2.client.registration.google.scope=email,profile +spring.security.oauth2.client.provider.google.authorization-uri=https://accounts.google.com/o/oauth2/v2/auth +spring.security.oauth2.client.provider.google.token-uri=https://oauth2.googleapis.com/token +spring.security.oauth2.client.provider.google.user-info-uri=https://www.googleapis.com/oauth2/v3/userinfo +spring.security.oauth2.client.provider.google.user-name-attribute=sub \ No newline at end of file diff --git a/projektdokumentation/Listings/composer.json b/projektdokumentation/Listings/composer.json deleted file mode 100644 index 0b48a4f..0000000 --- a/projektdokumentation/Listings/composer.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "neusta/m2-intex-client", - "license": "proprietary", - "description": "Client for Magento2 Intex Import/Export", - "type": "magento2-module", - "version": "0.0.1", - "require": { - "php": "7.4.33", - "magento/framework": "~101.0", - "neusta/m2-intex-base": "0.0.1", - "guzzlehttp/guzzle": "6.5.*" - }, - "autoload": { - "files": [ - "registration.php" - ], - "psr-4": { - "Neusta\\IntexClient\\": "src" - } - } -} diff --git a/projektdokumentation/Listings/tests.php b/projektdokumentation/Listings/tests.php deleted file mode 100644 index 14e938d..0000000 --- a/projektdokumentation/Listings/tests.php +++ /dev/null @@ -1,33 +0,0 @@ -comment('Empty Information'); -$emptyComparedInformation = new ComparedNaturalModuleInformation(array()); -$t->is($emptyComparedInformation->getCatalogSign(), ComparedNaturalModuleInformation::EMPTY_SIGN, 'Has no catalog sign'); -$t->is($emptyComparedInformation->getSourceSign(), ComparedNaturalModuleInformation::SIGN_CREATE, 'Source has to be created'); - -$t->comment('Perfect Module'); -$criteria = new Criteria(); -$criteria->add(NaturalmodulenamePeer::NAME, 'SMTAB'); -$moduleName = NaturalmodulenamePeer::doSelectOne($criteria); -$t->is($moduleName->getName(), 'SMTAB', 'Right modulename selected'); -$comparedInformation = $moduleName->loadNaturalModuleInformation(); -$t->is($comparedInformation->getSourceSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Source sign shines global'); -$t->is($comparedInformation->getCatalogSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Catalog sign shines global'); -$infos = $comparedInformation->getNaturalModuleInformations(); -foreach($infos as $info) -{ - $env = $info->getEnvironmentName(); - $t->is($info->getSourceSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Source sign shines at ' . $env); - if($env != 'SVNENTW') - { - $t->is($info->getCatalogSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Catalog sign shines at ' . $info->getEnvironmentName()); - } - else - { - $t->is($info->getCatalogSign(), ComparedNaturalModuleInformation::EMPTY_SIGN, 'Catalog sign is empty at ' . $info->getEnvironmentName()); - } -} -?> \ No newline at end of file diff --git a/projektdokumentation/Projektdokumentation.tex b/projektdokumentation/Projektdokumentation.tex index 00bb191..7bd2c8f 100644 --- a/projektdokumentation/Projektdokumentation.tex +++ b/projektdokumentation/Projektdokumentation.tex @@ -53,12 +53,6 @@ \pagenumbering{arabic} \input{Inhalt.tex} -% Literatur ------------------------------------------------------------------ -\clearpage -\renewcommand{\refname}{Literaturverzeichnis} -\bibliography{Bibliographie} -\bibliographystyle{Allgemein/natdin} % DIN-Stil des Literaturverzeichnisses - % Anhang --------------------------------------------------------------------- \clearpage \appendix diff --git a/texput.log b/texput.log new file mode 100644 index 0000000..ffecf13 --- /dev/null +++ b/texput.log @@ -0,0 +1,21 @@ +This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex 2025.6.5) 12 JUN 2025 23:26 +entering extended mode + restricted \write18 enabled. + %&-line parsing enabled. +**Projektdokumentation.tex + +! Emergency stop. +<*> Projektdokumentation.tex + +End of file on the terminal! + + +Here is how much of TeX's memory you used: + 3 strings out of 478287 + 131 string characters out of 5849290 + 289007 words of memory out of 5000000 + 18302 multiletter control sequences out of 15000+600000 + 469259 words of font info for 28 fonts, out of 8000000 for 9000 + 1141 hyphenation exceptions out of 8191 + 0i,0n,0p,1b,6s stack positions out of 5000i,500n,10000p,200000b,80000s +! ==> Fatal error occurred, no output PDF file produced!