@jjlmoya/utils-finance 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/package.json +64 -0
  2. package/src/category/i18n/en.ts +159 -0
  3. package/src/category/i18n/es.ts +159 -0
  4. package/src/category/i18n/fr.ts +159 -0
  5. package/src/category/index.ts +24 -0
  6. package/src/category/seo.astro +15 -0
  7. package/src/components/PreviewNavSidebar.astro +116 -0
  8. package/src/components/PreviewToolbar.astro +143 -0
  9. package/src/data.ts +11 -0
  10. package/src/env.d.ts +5 -0
  11. package/src/index.ts +32 -0
  12. package/src/layouts/PreviewLayout.astro +117 -0
  13. package/src/pages/[locale]/[slug].astro +146 -0
  14. package/src/pages/[locale].astro +251 -0
  15. package/src/pages/index.astro +4 -0
  16. package/src/tests/faq_count.test.ts +19 -0
  17. package/src/tests/locale_completeness.test.ts +39 -0
  18. package/src/tests/mocks/astro_mock.js +2 -0
  19. package/src/tests/no_h1_in_components.test.ts +48 -0
  20. package/src/tests/schemas_fulfillment.test.ts +23 -0
  21. package/src/tests/seo_length.test.ts +23 -0
  22. package/src/tests/title_quality.test.ts +55 -0
  23. package/src/tests/tool_validation.test.ts +17 -0
  24. package/src/tool/compoundInterest/bibliography.astro +14 -0
  25. package/src/tool/compoundInterest/component.astro +697 -0
  26. package/src/tool/compoundInterest/i18n/en.ts +212 -0
  27. package/src/tool/compoundInterest/i18n/es.ts +212 -0
  28. package/src/tool/compoundInterest/i18n/fr.ts +212 -0
  29. package/src/tool/compoundInterest/index.ts +34 -0
  30. package/src/tool/compoundInterest/logic.ts +40 -0
  31. package/src/tool/compoundInterest/seo.astro +14 -0
  32. package/src/tool/compoundInterest/ui.ts +19 -0
  33. package/src/tool/courtFeeCalculator/bibliography.astro +14 -0
  34. package/src/tool/courtFeeCalculator/component.astro +427 -0
  35. package/src/tool/courtFeeCalculator/i18n/en.ts +268 -0
  36. package/src/tool/courtFeeCalculator/i18n/es.ts +268 -0
  37. package/src/tool/courtFeeCalculator/i18n/fr.ts +268 -0
  38. package/src/tool/courtFeeCalculator/index.ts +33 -0
  39. package/src/tool/courtFeeCalculator/logic.ts +86 -0
  40. package/src/tool/courtFeeCalculator/seo.astro +14 -0
  41. package/src/tool/courtFeeCalculator/ui.ts +31 -0
  42. package/src/tool/debtSnowball/bibliography.astro +14 -0
  43. package/src/tool/debtSnowball/component.astro +1052 -0
  44. package/src/tool/debtSnowball/i18n/en.ts +288 -0
  45. package/src/tool/debtSnowball/i18n/es.ts +288 -0
  46. package/src/tool/debtSnowball/i18n/fr.ts +288 -0
  47. package/src/tool/debtSnowball/index.ts +37 -0
  48. package/src/tool/debtSnowball/logic.ts +156 -0
  49. package/src/tool/debtSnowball/seo.astro +14 -0
  50. package/src/tool/debtSnowball/ui.ts +49 -0
  51. package/src/tool/fireCalculator/bibliography.astro +14 -0
  52. package/src/tool/fireCalculator/component.astro +689 -0
  53. package/src/tool/fireCalculator/i18n/en.ts +261 -0
  54. package/src/tool/fireCalculator/i18n/es.ts +261 -0
  55. package/src/tool/fireCalculator/i18n/fr.ts +261 -0
  56. package/src/tool/fireCalculator/index.ts +33 -0
  57. package/src/tool/fireCalculator/logic.ts +108 -0
  58. package/src/tool/fireCalculator/seo.astro +14 -0
  59. package/src/tool/fireCalculator/ui.ts +33 -0
  60. package/src/tool/ibanBicSwiftConverter/bibliography.astro +14 -0
  61. package/src/tool/ibanBicSwiftConverter/component.astro +581 -0
  62. package/src/tool/ibanBicSwiftConverter/i18n/en.ts +167 -0
  63. package/src/tool/ibanBicSwiftConverter/i18n/es.ts +216 -0
  64. package/src/tool/ibanBicSwiftConverter/i18n/fr.ts +167 -0
  65. package/src/tool/ibanBicSwiftConverter/index.ts +33 -0
  66. package/src/tool/ibanBicSwiftConverter/logic.ts +101 -0
  67. package/src/tool/ibanBicSwiftConverter/seo.astro +14 -0
  68. package/src/tool/ibanBicSwiftConverter/ui.ts +17 -0
  69. package/src/tool/inflation/bibliography.astro +14 -0
  70. package/src/tool/inflation/component.astro +400 -0
  71. package/src/tool/inflation/i18n/en.ts +301 -0
  72. package/src/tool/inflation/i18n/es.ts +301 -0
  73. package/src/tool/inflation/i18n/fr.ts +301 -0
  74. package/src/tool/inflation/index.ts +34 -0
  75. package/src/tool/inflation/logic.ts +92 -0
  76. package/src/tool/inflation/seo.astro +14 -0
  77. package/src/tool/inflation/ui.ts +17 -0
  78. package/src/tool/lateInterest/bibliography.astro +14 -0
  79. package/src/tool/lateInterest/component.astro +655 -0
  80. package/src/tool/lateInterest/i18n/en.ts +255 -0
  81. package/src/tool/lateInterest/i18n/es.ts +224 -0
  82. package/src/tool/lateInterest/i18n/fr.ts +224 -0
  83. package/src/tool/lateInterest/index.ts +34 -0
  84. package/src/tool/lateInterest/logic.ts +89 -0
  85. package/src/tool/lateInterest/seo.astro +14 -0
  86. package/src/tool/lateInterest/ui.ts +33 -0
  87. package/src/tool/legalInterestRate/bibliography.astro +14 -0
  88. package/src/tool/legalInterestRate/component.astro +650 -0
  89. package/src/tool/legalInterestRate/i18n/en.ts +159 -0
  90. package/src/tool/legalInterestRate/i18n/es.ts +159 -0
  91. package/src/tool/legalInterestRate/i18n/fr.ts +159 -0
  92. package/src/tool/legalInterestRate/index.ts +33 -0
  93. package/src/tool/legalInterestRate/logic.ts +29 -0
  94. package/src/tool/legalInterestRate/seo.astro +14 -0
  95. package/src/tool/legalInterestRate/ui.ts +23 -0
  96. package/src/tool/lotteryOptimizer/bibliography.astro +14 -0
  97. package/src/tool/lotteryOptimizer/component.astro +863 -0
  98. package/src/tool/lotteryOptimizer/i18n/en.ts +188 -0
  99. package/src/tool/lotteryOptimizer/i18n/es.ts +281 -0
  100. package/src/tool/lotteryOptimizer/i18n/fr.ts +188 -0
  101. package/src/tool/lotteryOptimizer/index.ts +33 -0
  102. package/src/tool/lotteryOptimizer/logic.ts +133 -0
  103. package/src/tool/lotteryOptimizer/seo.astro +14 -0
  104. package/src/tool/lotteryOptimizer/ui.ts +33 -0
  105. package/src/tool/mortgage/bibliography.astro +14 -0
  106. package/src/tool/mortgage/component.astro +1030 -0
  107. package/src/tool/mortgage/i18n/en.ts +227 -0
  108. package/src/tool/mortgage/i18n/es.ts +227 -0
  109. package/src/tool/mortgage/i18n/fr.ts +227 -0
  110. package/src/tool/mortgage/index.ts +34 -0
  111. package/src/tool/mortgage/logic.ts +118 -0
  112. package/src/tool/mortgage/seo.astro +14 -0
  113. package/src/tool/mortgage/ui.ts +35 -0
  114. package/src/tool/percentageCalculator/bibliography.astro +14 -0
  115. package/src/tool/percentageCalculator/component.astro +640 -0
  116. package/src/tool/percentageCalculator/i18n/en.ts +233 -0
  117. package/src/tool/percentageCalculator/i18n/es.ts +233 -0
  118. package/src/tool/percentageCalculator/i18n/fr.ts +233 -0
  119. package/src/tool/percentageCalculator/index.ts +34 -0
  120. package/src/tool/percentageCalculator/logic.ts +48 -0
  121. package/src/tool/percentageCalculator/seo.astro +14 -0
  122. package/src/tool/percentageCalculator/ui.ts +30 -0
  123. package/src/tool/rentIncreaseCalculator/bibliography.astro +14 -0
  124. package/src/tool/rentIncreaseCalculator/component.astro +587 -0
  125. package/src/tool/rentIncreaseCalculator/i18n/en.ts +159 -0
  126. package/src/tool/rentIncreaseCalculator/i18n/es.ts +220 -0
  127. package/src/tool/rentIncreaseCalculator/i18n/fr.ts +159 -0
  128. package/src/tool/rentIncreaseCalculator/index.ts +33 -0
  129. package/src/tool/rentIncreaseCalculator/logic.ts +43 -0
  130. package/src/tool/rentIncreaseCalculator/seo.astro +14 -0
  131. package/src/tool/rentIncreaseCalculator/ui.ts +19 -0
  132. package/src/tools.ts +16 -0
  133. package/src/types.ts +74 -0
