diff --git a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts
index ca7c3ca..cd3ed1f 100644
--- a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts
+++ b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts
@@ -38,7 +38,7 @@ export default class LootboxOpeningComponent {
this.isLoading = false;
return;
}
-
+
const lootboxId = parseInt(idParam, 10);
this.lootboxService.getAllLootBoxes().subscribe({
next: (lootboxes) => {
@@ -56,9 +56,9 @@ export default class LootboxOpeningComponent {
openLootbox(): void {
if (!this.lootbox || this.isOpening) return;
-
+
this.resetState(true);
-
+
setTimeout(() => {
this.lootboxService.purchaseLootBox(this.lootbox!.id).subscribe({
next: this.handleRewardSuccess.bind(this),
@@ -77,7 +77,7 @@ export default class LootboxOpeningComponent {
private handleRewardError(): void {
if (!this.lootbox) return;
-
+
const rewards = this.lootbox.rewards;
const fallback = rewards[Math.floor(Math.random() * rewards.length)];
this.handleRewardSuccess(fallback);
@@ -99,17 +99,17 @@ export default class LootboxOpeningComponent {
const winningPosition = Math.floor(prizeCount / 2);
const possibleRewards = this.lootbox.rewards;
const items: Reward[] = [];
-
+
for (let i = 0; i < prizeCount; i++) {
if (i === winningPosition) {
- items.push({...wonReward});
+ items.push({ ...wonReward });
} else {
items.push(this.getWeightedRandomReward(possibleRewards));
}
}
this.prizeList = items;
-
+
setTimeout(() => {
this.animationCompleted = true;
this.cdr.detectChanges();
@@ -120,14 +120,14 @@ export default class LootboxOpeningComponent {
const totalProbability = rewards.reduce((sum, reward) => sum + reward.probability, 0);
const randomValue = Math.random() * totalProbability;
let cumulativeProbability = 0;
-
+
for (const reward of rewards) {
cumulativeProbability += reward.probability;
if (randomValue <= cumulativeProbability) {
return { ...reward };
}
}
-
+
return { ...rewards[0] };
}
@@ -146,27 +146,26 @@ export default class LootboxOpeningComponent {
isWonReward(reward: Reward): boolean {
if (!this.wonReward || !this.prizeList.length) return false;
-
+
const middleIndex = Math.floor(this.prizeList.length / 2);
return this.prizeList.indexOf(reward) === middleIndex;
}
-
+
getRewardRarityClass(reward: Reward): string {
if (!reward) return 'text-common';
-
+
const probability = reward.probability;
-
+
if (probability < 0.01) return 'text-mythic';
if (probability < 0.05) return 'text-legendary';
- if (probability < 0.10) return 'text-epic';
- if (probability < 0.20) return 'text-rare';
- if (probability < 0.40) return 'text-uncommon';
+ if (probability < 0.1) return 'text-epic';
+ if (probability < 0.2) return 'text-rare';
+ if (probability < 0.4) return 'text-uncommon';
return 'text-common';
}
-
+
getRewardClass(): string {
if (!this.wonReward || !this.lootbox) return '';
return this.wonReward.value > (this.lootbox.price || 0) ? 'text-emerald' : 'text-accent-red';
}
}
-
diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.css b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.css
index bbeb8b0..878220b 100644
--- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.css
+++ b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.css
@@ -8,15 +8,21 @@
}
@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
}
.card {
- transition: transform 0.3s ease, box-shadow 0.3s ease;
+ transition:
+ transform 0.3s ease,
+ box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
-}
\ No newline at end of file
+}
diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html
index a4293fd..bda9028 100644
--- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html
+++ b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html
@@ -1,48 +1,60 @@
Lootboxen
-
-
isLoading: {{ isLoading }} | error: {{ error }} | lootboxes: {{ lootboxes.length }}
-
+
+
+ isLoading: {{ isLoading }} | error: {{ error }} | lootboxes: {{ lootboxes.length }}
+
+
-
+
{{ error }}
-
+
-
+
-
![]()
+
- {{ lootbox.price | currency:'EUR' }}
+ {{ lootbox.price | currency: 'EUR' }}
-
+
{{ lootbox.name }}
-
+
Mögliche Gewinne:
-
- {{ reward.value | currency:'EUR' }}
+ {{
+ reward.value | currency: 'EUR'
+ }}
{{ formatProbability(reward.probability) }}
-
+
-
-
+
Fairness garantiert - Alle Ergebnisse werden transparent berechnet.
@@ -50,4 +62,4 @@
-
\ No newline at end of file
+
diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts
index 1382b23..217af16 100644
--- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts
+++ b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts
@@ -11,7 +11,7 @@ import { timeout } from 'rxjs';
standalone: true,
imports: [CommonModule, NavbarComponent],
templateUrl: './lootbox-selection.component.html',
- styleUrls: ['./lootbox-selection.component.css']
+ styleUrls: ['./lootbox-selection.component.css'],
})
export default class LootboxSelectionComponent implements OnInit {
lootboxes: LootBox[] = [];
@@ -22,68 +22,72 @@ export default class LootboxSelectionComponent implements OnInit {
fallbackLootboxes: LootBox[] = [
{
id: 1,
- name: "Basic LootBox",
- price: 2.00,
+ name: 'Basic LootBox',
+ price: 2.0,
rewards: [
{
id: 1,
- value: 0.50,
- probability: 0.70
+ value: 0.5,
+ probability: 0.7,
},
{
id: 5,
- value: 5.00,
- probability: 0.30
- }
- ]
+ value: 5.0,
+ probability: 0.3,
+ },
+ ],
},
{
id: 2,
- name: "Premium LootBox",
- price: 5.00,
+ name: 'Premium LootBox',
+ price: 5.0,
rewards: [
{
id: 4,
- value: 2.00,
- probability: 0.60
+ value: 2.0,
+ probability: 0.6,
},
{
id: 5,
- value: 5.00,
- probability: 0.30
+ value: 5.0,
+ probability: 0.3,
},
{
id: 6,
- value: 15.00,
- probability: 0.10
- }
- ]
+ value: 15.0,
+ probability: 0.1,
+ },
+ ],
},
{
id: 3,
- name: "Legendäre LootBox",
- price: 15.00,
+ name: 'Legendäre LootBox',
+ price: 15.0,
rewards: [
{
id: 4,
- value: 2.00,
- probability: 0.60
+ value: 2.0,
+ probability: 0.6,
},
{
id: 5,
- value: 5.00,
- probability: 0.30
+ value: 5.0,
+ probability: 0.3,
},
{
id: 6,
- value: 15.00,
- probability: 0.10
- }
- ]
- }
+ value: 15.0,
+ probability: 0.1,
+ },
+ ],
+ },
];
- constructor(private lootboxService: LootboxService, private router: Router, private cdr: ChangeDetectorRef) {}
+ constructor(
+ private lootboxService: LootboxService,
+ private router: Router,
+ private cdr: ChangeDetectorRef
+ ) {}
ngOnInit(): void {
this.loadLootboxes();
@@ -91,23 +95,24 @@ export default class LootboxSelectionComponent implements OnInit {
loadLootboxes(): void {
this.isLoading = true;
- this.lootboxService.getAllLootBoxes().pipe(
- timeout(5000)
- ).subscribe({
- next: (data) => {
- console.log('Received lootboxes:', data);
- this.lootboxes = data;
- this.isLoading = false;
- this.cdr.detectChanges();
- },
- error: (err) => {
- this.error = 'Konnte keine Verbindung zum Backend herstellen. Zeige Demo-Daten.';
- this.lootboxes = this.fallbackLootboxes;
- this.isLoading = false;
- this.cdr.detectChanges();
- console.error('Failed to load lootboxes:', err);
- }
- });
+ this.lootboxService
+ .getAllLootBoxes()
+ .pipe(timeout(5000))
+ .subscribe({
+ next: (data) => {
+ console.log('Received lootboxes:', data);
+ this.lootboxes = data;
+ this.isLoading = false;
+ this.cdr.detectChanges();
+ },
+ error: (err) => {
+ this.error = 'Konnte keine Verbindung zum Backend herstellen. Zeige Demo-Daten.';
+ this.lootboxes = this.fallbackLootboxes;
+ this.isLoading = false;
+ this.cdr.detectChanges();
+ console.error('Failed to load lootboxes:', err);
+ },
+ });
}
getBoxImage(id: number): string {
@@ -131,4 +136,4 @@ export default class LootboxSelectionComponent implements OnInit {
formatProbability(probability: number): string {
return (probability * 100).toFixed(0) + '%';
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/app/feature/lootboxes/services/lootbox.service.ts b/frontend/src/app/feature/lootboxes/services/lootbox.service.ts
index 040b55d..b0fb58d 100644
--- a/frontend/src/app/feature/lootboxes/services/lootbox.service.ts
+++ b/frontend/src/app/feature/lootboxes/services/lootbox.service.ts
@@ -10,14 +10,12 @@ export class LootboxService {
private http = inject(HttpClient);
getAllLootBoxes(): Observable
{
- return this.http
- .get('/backend/lootboxes', { responseType: 'json' })
- .pipe(
- catchError((error) => {
- console.error('Get lootboxes error:', error);
- throw error;
- })
- );
+ return this.http.get('/backend/lootboxes', { responseType: 'json' }).pipe(
+ catchError((error) => {
+ console.error('Get lootboxes error:', error);
+ throw error;
+ })
+ );
}
purchaseLootBox(lootBoxId: number): Observable {
@@ -30,4 +28,4 @@ export class LootboxService {
})
);
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/app/model/LootBox.ts b/frontend/src/app/model/LootBox.ts
index f1547b1..ebcf6e8 100644
--- a/frontend/src/app/model/LootBox.ts
+++ b/frontend/src/app/model/LootBox.ts
@@ -9,4 +9,4 @@ export interface LootBox {
name: string;
price: number;
rewards: Reward[];
-}
\ No newline at end of file
+}