Stand auswürfeln

This commit is contained in:
2025-08-11 21:55:24 +02:00
parent 4df7376e33
commit 1ab469c186
9 changed files with 625 additions and 42 deletions
+142
View File
@@ -751,4 +751,146 @@ a,
.character-details {
padding-bottom: 120px;
}
}
/* Dice Button and Overlay Styles */
.input-with-dice {
display: flex;
gap: 8px;
align-items: center;
}
.input-with-dice select {
flex: 1;
}
.dice-btn {
background: #4CAF50;
border: none;
border-radius: 4px;
width: 40px;
height: 40px;
font-size: 18px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s;
}
.dice-btn:hover:not(:disabled) {
background: #45a049;
}
.dice-btn:disabled {
background: #ccc;
cursor: not-allowed;
opacity: 0.6;
}
.roll-result {
margin-top: 8px;
padding: 8px;
background-color: #e8f5e8;
border-radius: 4px;
font-size: 14px;
color: #2e7d2e;
border-left: 3px solid #4CAF50;
}
/* Roll Overlay Styles */
.roll-overlay {
position: fixed;
top: 20px;
right: 20px;
z-index: 2000;
cursor: pointer;
animation: slideInRight 0.3s ease-out;
}
.roll-overlay-content {
background: linear-gradient(135deg, #4CAF50, #45a049);
color: white;
padding: 20px;
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
min-width: 200px;
position: relative;
text-align: center;
border: 2px solid rgba(255, 255, 255, 0.2);
}
.overlay-close {
position: absolute;
top: 8px;
right: 12px;
background: none;
border: none;
color: white;
font-size: 20px;
cursor: pointer;
opacity: 0.7;
transition: opacity 0.2s;
}
.overlay-close:hover {
opacity: 1;
}
.overlay-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
}
.overlay-roll {
font-size: 24px;
font-weight: bold;
margin-bottom: 8px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
}
.roll-breakdown {
font-size: 14px;
opacity: 0.9;
margin-left: 5px;
}
.overlay-result {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
color: #ffeb3b;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.overlay-hint {
font-size: 12px;
opacity: 0.8;
font-style: italic;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
/* Responsive design for smaller screens */
@media (max-width: 768px) {
.roll-overlay {
top: 10px;
right: 10px;
left: 10px;
}
.roll-overlay-content {
min-width: unset;
}
}
@@ -65,8 +65,8 @@ export default {
ko: 50, // Konstitution
in: 50, // Intelligenz
zt: 50, // Zaubertalent
au: 50, // Ausstrahlung
pa: 50, // Psi-Kraft
au: 50, // Ausehen
pa: 50, // Persönliche Ausstrahlung
wk: 50, // Willenskraft
},
attributes: [
@@ -102,13 +102,13 @@ export default {
},
{
key: 'au',
name: 'Ausstrahlung',
description: 'Charisma and leadership'
name: 'Aussehen',
description: 'Beautyness'
},
{
key: 'pa',
name: 'Psi-Kraft',
description: 'Psychic abilities'
name: 'Persönliche Ausstrahlung',
description: 'Charisma and leadership'
},
{
key: 'wk',
@@ -34,12 +34,43 @@
</div>
</div>
<div class="form-group">
<label for="herkunft">{{ $t('characters.basicInfo.origin') }} {{ $t('characters.basicInfo.required') }}</label>
<select id="herkunft" v-model="formData.herkunft" required>
<option value="">{{ $t('characters.basicInfo.selectOrigin') }}</option>
<option v-for="origin in origins" :key="origin" :value="origin">{{ origin }}</option>
</select>
<div class="form-row">
<div class="form-group">
<label for="herkunft">{{ $t('characters.basicInfo.origin') }} {{ $t('characters.basicInfo.required') }}</label>
<select id="herkunft" v-model="formData.herkunft" required>
<option value="">{{ $t('characters.basicInfo.selectOrigin') }}</option>
<option v-for="origin in origins" :key="origin" :value="origin">{{ origin }}</option>
</select>
</div>
<div class="form-group">
<label for="stand">{{ $t('characters.basicInfo.socialClass') }} {{ $t('characters.basicInfo.required') }}</label>
<div class="input-with-dice">
<select id="stand" v-model="formData.stand" required>
<option value="">{{ $t('characters.basicInfo.selectSocialClass') }}</option>
<option value="Adel">{{ $t('characters.basicInfo.nobility') }}</option>
<option value="Mittelschicht">{{ $t('characters.basicInfo.middleClass') }}</option>
<option value="Volk">{{ $t('characters.basicInfo.commonFolk') }}</option>
<option value="Unfrei">{{ $t('characters.basicInfo.unfree') }}</option>
</select>
<button
type="button"
class="dice-btn"
@click="rollSocialClass"
:disabled="!formData.typ"
:title="formData.typ ? $t('characters.basicInfo.rollSocialClass') : $t('characters.basicInfo.selectClassFirst')"
>
🎲
</button>
</div>
<div v-if="lastSocialClassRoll" class="roll-result">
{{ $t('characters.basicInfo.rollResult') }}: {{ lastSocialClassRoll.roll }}
<span v-if="lastSocialClassRoll.modifier !== 0">
({{ lastSocialClassRoll.baseRoll }}{{ lastSocialClassRoll.modifier >= 0 ? '+' : '' }}{{ lastSocialClassRoll.modifier }})
</span>
{{ lastSocialClassRoll.result }}
</div>
</div>
</div>
<div class="form-group">
@@ -75,6 +106,24 @@
</button>
</div>
</form>
<!-- Roll Result Overlay -->
<div v-if="showOverlay && lastSocialClassRoll" class="roll-overlay" @click="hideOverlay">
<div class="roll-overlay-content">
<button class="overlay-close" @click="hideOverlay">×</button>
<div class="overlay-title">🎲 {{ $t('characters.basicInfo.rollResult') }}</div>
<div class="overlay-roll">
{{ lastSocialClassRoll.roll }}
<span v-if="lastSocialClassRoll.modifier !== 0" class="roll-breakdown">
({{ lastSocialClassRoll.baseRoll }}{{ lastSocialClassRoll.modifier >= 0 ? '+' : '' }}{{ lastSocialClassRoll.modifier }})
</span>
</div>
<div class="overlay-result">
{{ $t('characters.basicInfo.' + lastSocialClassRoll.result.toLowerCase()) || lastSocialClassRoll.result }}
</div>
<div class="overlay-hint">{{ $t('characters.basicInfo.clickToClose') }}</div>
</div>
</div>
</div>
</template>
@@ -97,6 +146,7 @@ export default {
rasse: '',
typ: '',
herkunft: '',
stand: '',
glaube: '',
},
races: [],
@@ -105,6 +155,9 @@ export default {
beliefSearch: '',
beliefResults: [],
searchTimeout: null,
lastSocialClassRoll: null,
showOverlay: false,
overlayTimeout: null,
}
},
computed: {
@@ -112,7 +165,14 @@ export default {
return this.formData.name.length >= 2 &&
this.formData.rasse &&
this.formData.typ &&
this.formData.herkunft
this.formData.herkunft &&
this.formData.stand
}
},
watch: {
'formData.typ'() {
// Clear social class roll result when character class changes
this.lastSocialClassRoll = null
}
},
async created() {
@@ -122,6 +182,7 @@ export default {
rasse: this.sessionData.rasse || '',
typ: this.sessionData.typ || '',
herkunft: this.sessionData.herkunft || '',
stand: this.sessionData.stand || '',
glaube: this.sessionData.glaube || '',
}
@@ -131,6 +192,15 @@ export default {
await this.loadReferenceData()
},
beforeUnmount() {
// Clean up timeouts
if (this.searchTimeout) {
clearTimeout(this.searchTimeout)
}
if (this.overlayTimeout) {
clearTimeout(this.overlayTimeout)
}
},
methods: {
async loadReferenceData() {
try {
@@ -187,6 +257,86 @@ export default {
this.beliefResults = []
},
rollSocialClass() {
if (!this.formData.typ) {
return
}
// Base 1d100 roll
const baseRoll = this.$rollNotation('1d100')
let modifier = 0
// Apply class modifiers
switch (this.formData.typ) {
case 'Barde':
case 'Priester':
modifier = 20
break
case 'Druide':
case 'Magier':
modifier = 10
break
case 'Assassine':
case 'Händler':
case 'Waldläufer':
modifier = -10
break
case 'Spitzbube':
modifier = -20
break
}
const finalRoll = baseRoll.sum + modifier
// Determine social class based on final roll
let socialClass = ''
if (finalRoll <= 10) {
socialClass = 'Unfrei'
} else if (finalRoll <= 50) {
socialClass = 'Volk'
} else if (finalRoll <= 90) {
socialClass = 'Mittelschicht'
} else {
socialClass = 'Adel'
}
// Set the form data
this.formData.stand = socialClass
// Store roll information for display
this.lastSocialClassRoll = {
baseRoll: baseRoll.sum,
modifier: modifier,
roll: finalRoll,
result: socialClass
}
// Show overlay notification
this.showRollOverlay()
},
showRollOverlay() {
this.showOverlay = true
// Clear existing timeout if any
if (this.overlayTimeout) {
clearTimeout(this.overlayTimeout)
}
// Hide overlay after 20 seconds
this.overlayTimeout = setTimeout(() => {
this.showOverlay = false
}, 20000)
},
hideOverlay() {
this.showOverlay = false
if (this.overlayTimeout) {
clearTimeout(this.overlayTimeout)
this.overlayTimeout = null
}
},
handleSubmit() {
if (this.isValid) {
this.$emit('next', this.formData)
@@ -1,12 +1,12 @@
<template>
<div class="derived-values-form">
<h2>Derived Values</h2>
<p class="instruction">These values are calculated from your attributes. You can adjust them as needed.</p>
<h2>{{ $t('characters.derivedValues.title') }}</h2>
<p class="instruction">{{ $t('characters.derivedValues.instruction') }}</p>
<form @submit.prevent="handleSubmit">
<div class="values-grid">
<div class="value-group" v-for="value in derivedValues" :key="value.key">
<label :for="value.key">{{ value.name }}</label>
<label :for="value.key">{{ $t(value.name) }}</label>
<div class="value-input-group">
<input
:id="value.key"
@@ -17,40 +17,40 @@
required
/>
<div class="value-info">
<span class="calculated-value">Calculated: {{ calculatedValues[value.key] }}</span>
<span class="value-description">{{ value.description }}</span>
<span class="calculated-value">{{ $t('characters.derivedValues.calculated') }}: {{ calculatedValues[value.key] }}</span>
<span class="value-description">{{ $t(value.description) }}</span>
</div>
</div>
</div>
</div>
<div class="calculation-info">
<h3>Calculation Rules</h3>
<h3>{{ $t('characters.derivedValues.calculationRules') }}</h3>
<div class="calculation-rules">
<div class="rule">
<strong>LP (Life Points):</strong> Base formula: (KO + ST) / 2 + modifier
<strong>{{ $t('characters.derivedValues.lpFormula') }}:</strong> {{ $t('characters.derivedValues.lpDescription') }}
</div>
<div class="rule">
<strong>AP (Adventure Points):</strong> Base formula: (AU + WK) / 2 + modifier
<strong>{{ $t('characters.derivedValues.apFormula') }}:</strong> {{ $t('characters.derivedValues.apDescription') }}
</div>
<div class="rule">
<strong>B (Burden):</strong> Base formula: ST + modifier
<strong>{{ $t('characters.derivedValues.bFormula') }}:</strong> {{ $t('characters.derivedValues.bDescription') }}
</div>
<div class="rule">
<strong>Bennies:</strong> Base values based on character class
<strong>{{ $t('characters.derivedValues.benniesFormula') }}:</strong> {{ $t('characters.derivedValues.benniesDescription') }}
</div>
</div>
</div>
<div class="form-actions">
<button type="button" @click="handlePrevious" class="prev-btn">
Previous: Attributes
{{ $t('characters.derivedValues.previousAttributes') }}
</button>
<button type="button" @click="recalculate" class="calc-btn">
Recalculate from Attributes
{{ $t('characters.derivedValues.recalculate') }}
</button>
<button type="submit" class="next-btn" :disabled="!isValid">
Next: Skills & Spells
{{ $t('characters.derivedValues.nextSkills') }}
</button>
</div>
</form>
@@ -80,43 +80,43 @@ export default {
derivedValues: [
{
key: 'lp_max',
name: 'Life Points (LP) Maximum',
description: 'Maximum life/health points',
name: 'characters.derivedValues.lpMax',
description: 'characters.derivedValues.lpMaxDescription',
min: 1,
max: 200
},
{
key: 'ap_max',
name: 'Adventure Points (AP) Maximum',
description: 'Maximum adventure points for special actions',
name: 'characters.derivedValues.apMax',
description: 'characters.derivedValues.apMaxDescription',
min: 1,
max: 200
},
{
key: 'b_max',
name: 'Burden (B) Maximum',
description: 'Maximum carrying capacity',
name: 'characters.derivedValues.bMax',
description: 'characters.derivedValues.bMaxDescription',
min: 1,
max: 500
},
{
key: 'sg',
name: 'Schicksalsgunst (SG)',
description: 'Fate points for rerolls',
name: 'characters.derivedValues.sg',
description: 'characters.derivedValues.sgDescription',
min: 0,
max: 10
},
{
key: 'gg',
name: 'Göttliche Gnade (GG)',
description: 'Divine grace points',
name: 'characters.derivedValues.gg',
description: 'characters.derivedValues.ggDescription',
min: 0,
max: 10
},
{
key: 'gp',
name: 'Glückspunkte (GP)',
description: 'Luck points',
name: 'characters.derivedValues.gp',
description: 'characters.derivedValues.gpDescription',
min: 0,
max: 10
},
+44 -1
View File
@@ -227,11 +227,54 @@ export default {
selectClass: 'Klasse auswählen',
origin: 'Herkunft',
selectOrigin: 'Herkunft auswählen',
socialClass: 'Gesellschaftlicher Stand',
selectSocialClass: 'Stand auswählen',
nobility: 'Adel',
middleClass: 'Mittelschicht',
commonFolk: 'Volk',
unfree: 'Unfrei',
religion: 'Religion/Glaube',
religionPlaceholder: 'Mindestens 2 Zeichen für die Suche eingeben...',
selected: 'Ausgewählt',
nextAttributes: 'Weiter: Attribute →',
required: '*'
required: '*',
rollResult: 'Würfelergebnis',
rollSocialClass: 'Würfle für gesellschaftlichen Stand',
selectClassFirst: 'Zuerst Charakterklasse auswählen',
clickToClose: 'Klicken zum Schließen',
adel: 'Adel',
mittelschicht: 'Mittelschicht',
volk: 'Volk',
unfrei: 'Unfrei'
},
derivedValues: {
title: 'Abgeleitete Werte',
instruction: 'Diese Werte werden aus Ihren Attributen berechnet. Sie können sie nach Bedarf anpassen.',
lpMax: 'Lebenspunkte (LP) Maximum',
lpMaxDescription: 'Maximale Lebens-/Gesundheitspunkte',
apMax: 'Abenteuerpunkte (AP) Maximum',
apMaxDescription: 'Maximale Abenteuerpunkte für spezielle Aktionen',
bMax: 'Belastung (B) Maximum',
bMaxDescription: 'Maximale Tragekapazität',
sg: 'Schicksalsgunst (SG)',
sgDescription: 'Schicksalspunkte für Wiederholungswürfe',
gg: 'Göttliche Gnade (GG)',
ggDescription: 'Göttliche Gnadenpunkte',
gp: 'Glückspunkte (GP)',
gpDescription: 'Glückspunkte',
calculated: 'Berechnet',
calculationRules: 'Berechnungsregeln',
lpFormula: 'LP (Lebenspunkte)',
lpDescription: 'Grundformel: (KO + ST) / 2 + Modifikator',
apFormula: 'AP (Ausdauerpunkte)',
apDescription: 'Grundformel: (AU + WK) / 2 + Modifikator',
bFormula: 'B (Bewegungsweite)',
bDescription: 'Grundformel: ST + Modifikator',
benniesFormula: 'Bennies',
benniesDescription: 'Grundwerte basierend auf Charakterklasse',
previousAttributes: 'Zurück: Attribute',
recalculate: 'Aus Attributen neu berechnen',
nextSkills: 'Weiter: Fertigkeiten & Zauber'
}
}
}
+44 -1
View File
@@ -133,11 +133,54 @@ export default {
selectClass: 'Select Class',
origin: 'Origin',
selectOrigin: 'Select Origin',
socialClass: 'Social Class',
selectSocialClass: 'Select Social Class',
nobility: 'Nobility',
middleClass: 'Middle Class',
commonFolk: 'Common Folk',
unfree: 'Unfree',
religion: 'Religion/Belief',
religionPlaceholder: 'Type at least 2 characters to search beliefs...',
selected: 'Selected',
nextAttributes: 'Next: Attributes →',
required: '*'
required: '*',
rollResult: 'Roll Result',
rollSocialClass: 'Roll for social class',
selectClassFirst: 'Select character class first',
clickToClose: 'Click to close',
adel: 'Nobility',
mittelschicht: 'Middle Class',
volk: 'Common Folk',
unfrei: 'Unfree'
},
derivedValues: {
title: 'Derived Values',
instruction: 'These values are calculated from your attributes. You can adjust them as needed.',
lpMax: 'Life Points (LP) Maximum',
lpMaxDescription: 'Maximum life/health points',
apMax: 'Adventure Points (AP) Maximum',
apMaxDescription: 'Maximum adventure points for special actions',
bMax: 'Burden (B) Maximum',
bMaxDescription: 'Maximum carrying capacity',
sg: 'Fate\'s Favor (SG)',
sgDescription: 'Fate points for rerolls',
gg: 'Divine Grace (GG)',
ggDescription: 'Divine grace points',
gp: 'Luck Points (GP)',
gpDescription: 'Luck points',
calculated: 'Calculated',
calculationRules: 'Calculation Rules',
lpFormula: 'LP (Life Points)',
lpDescription: 'Base formula: (KO + ST) / 2 + modifier',
apFormula: 'AP (Adventure Points)',
apDescription: 'Base formula: (AU + WK) / 2 + modifier',
bFormula: 'B (Movement Range)',
bDescription: 'Base formula: ST + modifier',
benniesFormula: 'Bennies',
benniesDescription: 'Base values based on character class',
previousAttributes: 'Previous: Attributes',
recalculate: 'Recalculate from Attributes',
nextSkills: 'Next: Skills & Spells'
}
},
common: {
+2
View File
@@ -5,6 +5,7 @@ import { createPinia } from 'pinia'
import App from "./App.vue";
import router from "./router";
import { i18n } from './stores/languageStore'
import UtilsPlugin from './utils/utilsPlugin'
const app = createApp(App);
@@ -12,4 +13,5 @@ const pinia = createPinia();
app.use(pinia);
app.use(router);
app.use(i18n);
app.use(UtilsPlugin);
app.mount("#app");
+174
View File
@@ -0,0 +1,174 @@
/**
* Utility-Funktionen für Zufallszahlen
*/
/**
* Erzeugt eine einzelne Zufallszahl im Bereich von 1 bis max
* @param {number} max - Maximaler Wert (inklusive)
* @returns {number} - Zufallszahl zwischen 1 und max
*/
export function rollDie(max = 6) {
if (typeof max !== 'number' || max < 1) {
throw new Error('Max value must be a positive number')
}
return Math.floor(Math.random() * max) + 1
}
/**
* Erzeugt mehrere Zufallszahlen im Bereich von 1 bis max
* @param {number} count - Anzahl der zu erzeugenden Zufallszahlen
* @param {number} max - Maximaler Wert (inklusive, default: 6)
* @returns {Array<number>} - Array mit Zufallszahlen
*/
export function rollDice(count = 1, max = 6) {
if (typeof count !== 'number' || count < 1) {
throw new Error('Count must be a positive number')
}
if (typeof max !== 'number' || max < 1) {
throw new Error('Max value must be a positive number')
}
const results = []
for (let i = 0; i < count; i++) {
results.push(rollDie(max))
}
return results
}
/**
* Erzeugt Zufallszahlen und gibt sowohl die einzelnen Ergebnisse als auch die Summe zurück
* @param {number} count - Anzahl der Würfel
* @param {number} max - Maximaler Wert pro Würfel (default: 6)
* @returns {Object} - Objekt mit rolls (Array) und sum (Summe)
*/
export function rollDiceWithSum(count = 1, max = 6) {
const rolls = rollDice(count, max)
const sum = rolls.reduce((total, roll) => total + roll, 0)
return {
rolls,
sum,
count,
max
}
}
/**
* Simuliert RPG-Würfelnotation (z.B. "3d6", "1d20", "2d10+5", "max(2d20)")
* @param {string} notation - Würfelnotation (z.B. "3d6", "1d20+5", "2d8-1", "max(2d20)", "min(3d6)")
* @returns {Object} - Objekt mit rolls, sum, modifier und der ursprünglichen notation
*/
export function rollNotation(notation = '1d6') {
if (typeof notation !== 'string') {
throw new Error('Notation must be a string')
}
// Entferne Leerzeichen
const cleanNotation = notation.replace(/\s+/g, '')
// Check für max/min Funktionen (z.B. "max(2d20)", "min(3d6)")
const functionMatch = cleanNotation.match(/^(max|min)\((\d+)d(\d+)([+-]\d+)?\)$/i)
if (functionMatch) {
const func = functionMatch[1].toLowerCase()
const count = parseInt(functionMatch[2])
const sides = parseInt(functionMatch[3])
const modifier = functionMatch[4] ? parseInt(functionMatch[4]) : 0
const rolls = rollDice(count, sides)
let selectedValue
if (func === 'max') {
selectedValue = Math.max(...rolls)
} else if (func === 'min') {
selectedValue = Math.min(...rolls)
}
const finalSum = selectedValue + modifier
return {
notation,
rolls,
selectedValue,
selectedFunction: func,
baseSum: selectedValue,
modifier,
sum: finalSum,
count,
sides
}
}
// Standard-Notation (z.B. "3d6+2" oder "1d20-1")
const standardMatch = cleanNotation.match(/^(\d+)d(\d+)([+-]\d+)?$/i)
if (!standardMatch) {
throw new Error('Invalid dice notation. Use format like "3d6", "1d20+5", "2d8-2", "max(2d20)", or "min(3d6)"')
}
const count = parseInt(standardMatch[1])
const sides = parseInt(standardMatch[2])
const modifier = standardMatch[3] ? parseInt(standardMatch[3]) : 0
const rolls = rollDice(count, sides)
const baseSum = rolls.reduce((total, roll) => total + roll, 0)
const finalSum = baseSum + modifier
return {
notation,
rolls,
baseSum,
modifier,
sum: finalSum,
count,
sides
}
}
/**
* Erzeugt eine Zufallszahl in einem bestimmten Bereich (min bis max, inklusive)
* @param {number} min - Minimaler Wert (inklusive)
* @param {number} max - Maximaler Wert (inklusive)
* @returns {number} - Zufallszahl zwischen min und max
*/
export function randomBetween(min = 1, max = 6) {
if (typeof min !== 'number' || typeof max !== 'number') {
throw new Error('Min and max must be numbers')
}
if (min > max) {
throw new Error('Min value cannot be greater than max value')
}
return Math.floor(Math.random() * (max - min + 1)) + min
}
/**
* Wählt ein zufälliges Element aus einem Array
* @param {Array} array - Array mit Elementen zur Auswahl
* @returns {*} - Zufällig gewähltes Element
*/
export function randomChoice(array) {
if (!Array.isArray(array) || array.length === 0) {
throw new Error('Array must be a non-empty array')
}
const randomIndex = Math.floor(Math.random() * array.length)
return array[randomIndex]
}
/**
* Mischt ein Array zufällig (Fisher-Yates Shuffle)
* @param {Array} array - Array zum Mischen
* @returns {Array} - Neues gemischtes Array (Original bleibt unverändert)
*/
export function shuffleArray(array) {
if (!Array.isArray(array)) {
throw new Error('Input must be an array')
}
const shuffled = [...array]
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]
}
return shuffled
}
+31 -2
View File
@@ -8,26 +8,55 @@
* Usage in components:
* this.$formatDate(dateString)
* this.$safeValue(value, 'fallback')
* this.$rollDice(3, 6) // 3 Würfel mit 6 Seiten
* this.$rollNotation('2d10+3') // RPG-Würfelnotation
*/
import { formatDate, formatDateTime, formatRelativeDate, safeValue, capitalize } from './dateUtils'
import {
rollDie,
rollDice,
rollDiceWithSum,
rollNotation,
randomBetween,
randomChoice,
shuffleArray
} from './randomUtils.js'
export default {
install(app) {
// Globale Properties für Vue 3
// Globale Properties für Vue 3 - Date Utils
app.config.globalProperties.$formatDate = formatDate
app.config.globalProperties.$formatDateTime = formatDateTime
app.config.globalProperties.$formatRelativeDate = formatRelativeDate
app.config.globalProperties.$safeValue = safeValue
app.config.globalProperties.$capitalize = capitalize
// Globale Properties für Vue 3 - Random Utils
app.config.globalProperties.$rollDie = rollDie
app.config.globalProperties.$rollDice = rollDice
app.config.globalProperties.$rollDiceWithSum = rollDiceWithSum
app.config.globalProperties.$rollNotation = rollNotation
app.config.globalProperties.$randomBetween = randomBetween
app.config.globalProperties.$randomChoice = randomChoice
app.config.globalProperties.$shuffleArray = shuffleArray
// Provide/Inject für Composition API
app.provide('utils', {
// Date Utils
formatDate,
formatDateTime,
formatRelativeDate,
safeValue,
capitalize
capitalize,
// Random Utils
rollDie,
rollDice,
rollDiceWithSum,
rollNotation,
randomBetween,
randomChoice,
shuffleArray
})
}
}