@@ -0,0 +1,33 @@
1
+ import type { FinanceToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
+ import LotteryOptimizerComponent from './component.astro';
3
+ import LotteryOptimizerSEO from './seo.astro';
4
+ import LotteryOptimizerBibliography from './bibliography.astro';
5
+ import type { LotteryOptimizerUI } from './ui';
6
+
7
+ export type LotteryOptimizerLocaleContent = ToolLocaleContent<LotteryOptimizerUI>;
8
+
9
+ import { content as es } from './i18n/es';
10
+ import { content as en } from './i18n/en';
11
+ import { content as fr } from './i18n/fr';
12
+
13
+ export const lotteryOptimizer: FinanceToolEntry<LotteryOptimizerUI> = {
14
+ id: 'optimizador-loterias',
15
+ icons: {
16
+ bg: 'mdi:dice-multiple',
17
+ fg: 'mdi:star',
18
+ },
19
+ i18n: {
20
+ es: async () => es,
21
+ en: async () => en,
22
+ fr: async () => fr,
23
+ },
24
+ };
25
+
26
+ export { LotteryOptimizerComponent, LotteryOptimizerSEO, LotteryOptimizerBibliography };
27
+
28
+ export const LOTTERY_OPTIMIZER_TOOL: ToolDefinition = {
29
+ entry: lotteryOptimizer,
30
+ Component: LotteryOptimizerComponent,
31
+ SEOComponent: LotteryOptimizerSEO,
32
+ BibliographyComponent: LotteryOptimizerBibliography,
33
+ };
@@ -0,0 +1,133 @@
1
+ export type LotteryId = 'gordo' | 'nino' | 'euromillones' | 'primitiva' | 'bonoloto';
2
+
3
+ export interface LotteryGame {
4
+ id: LotteryId;
5
+ name: string;
6
+ cost: number;
7
+ jackpot: number;
8
+ odds: number;
9
+ description: string;
10
+ payoutRate: number;
11
+ }
12
+
13
+ export const LOTTERY_DATA: Record<LotteryId, LotteryGame> = {
14
+ gordo: {
15
+ id: 'gordo',
16
+ name: 'Lotería de Navidad',
17
+ cost: 20,
18
+ jackpot: 400000,
19
+ odds: 100000,
20
+ payoutRate: 70,
21
+ description: 'El mayor reparto de premios del mundo. Probabilidad alta de ganar algo.',
22
+ },
23
+ nino: {
24
+ id: 'nino',
25
+ name: 'Lotería del Niño',
26
+ cost: 20,
27
+ jackpot: 200000,
28
+ odds: 100000,
29
+ payoutRate: 70,
30
+ description: 'Triplica las posibilidades de reintegro respecto a Navidad.',
31
+ },
32
+ euromillones: {
33
+ id: 'euromillones',
34
+ name: 'Euromillones',
35
+ cost: 2.5,
36
+ jackpot: 17000000,
37
+ odds: 139838160,
38
+ payoutRate: 50,
39
+ description: 'Premios astronómicos, probabilidades casi imposibles.',
40
+ },
41
+ primitiva: {
42
+ id: 'primitiva',
43
+ name: 'La Primitiva',
44
+ cost: 1,
45
+ jackpot: 2000000,
46
+ odds: 139838160,
47
+ payoutRate: 55,
48
+ description: 'La lotería más antigua de España. Difícil pero más barata.',
49
+ },
50
+ bonoloto: {
51
+ id: 'bonoloto',
52
+ name: 'Bonoloto',
53
+ cost: 0.5,
54
+ jackpot: 400000,
55
+ odds: 13983816,
56
+ payoutRate: 55,
57
+ description: 'La más económica. Ideal para jugar a diario con poco presupuesto.',
58
+ },
59
+ };
60
+
61
+ export class LotteryLogic {
62
+ private static getChristmasRecommendation(tickets: number): { recommendation: string; optimalTickets: number } {
63
+ if (tickets < 5) {
64
+ return {
65
+ recommendation:
66
+ 'Para una gestión de riesgo básica, se suele buscar diversificar terminaciones. Jugar pocas unidades mantiene la ilusión con el mínimo riesgo de capital.',
67
+ optimalTickets: 1,
68
+ };
69
+ }
70
+ if (tickets < 10) {
71
+ return {
72
+ recommendation:
73
+ 'Acercarse a los 10 décimos (200€) garantiza estadísticamente un reintegro, pero recuerda que esto supone recuperar solo el 10% de lo invertido en ese nivel.',
74
+ optimalTickets: tickets,
75
+ };
76
+ }
77
+ return {
78
+ recommendation:
79
+ 'Has superado el umbral de diversificación básica. A partir de aquí, cada décimo extra aumenta tu exposición al riesgo sin mejorar la eficiencia de retorno.',
80
+ optimalTickets: 10,
81
+ };
82
+ }
83
+
84
+ private static getOtherRecommendation(
85
+ totalCost: number,
86
+ tickets: number,
87
+ cost: number
88
+ ): { recommendation: string; optimalTickets: number } {
89
+ if (totalCost > 15) {
90
+ return {
91
+ recommendation:
92
+ 'En juegos de probabilidad extrema, no hay "estrategia óptima" más allá de limitar estrictamente el gasto. Reducir la cuantía es la mejor jugada.',
93
+ optimalTickets: Math.floor(5 / cost),
94
+ };
95
+ }
96
+ return {
97
+ recommendation:
98
+ 'Mantener una participación simbólica es la forma más racional de participar en sorteos con botes astronómicos.',
99
+ optimalTickets: tickets,
100
+ };
101
+ }
102
+
103
+ static calculateStats(id: LotteryId, tickets: number) {
104
+ const game = LOTTERY_DATA[id];
105
+ const totalCost = tickets * game.cost;
106
+ const winProbability = 1 - Math.pow((game.odds - 1) / game.odds, tickets);
107
+ const expectedValue = game.jackpot * (tickets / game.odds) - totalCost;
108
+
109
+ const isChristmas = id === 'gordo' || id === 'nino';
110
+ const { recommendation, optimalTickets } = isChristmas
111
+ ? this.getChristmasRecommendation(tickets)
112
+ : this.getOtherRecommendation(totalCost, tickets, game.cost);
113
+
114
+ return {
115
+ totalCost,
116
+ winProbability: winProbability * 100,
117
+ expectedValue,
118
+ recommendation,
119
+ optimalTickets,
120
+ efficiency: (game.payoutRate / 100) * (tickets / totalCost),
121
+ };
122
+ }
123
+
124
+ static compareGames() {
125
+ return Object.values(LOTTERY_DATA)
126
+ .map((game) => ({
127
+ name: game.name,
128
+ score: game.payoutRate / 100 / (game.odds / 1000000),
129
+ odds: game.odds,
130
+ }))
131
+ .sort((a, b) => b.score - a.score);
132
+ }
133
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { lotteryOptimizer } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await lotteryOptimizer.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+ <SEORenderer content={{ locale: locale as string, sections: content.seo }} />
@@ -0,0 +1,33 @@
1
+ export interface LotteryOptimizerUI {
2
+ gameTranslations?: Record<string, { name: string; description: string }>;
3
+ labelTitle: string;
4
+ labelDescription: string;
5
+ labelSelectGame: string;
6
+ labelConfigurePlay: string;
7
+ labelAdjustQuantity: string;
8
+ labelTotalInvestment: string;
9
+ labelTickets: string;
10
+ labelUnits: string;
11
+ labelExposureAnalysis: string;
12
+ labelSelectLottery: string;
13
+ labelOptimalCutoff: string;
14
+ labelProbabilitySuccess: string;
15
+ labelExpectedValue: string;
16
+ labelReturnTheoretical: string;
17
+ labelSocialReturnIndex: string;
18
+ labelLow: string;
19
+ labelMedium: string;
20
+ labelHigh: string;
21
+ labelComparison: string;
22
+ labelLottery: string;
23
+ labelCost: string;
24
+ labelTypicalPrize: string;
25
+ labelDifficulty: string;
26
+ labelAccessible: string;
27
+ labelDifficult: string;
28
+ labelExtreme: string;
29
+ labelNote: string;
30
+ currencySymbol: string;
31
+ currencyCode: string;
32
+ currencyLocale: string;
33
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { mortgage } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await mortgage.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <SharedBibliography links={content.bibliography} />}