@jjlmoya/utils-civic 1.5.0 → 1.6.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 (38) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +2 -0
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +1 -1
  6. package/src/tests/tool_validation.test.ts +1 -1
  7. package/src/tool/participatory-budget-allocator/bibliography.astro +6 -0
  8. package/src/tool/participatory-budget-allocator/bibliography.ts +8 -0
  9. package/src/tool/participatory-budget-allocator/component.astro +61 -0
  10. package/src/tool/participatory-budget-allocator/contract.test.ts +13 -0
  11. package/src/tool/participatory-budget-allocator/controller.ts +108 -0
  12. package/src/tool/participatory-budget-allocator/dom-views.test.ts +14 -0
  13. package/src/tool/participatory-budget-allocator/dom-views.ts +58 -0
  14. package/src/tool/participatory-budget-allocator/entry.ts +27 -0
  15. package/src/tool/participatory-budget-allocator/evaluator.ts +24 -0
  16. package/src/tool/participatory-budget-allocator/i18n/de.ts +44 -0
  17. package/src/tool/participatory-budget-allocator/i18n/en.ts +79 -0
  18. package/src/tool/participatory-budget-allocator/i18n/es.ts +43 -0
  19. package/src/tool/participatory-budget-allocator/i18n/fr.ts +43 -0
  20. package/src/tool/participatory-budget-allocator/i18n/id.ts +43 -0
  21. package/src/tool/participatory-budget-allocator/i18n/it.ts +43 -0
  22. package/src/tool/participatory-budget-allocator/i18n/ja.ts +43 -0
  23. package/src/tool/participatory-budget-allocator/i18n/ko.ts +43 -0
  24. package/src/tool/participatory-budget-allocator/i18n/nl.ts +43 -0
  25. package/src/tool/participatory-budget-allocator/i18n/pl.ts +43 -0
  26. package/src/tool/participatory-budget-allocator/i18n/pt.ts +43 -0
  27. package/src/tool/participatory-budget-allocator/i18n/ru.ts +43 -0
  28. package/src/tool/participatory-budget-allocator/i18n/sv.ts +43 -0
  29. package/src/tool/participatory-budget-allocator/i18n/tr.ts +43 -0
  30. package/src/tool/participatory-budget-allocator/i18n/zh.ts +43 -0
  31. package/src/tool/participatory-budget-allocator/index.ts +11 -0
  32. package/src/tool/participatory-budget-allocator/logic.test.ts +48 -0
  33. package/src/tool/participatory-budget-allocator/logic.ts +146 -0
  34. package/src/tool/participatory-budget-allocator/participatory-budget-allocator.css +426 -0
  35. package/src/tool/participatory-budget-allocator/seo.astro +14 -0
  36. package/src/tool/participatory-budget-allocator/storage.ts +32 -0
  37. package/src/tool/participatory-budget-allocator/ui.ts +88 -0
  38. package/src/tools.ts +2 -0
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: 'Budget disponible', budgetHelp: 'Utilisez une seule monnaie et saisissez le plafond à ne pas dépasser.', proposalsHeading: 'Ajouter des projets avec un score comparable', proposalNameLabel: 'Nom du projet', proposalCostLabel: 'Coût', proposalScoreLabel: 'Voix ou score de bénéfice', addProposal: 'Ajouter un projet', removeProposal: 'Supprimer', calculateNote: 'La sélection se met à jour pendant la saisie. Chaque projet est financé en entier ou laissé de côté.', loadExample: 'Charger un exemple', printAction: 'Imprimer la fiche de révision', resultHeading: 'Mosaïque budgétaire', emptyResult: 'Ajoutez des projets pour voir quel ensemble complet respecte le budget.', excludedLabel: 'Non financé', spentLabel: 'Coût total', remainingLabel: 'Budget restant', scoreLabel: 'Score total', proposalCountLabel: 'projets', selectedStatus: 'Financé', tooExpensiveStatus: 'Impossible', notSelectedStatus: 'Écarté', invalidStatus: 'À corriger', reasonLabel: 'Pourquoi', methodHeading: 'Méthode appliquée', methodText: 'L outil résout un modèle de sac à dos 0/1. Chaque projet possède un coût et un score comparable. Il recherche les combinaisons admissibles, maximise le score, puis utilise le coût inférieur, le nombre réduit de projets et l ordre de saisie comme départages déterministes.', limitsHeading: 'Ce que cet outil ne fait pas', limitsText: 'Il ne décide pas si un projet est juste, légal, éligible, réalisable ou préférable socialement. Il ne remplace ni les règles de participation ni un vote.', warningsHeading: 'Cas limites et alertes de données', warningsText: 'Gardez les scores comparables et la même base de coûts. Les zéros, les noms en double, les estimations incomplètes, les dépendances et les bénéfices divisibles exigent une vérification humaine.', noProposalsWarning: 'Aucun projet n a été saisi.', noFeasibleWarning: 'Aucun projet ne respecte le budget disponible.', invalidBudget: 'Saisissez un budget positif ou nul. Le modèle accepte jusqu à 20 000,00 dans la monnaie choisie.', budgetTooLarge: 'Le budget dépasse la limite de 20 000,00. Réduisez le plafond ou divisez l exercice.', invalidProposal: 'Chaque ligne doit avoir un nom, un coût positif ou nul et un score positif ou nul.', costExceedsBudget: 'Ce coût dépasse le budget disponible. Le projet ne peut pas être sélectionné.', tieBreakLabel: 'Règle déterministe', budgetUsedLabel: 'utilisé', budgetLeftLabel: 'restant', selectedTilesLabel: 'Blocs sélectionnés', allocationLabel: 'Capacité budgétaire', statusSaved: 'Brouillon enregistré localement dans ce navigateur.',
8
+ };
9
+ const faq = [
10
+ { question: 'Qu optimise cet allocateur ?', answer: 'Il choisit un ensemble admissible de projets entiers qui maximise le score total saisi sans dépasser le plafond. Il ne juge pas si ce score est juste ou pertinent.' },
11
+ { question: 'Pourquoi les projets sont-ils tout ou rien ?', answer: 'La première version utilise un modèle 0/1. Chaque projet est financé à son coût complet ou écarté, ce qui convient aux réalisations dont l utilité dépend de leur achèvement.' },
12
+ { question: 'Que se passe-t-il en cas d égalité ?', answer: 'L outil choisit d abord le coût total le plus faible, puis le nombre de projets le plus réduit et enfin l ordre de saisie. Le départage reste reproductible.' },
13
+ { question: 'Le résultat peut-il décider d un vrai budget ?', answer: 'Non. Il s agit d un scénario transparent. Vérifiez l éligibilité, les dépendances, la capacité, la base monétaire et la procédure officielle.' },
14
+ ];
15
+ const howTo = [
16
+ { name: 'Fixer le plafond', text: 'Saisissez le montant disponible pour cette session et gardez la même base monétaire.' },
17
+ { name: 'Ajouter les projets complets', text: 'Saisissez chaque projet une fois avec son coût entier et un score comparable.' },
18
+ { name: 'Examiner la mosaïque', text: 'Observez l ensemble financé, le score, le coût et le budget restant pendant la saisie.' },
19
+ { name: 'Lire les exclusions', text: 'Distinguez les projets trop chers seuls de ceux qui perdent face à une meilleure combinaison admissible.' },
20
+ { name: 'Faire les vérifications humaines', text: 'Comparez le scénario aux règles, dépendances, capacités et personnes concernées avant la réunion.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: 'Allocateur de budget participatif', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: 'Sélectionnez des projets publics entiers sous un plafond budgétaire avec une règle d optimisation transparente.', url: 'https://gamebob.dev/fr/allocateur-budget-participatif', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: 'Répartir un budget participatif fixe', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'allocateur-budget-participatif', title: 'Allocateur de budget participatif', description: 'Sélectionnez des projets entiers sous un budget fixe, maximisez un score déclaré et comprenez le coût et la raison de chaque exclusion.', ui, seo: [
27
+ { type: 'title', text: 'Transformer un plafond budgétaire en scénario reproductible', level: 2 },
28
+ { type: 'paragraph', html: 'Une session de budget public contient souvent plus de projets utiles que les ressources disponibles. Cet allocateur rend l arbitrage explicite: saisissez le plafond, ajoutez les projets entiers et attribuez à chacun des voix ou un score de bénéfice comparable. Le résultat montre un ensemble réalisable au lieu de cacher le choix derrière une recommandation unique.' },
29
+ { type: 'title', text: 'Comment la sélection est calculée', level: 2 },
30
+ { type: 'paragraph', html: 'Le modèle est un sac à dos 0/1. Le navigateur compare les combinaisons qui restent sous le plafond et garde celle qui a le score total le plus élevé. Il applique ensuite un départage visible: coût inférieur, moins de projets, puis ordre de saisie. Le score est l objectif déclaré, pas une mesure indépendante de la valeur publique.' },
31
+ { type: 'table', headers: ['Champ', 'Sens', 'Question de révision'], rows: [['Coût', 'Montant complet nécessaire à la réalisation', 'Toutes les lignes reposent-elles sur la même base ?'], ['Score', 'Voix ou bénéfice saisi par l utilisateur', 'Les valeurs sont-elles comparables ?'], ['Budget', 'Coût total maximal de la sélection', 'Le plafond couvre-t-il les mêmes coûts ?'], ['Exclusion', 'Trop cher seul ou battu par un meilleur ensemble', 'La raison est-elle mathématique ou politique ?']] },
32
+ { type: 'title', text: 'Préparer des entrées qui ne trompent pas', level: 2 },
33
+ { type: 'list', items: ['Confirmez l éligibilité de chaque projet pour la même session.', 'Utilisez le coût complet ou de vraies étapes indépendantes.', 'Notez l origine des voix et des scores de bénéfice.', 'Vérifiez séparément les dépendances, la maintenance, le droit et la capacité.', 'Conservez la sélection et les motifs d exclusion dans le compte rendu.'] },
34
+ { type: 'tip', title: 'Un score est un objectif choisi', html: 'Avec des voix, le résultat maximise les voix totales. Avec une évaluation de bénéfice, il maximise cette évaluation. Changer le score change la question: conservez donc sa méthode avec le résultat.' },
35
+ { type: 'title', text: 'Lire les ensembles financé et exclu', level: 2 },
36
+ { type: 'paragraph', html: 'Les projets financés indiquent le coût, le score et le budget restant. Un projet impossible coûte plus que le plafond à lui seul. Un projet écarté pourrait tenir seul mais ne fait pas partie de la meilleure combinaison selon l objectif et le départage choisis.' },
37
+ { type: 'title', text: 'Limites et prochaines vérifications', level: 2 },
38
+ { type: 'paragraph', html: 'L allocateur ne juge ni l équité entre quartiers, ni le risque de livraison, ni les conflits entre projets, ni l éligibilité juridique. Le modèle est limité à 20 000,00 dans la monnaie choisie pour conserver une recherche exacte réactive.' },
39
+ { type: 'paragraph', html: 'Une combinaison qui obtient un score élevé ne vaut que par la qualité de ses coûts et de la méthode de notation.' },
40
+ { type: 'title', text: 'Faire du budget restant un sujet de discussion', level: 2 },
41
+ { type: 'paragraph', html: 'Un reliquat peut montrer qu aucun projet supplémentaire n améliore la sélection actuelle. Il peut aussi signaler un projet admissible manquant ou une réserve volontaire.' },
42
+ { type: 'tip', title: 'Vérifier avant de décider', html: 'Lisez la sélection mathématique avec les règles officielles de participation et la parole des personnes concernées.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: 'Anggaran tersedia', budgetHelp: 'Gunakan satu mata uang dan masukkan batas yang tidak boleh terlampaui.', proposalsHeading: 'Tambahkan usulan dengan skor yang sebanding', proposalNameLabel: 'Nama usulan', proposalCostLabel: 'Biaya', proposalScoreLabel: 'Suara atau skor manfaat', addProposal: 'Tambah usulan', removeProposal: 'Hapus', calculateNote: 'Pilihan diperbarui saat Anda mengedit baris. Setiap usulan didanai penuh atau tidak dipilih.', loadExample: 'Muat contoh', printAction: 'Cetak lembar tinjauan', resultHeading: 'Mozaik anggaran', emptyResult: 'Tambahkan usulan untuk melihat kombinasi lengkap yang sesuai anggaran.', excludedLabel: 'Tidak didanai', spentLabel: 'Total biaya', remainingLabel: 'Sisa anggaran', scoreLabel: 'Total skor', proposalCountLabel: 'usulan', selectedStatus: 'Didanai', tooExpensiveStatus: 'Tidak muat', notSelectedStatus: 'Tidak dipilih', invalidStatus: 'Perlu diperbaiki', reasonLabel: 'Mengapa', methodHeading: 'Metode yang digunakan', methodText: 'Alat ini menyelesaikan model ransel 0/1. Setiap usulan memiliki biaya dan skor yang dapat dibandingkan. Kombinasi yang layak dicari untuk memaksimalkan skor, lalu biaya lebih rendah, jumlah usulan lebih sedikit, dan urutan masukan menjadi aturan seri yang tetap.', limitsHeading: 'Yang tidak dilakukan alat ini', limitsText: 'Alat ini tidak menentukan apakah usulan adil, legal, layak didanai, dapat dilaksanakan, atau lebih disukai masyarakat. Alat ini bukan pengganti aturan partisipasi atau pemungutan suara.', warningsHeading: 'Kasus tepi dan peringatan data', warningsText: 'Jaga agar skor dapat dibandingkan dan gunakan dasar biaya yang sama. Nilai nol, nama ganda, perkiraan yang tidak lengkap, ketergantungan, dan manfaat yang dapat dibagi memerlukan tinjauan manusia.', noProposalsWarning: 'Belum ada usulan yang dimasukkan.', noFeasibleWarning: 'Tidak ada usulan yang sesuai dengan anggaran tersedia.', invalidBudget: 'Masukkan anggaran nol atau lebih. Model browser menerima hingga 20.000,00 dalam mata uang pilihan.', budgetTooLarge: 'Anggaran melebihi batas model 20.000,00. Kurangi batas atau bagi latihan menjadi beberapa putaran.', invalidProposal: 'Setiap baris memerlukan nama, biaya tidak negatif, dan skor tidak negatif.', costExceedsBudget: 'Biaya ini melebihi anggaran tersedia. Usulan tidak dapat dipilih.', tieBreakLabel: 'Aturan tetap', budgetUsedLabel: 'terpakai', budgetLeftLabel: 'tersisa', selectedTilesLabel: 'Blok terpilih', allocationLabel: 'Kapasitas anggaran', statusSaved: 'Draf disimpan secara lokal di browser ini.',
8
+ };
9
+ const faq = [
10
+ { question: 'Apa yang dioptimalkan alat ini?', answer: 'Alat ini memilih kumpulan usulan utuh yang layak dan memaksimalkan total skor yang Anda masukkan tanpa melewati batas anggaran. Alat ini tidak menilai apakah skor itu adil atau bermakna.' },
11
+ { question: 'Mengapa usulan dipilih seluruhnya atau tidak sama sekali?', answer: 'Versi pertama menggunakan model 0/1. Setiap usulan dibiayai dengan biaya penuh atau dikeluarkan, sesuai untuk proyek yang manfaatnya bergantung pada penyelesaian penuh.' },
12
+ { question: 'Apa yang terjadi jika dua alokasi memiliki skor yang sama?', answer: 'Alat memilih total biaya yang lebih rendah, lalu jumlah usulan yang lebih sedikit, kemudian urutan masukan yang lebih awal. Aturan ini dapat diulang oleh peninjau lain.' },
13
+ { question: 'Apakah hasil ini bisa menentukan anggaran nyata?', answer: 'Tidak. Ini adalah skenario transparan. Periksa kelayakan, ketergantungan, kapasitas pelaksanaan, dasar mata uang, dan proses resmi.' },
14
+ ];
15
+ const howTo = [
16
+ { name: 'Tetapkan batas', text: 'Masukkan jumlah yang tersedia untuk putaran ini dan gunakan dasar mata uang yang konsisten.' },
17
+ { name: 'Tambahkan usulan lengkap', text: 'Masukkan setiap usulan sekali dengan biaya penuh dan skor suara atau manfaat yang sebanding.' },
18
+ { name: 'Periksa mozaik', text: 'Tinjau usulan yang didanai, skor, biaya, dan sisa anggaran saat baris berubah.' },
19
+ { name: 'Baca pengecualian', text: 'Bedakan usulan yang terlalu mahal sendiri dari usulan yang kalah oleh kombinasi layak yang lebih baik.' },
20
+ { name: 'Lakukan pemeriksaan manusia', text: 'Bandingkan skenario dengan aturan, ketergantungan, kapasitas, dan kebutuhan warga sebelum rapat.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: 'Alokator anggaran partisipatif', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: 'Pilih usulan publik secara utuh di bawah batas anggaran tetap dengan aturan optimasi transparan.', url: 'https://gamebob.dev/id/alokator-anggaran-partisipatif', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: 'Membagi anggaran partisipatif tetap', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'alokator-anggaran-partisipatif', title: 'Alokator anggaran partisipatif', description: 'Pilih usulan utuh di bawah batas anggaran tetap, maksimalkan skor yang dinyatakan, dan pahami biaya serta alasan setiap pengecualian.', ui, seo: [
27
+ { type: 'title', text: 'Ubah batas anggaran menjadi skenario yang dapat diulang', level: 2 },
28
+ { type: 'paragraph', html: 'Putaran anggaran publik sering memiliki lebih banyak usulan bermanfaat daripada dana yang tersedia. Alat ini membuat pertukaran menjadi jelas: masukkan batas, tambahkan usulan lengkap, dan beri masing-masing skor suara atau manfaat yang sebanding. Hasilnya menunjukkan kumpulan yang layak, bukan rekomendasi tersembunyi.' },
29
+ { type: 'title', text: 'Cara pilihan dihitung', level: 2 },
30
+ { type: 'paragraph', html: 'Model ini adalah ransel 0/1. Browser membandingkan kombinasi yang tetap di bawah batas dan menyimpan kombinasi dengan skor total terbesar. Jika seri, alat memilih biaya lebih rendah, lebih sedikit usulan, lalu urutan masukan lebih awal. Skor adalah tujuan yang Anda tetapkan, bukan ukuran nilai publik yang berdiri sendiri.' },
31
+ { type: 'table', headers: ['Kolom', 'Arti', 'Pertanyaan tinjauan'], rows: [['Biaya', 'Jumlah penuh untuk menjalankan usulan', 'Apakah semua baris memakai dasar yang sama?'], ['Skor', 'Suara atau nilai manfaat dari pengguna', 'Apakah nilainya dapat dibandingkan?'], ['Anggaran', 'Biaya maksimum usulan terpilih', 'Apakah batas mencakup biaya yang sama?'], ['Pengecualian', 'Terlalu mahal sendiri atau kalah oleh kombinasi lebih baik', 'Apakah alasannya matematis atau perlu kebijakan?']] },
32
+ { type: 'title', text: 'Siapkan masukan yang tidak menyesatkan', level: 2 },
33
+ { type: 'list', items: ['Pastikan semua usulan memenuhi syarat untuk putaran yang sama.', 'Gunakan biaya pelaksanaan penuh atau tahap yang benar-benar mandiri.', 'Catat cara suara dan skor manfaat dibuat.', 'Periksa ketergantungan, pemeliharaan, legalitas, dan kapasitas secara terpisah.', 'Simpan pilihan dan alasan pengecualian sebagai catatan tinjauan.'] },
34
+ { type: 'tip', title: 'Skor adalah tujuan yang dipilih', html: 'Jika skor berarti suara, hasil memaksimalkan jumlah suara. Jika skor berarti manfaat, hasil memaksimalkan penilaian itu. Mengubah skor berarti mengubah pertanyaan, jadi simpan metodenya bersama hasil.' },
35
+ { type: 'title', text: 'Baca kumpulan yang didanai dan dikecualikan', level: 2 },
36
+ { type: 'paragraph', html: 'Usulan yang didanai menampilkan biaya, skor, dan sisa anggaran. Usulan yang tidak muat lebih mahal daripada batas jika berdiri sendiri. Usulan yang tidak dipilih mungkin muat sendiri, tetapi bukan bagian dari kombinasi terbaik menurut tujuan dan aturan seri yang dipilih.' },
37
+ { type: 'title', text: 'Batasan dan pemeriksaan berikutnya', level: 2 },
38
+ { type: 'paragraph', html: 'Alokator tidak menilai keadilan antarwilayah, risiko pelaksanaan, konflik proyek, atau kelayakan hukum. Model browser dibatasi pada 20.000,00 agar pencarian eksak tetap responsif.' },
39
+ { type: 'paragraph', html: 'Kombinasi dengan skor tinggi hanya dapat dipercaya jika dasar biayanya dan cara penilaiannya juga jelas.' },
40
+ { type: 'title', text: 'Gunakan sisa anggaran sebagai bahan diskusi', level: 2 },
41
+ { type: 'paragraph', html: 'Sisa dana dapat berarti tidak ada usulan tambahan yang meningkatkan pilihan saat ini. Sisa itu juga dapat menunjukkan usulan yang belum dimasukkan atau dana yang sengaja dicadangkan.' },
42
+ { type: 'tip', title: 'Periksa sebelum memutuskan', html: 'Baca pilihan matematis bersama aturan partisipasi resmi dan suara warga yang terdampak.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: 'Budget disponibile', budgetHelp: 'Usa una sola valuta e inserisci il limite che non deve essere superato.', proposalsHeading: 'Aggiungi proposte con un punteggio confrontabile', proposalNameLabel: 'Nome della proposta', proposalCostLabel: 'Costo', proposalScoreLabel: 'Voti o punteggio di beneficio', addProposal: 'Aggiungi proposta', removeProposal: 'Rimuovi', calculateNote: 'La selezione si aggiorna mentre modifichi le righe. Ogni proposta è finanziata per intero oppure esclusa.', loadExample: 'Carica esempio', printAction: 'Stampa scheda di revisione', resultHeading: 'Mosaico del budget', emptyResult: 'Aggiungi proposte per vedere quale insieme completo rientra nel budget.', excludedLabel: 'Non finanziata', spentLabel: 'Costo totale', remainingLabel: 'Budget residuo', scoreLabel: 'Punteggio totale', proposalCountLabel: 'proposte', selectedStatus: 'Finanziata', tooExpensiveStatus: 'Non rientra', notSelectedStatus: 'Esclusa', invalidStatus: 'Da correggere', reasonLabel: 'Perché', methodHeading: 'Metodo applicato', methodText: 'Lo strumento risolve un modello zaino 0/1. Ogni proposta ha un costo e un punteggio confrontabile. Cerca combinazioni ammissibili, massimizza il punteggio e poi usa costo minore, meno proposte e ordine di inserimento come spareggi deterministici.', limitsHeading: 'Cosa non fa questo strumento', limitsText: 'Non decide se una proposta è equa, legale, ammissibile, realizzabile o preferibile per la società. Non sostituisce le regole del bilancio partecipativo né una votazione.', warningsHeading: 'Casi limite e avvisi sui dati', warningsText: 'Mantieni confrontabili i punteggi e usa la stessa base di costo. Zeri, nomi duplicati, stime incomplete, dipendenze e benefici divisibili richiedono una revisione umana.', noProposalsWarning: 'Non è stata inserita alcuna proposta.', noFeasibleWarning: 'Nessuna proposta rientra nel budget disponibile.', invalidBudget: 'Inserisci un budget non negativo. Il modello del browser accetta fino a 20.000,00 nella valuta scelta.', budgetTooLarge: 'Il budget supera il limite del modello di 20.000,00. Riduci il limite o dividi l esercizio.', invalidProposal: 'Ogni riga richiede un nome, un costo non negativo e un punteggio non negativo.', costExceedsBudget: 'Questo costo supera il budget disponibile. La proposta non può essere selezionata.', tieBreakLabel: 'Regola deterministica', budgetUsedLabel: 'usato', budgetLeftLabel: 'residuo', selectedTilesLabel: 'Blocchi selezionati', allocationLabel: 'Capacità di budget', statusSaved: 'Bozza salvata localmente in questo browser.',
8
+ };
9
+ const faq = [
10
+ { question: 'Che cosa ottimizza questo allocatore?', answer: 'Seleziona un insieme ammissibile di proposte intere che massimizza il punteggio totale inserito senza superare il limite. Non stabilisce se il punteggio sia equo o significativo.' },
11
+ { question: 'Perché le proposte sono tutto o niente?', answer: 'La prima versione usa un modello 0/1. Ogni proposta viene finanziata al costo completo oppure esclusa, adatto ai progetti il cui valore dipende dalla realizzazione completa.' },
12
+ { question: 'Che cosa succede a parità di punteggio?', answer: 'Vengono scelti prima il costo totale minore, poi un numero inferiore di proposte e infine l ordine di inserimento più precoce. Lo spareggio è quindi riproducibile.' },
13
+ { question: 'Il risultato può decidere un budget reale?', answer: 'No. È uno scenario trasparente. Verifica ammissibilità, dipendenze, capacità di realizzazione, base monetaria e procedura ufficiale.' },
14
+ ];
15
+ const howTo = [
16
+ { name: 'Imposta il limite', text: 'Inserisci l importo disponibile per questa tornata e mantieni costante la base monetaria.' },
17
+ { name: 'Aggiungi proposte complete', text: 'Inserisci ogni proposta una volta con costo completo e punteggio confrontabile.' },
18
+ { name: 'Esamina il mosaico', text: 'Controlla insieme finanziato, punteggio, costo e budget residuo mentre cambiano le righe.' },
19
+ { name: 'Leggi le esclusioni', text: 'Distingui le proposte troppo costose da sole da quelle sconfitte da una combinazione ammissibile migliore.' },
20
+ { name: 'Applica controlli umani', text: 'Confronta lo scenario con regole, dipendenze, capacità e persone coinvolte prima della riunione.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: 'Allocatore di budget partecipativo', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: 'Seleziona proposte pubbliche intere sotto un limite di budget con una regola di ottimizzazione trasparente.', url: 'https://gamebob.dev/it/allocatore-budget-partecipativo', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: 'Distribuire un budget partecipativo fisso', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'allocatore-budget-partecipativo', title: 'Allocatore di budget partecipativo', description: 'Seleziona proposte intere entro un budget fisso, massimizza un punteggio dichiarato e comprendi costo e motivo di ogni esclusione.', ui, seo: [
27
+ { type: 'title', text: 'Trasformare un limite di budget in uno scenario riproducibile', level: 2 },
28
+ { type: 'paragraph', html: 'Una tornata di bilancio pubblico contiene spesso più proposte valide dei fondi disponibili. Questo allocatore rende esplicito il compromesso: inserisci il limite, aggiungi proposte complete e assegna a ciascuna voti o un punteggio di beneficio confrontabile. Il risultato mostra un insieme ammissibile invece di nascondere la scelta dietro una raccomandazione.' },
29
+ { type: 'title', text: 'Come viene calcolata la selezione', level: 2 },
30
+ { type: 'paragraph', html: 'Il modello è uno zaino 0/1. Il browser confronta le combinazioni entro il limite e conserva quella con il punteggio totale più alto. Poi applica lo spareggio visibile: costo minore, meno proposte e ordine di inserimento. Il punteggio è l obiettivo dichiarato, non una misura indipendente del valore pubblico.' },
31
+ { type: 'table', headers: ['Campo', 'Significato', 'Domanda di revisione'], rows: [['Costo', 'Importo completo per realizzare la proposta', 'Tutte le righe usano la stessa base?'], ['Punteggio', 'Voti o valore di beneficio inserito', 'I valori sono confrontabili?'], ['Budget', 'Costo totale massimo della selezione', 'Il limite include gli stessi costi?'], ['Esclusione', 'Troppo costosa da sola o battuta da un insieme migliore', 'La ragione è matematica o richiede una scelta politica?']] },
32
+ { type: 'title', text: 'Preparare dati che non ingannino', level: 2 },
33
+ { type: 'list', items: ['Conferma l ammissibilità di ogni proposta per la stessa tornata.', 'Usa il costo completo o fasi davvero indipendenti.', 'Registra come sono stati prodotti voti e punteggi.', 'Controlla separatamente dipendenze, manutenzione, aspetti legali e capacità.', 'Conserva selezione e motivi di esclusione come verbale di revisione.'] },
34
+ { type: 'tip', title: 'Un punteggio è un obiettivo scelto', html: 'Se rappresenta voti, il risultato massimizza i voti totali. Se rappresenta benefici, massimizza quella valutazione. Cambiare punteggio cambia la domanda: conserva quindi il metodo insieme al risultato.' },
35
+ { type: 'title', text: 'Leggere gli insiemi finanziato ed escluso', level: 2 },
36
+ { type: 'paragraph', html: 'Le proposte finanziate mostrano costo, punteggio e budget residuo. Una proposta che non rientra costa più del limite da sola. Una proposta esclusa potrebbe rientrare da sola, ma non appartiene alla combinazione migliore secondo l obiettivo e lo spareggio scelti.' },
37
+ { type: 'title', text: 'Limiti e controlli successivi', level: 2 },
38
+ { type: 'paragraph', html: 'L allocatore non giudica equità tra quartieri, rischio di consegna, conflitti tra progetti o ammissibilità legale. Il modello del browser è limitato a 20.000,00 per mantenere reattiva la ricerca esatta.' },
39
+ { type: 'paragraph', html: 'Una combinazione con un punteggio alto è affidabile solo se sono solide anche la base dei costi e la raccolta dei punteggi.' },
40
+ { type: 'title', text: 'Usare il budget residuo per discutere', level: 2 },
41
+ { type: 'paragraph', html: 'Un residuo può indicare che nessuna proposta ulteriore migliora la selezione attuale. Può anche segnalare una proposta ammissibile mancante o una riserva intenzionale.' },
42
+ { type: 'tip', title: 'Controllare prima di decidere', html: 'Leggi la selezione matematica insieme alle regole ufficiali di partecipazione e alle voci delle persone coinvolte.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: '利用可能な予算', budgetHelp: '通貨を統一し、超えてはならない上限を入力してください。', proposalsHeading: '比較できるスコアで提案を追加', proposalNameLabel: '提案名', proposalCostLabel: '費用', proposalScoreLabel: '投票数または便益スコア', addProposal: '提案を追加', removeProposal: '削除', calculateNote: '行を編集すると選択結果が更新されます。各提案は全額採択されるか、対象外になります。', loadExample: '例を読み込む', printAction: '確認用シートを印刷', resultHeading: '予算モザイク', emptyResult: '提案を追加すると、予算に収まる組み合わせを確認できます。', excludedLabel: '不採択', spentLabel: '合計費用', remainingLabel: '残り予算', scoreLabel: '合計スコア', proposalCountLabel: '件', selectedStatus: '採択', tooExpensiveStatus: '予算外', notSelectedStatus: '対象外', invalidStatus: '修正が必要', reasonLabel: '理由', methodHeading: '適用した方法', methodText: 'このツールは0/1ナップサックモデルを解きます。各提案には費用と比較可能なスコアがあります。実行可能な組み合わせの中でスコアを最大化し、同点なら費用が低いもの、提案数が少ないもの、入力順が早いものを選びます。', limitsHeading: 'このツールが判断しないこと', limitsText: '提案が公平、合法、対象、実行可能、または社会的に望ましいかは判断しません。参加型予算のルールや投票の代わりにもなりません。', warningsHeading: '例外とデータの注意', warningsText: 'スコアの意味と費用の基準をそろえてください。ゼロ、重複名、不完全な見積もり、依存関係、分割できる便益は人が確認する必要があります。', noProposalsWarning: '提案が入力されていません。', noFeasibleWarning: '利用可能な予算に収まる提案がありません。', invalidBudget: '0以上の予算を入力してください。ブラウザモデルは選択した通貨で20,000.00まで対応します。', budgetTooLarge: '予算がモデル上限の20,000.00を超えています。上限を下げるか、練習を分けてください。', invalidProposal: '各行には名前、0以上の費用、0以上のスコアが必要です。', costExceedsBudget: 'この費用は利用可能な予算を超えています。提案を選択できません。', tieBreakLabel: '決定的なルール', budgetUsedLabel: '使用', budgetLeftLabel: '残り', selectedTilesLabel: '選択されたブロック', allocationLabel: '予算容量', statusSaved: '下書きをこのブラウザに保存しました。',
8
+ };
9
+ const faq = [
10
+ { question: 'この配分ツールは何を最適化しますか?', answer: '上限を超えず、入力した合計スコアを最大化する、提案全体の実行可能な組み合わせを選びます。スコアが公平か有意義かは判断しません。' },
11
+ { question: 'なぜ提案は全額採択か不採択なのですか?', answer: '最初の版は0/1モデルを使います。提案は全費用で実施するか除外します。完成して初めて役立つ事業に適した考え方です。' },
12
+ { question: '同じスコアの配分があるとどうなりますか?', answer: '合計費用が低いもの、提案数が少ないもの、入力順が早いものを順に選びます。他の人も結果を再現できます。' },
13
+ { question: 'この結果だけで実際の予算を決められますか?', answer: 'いいえ。これは透明なシナリオです。対象条件、依存関係、実施能力、費用の基準、公式手続きを確認してください。' },
14
+ ];
15
+ const howTo = [
16
+ { name: '上限を設定する', text: 'このラウンドで使える金額を入力し、通貨と費用の基準を統一します。' },
17
+ { name: '提案を入力する', text: '各提案を一度だけ入力し、全費用と比較可能な投票数または便益スコアを加えます。' },
18
+ { name: 'モザイクを確認する', text: '行を更新しながら、採択案、スコア、費用、残り予算を確認します。' },
19
+ { name: '対象外の理由を読む', text: '単独でも高すぎる提案と、より良い組み合わせに負けた提案を区別します。' },
20
+ { name: '人による確認を行う', text: '会議で使う前に、対象条件、依存関係、実施能力、公式ルールと照合します。' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: '参加型予算配分ツール', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: '固定された予算上限の下で公共提案を全体として選び、透明な最適化ルールを示します。', url: 'https://gamebob.dev/ja/participatory-budget-allocator', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: '固定された参加型予算を配分する', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'participatory-budget-allocator', title: '参加型予算配分ツール', description: '固定予算の下で提案全体を選び、宣言したスコアを最大化し、各対象外の費用と理由を確認します。', ui, seo: [
27
+ { type: 'title', text: '予算上限を再現可能なシナリオに変える', level: 2 },
28
+ { type: 'paragraph', html: '公共予算のラウンドでは、使える資金より価値のある提案が多くなりがちです。このツールは上限を入力し、完成単位の提案と比較可能な投票数または便益スコアを並べることで、選択のトレードオフを見えるようにします。' },
29
+ { type: 'title', text: '選択結果の計算方法', level: 2 },
30
+ { type: 'paragraph', html: '0/1ナップサックモデルとして、上限以内の組み合わせを比較し、合計スコアが最大のものを残します。同点では費用、提案数、入力順を使います。スコアは入力した目的であり、公共価値を独立に測る指標ではありません。' },
31
+ { type: 'table', headers: ['項目', '意味', '確認する問い'], rows: [['費用', '提案を実施するための全額', 'すべて同じ基準で見積もっていますか?'], ['スコア', '入力した投票数または便益の値', '提案同士で比較できますか?'], ['予算', '採択案の費用合計の上限', '各行と同じ費用を含んでいますか?'], ['対象外', '単独で高すぎるか、より良い組み合わせに負けた状態', '数学的な理由か、政策上の確認が必要ですか?']] },
32
+ { type: 'title', text: '誤解を招かない入力を準備する', level: 2 },
33
+ { type: 'list', items: ['同じ予算ラウンドの対象条件を確認する。', '全体費用か、実際に独立した段階の費用を使う。', '投票数や便益スコアの作り方を記録する。', '依存関係、維持費、法的確認、実施能力を別に確認する。', '採択案と対象外の理由を検討記録として保存する。'] },
34
+ { type: 'tip', title: 'スコアは選択した目的です', html: '投票数なら投票の合計を最大化し、便益評価ならその評価を最大化します。スコアを変えると問いも変わるので、方法を結果と一緒に保管してください。' },
35
+ { type: 'title', text: '採択案と対象外を読み分ける', level: 2 },
36
+ { type: 'paragraph', html: '採択案には費用、スコア、残り予算が表示されます。予算外の提案は単独でも上限を超えます。対象外の提案は単独なら入る場合がありますが、選んだ目的と同点処理では最良の組み合わせに含まれません。' },
37
+ { type: 'title', text: '限界と次の確認', level: 2 },
38
+ { type: 'paragraph', html: 'このツールは地域間の公平性、実施リスク、事業間の衝突、法的適格性を判断しません。正確な検索を保つため、モデルの予算は選択した通貨で20,000.00までです。' },
39
+ { type: 'paragraph', html: '高いスコアの組み合わせも、費用の前提と評価方法が明確でなければ信頼できません。' },
40
+ { type: 'title', text: '残り予算を話し合いの材料にする', level: 2 },
41
+ { type: 'paragraph', html: '残額は、追加の提案が現在の選択を改善しないことを示す場合があります。入力漏れの提案や、意図的な留保を示す場合もあります。' },
42
+ { type: 'tip', title: '決定前に確認する', html: '数学的な選択を公式の参加ルールと、影響を受ける人の声と一緒に読みます。' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: '사용 가능한 예산', budgetHelp: '통화를 하나로 통일하고 넘을 수 없는 한도를 입력하세요.', proposalsHeading: '비교 가능한 점수로 제안 추가', proposalNameLabel: '제안 이름', proposalCostLabel: '비용', proposalScoreLabel: '투표 또는 편익 점수', addProposal: '제안 추가', removeProposal: '삭제', calculateNote: '행을 편집하면 선택 결과가 갱신됩니다. 각 제안은 전액 지원되거나 제외됩니다.', loadExample: '예시 불러오기', printAction: '검토용 시트 인쇄', resultHeading: '예산 모자이크', emptyResult: '제안을 추가하면 예산에 들어가는 전체 조합을 확인할 수 있습니다.', excludedLabel: '지원 제외', spentLabel: '총비용', remainingLabel: '남은 예산', scoreLabel: '총점', proposalCountLabel: '개 제안', selectedStatus: '지원됨', tooExpensiveStatus: '초과', notSelectedStatus: '제외됨', invalidStatus: '수정 필요', reasonLabel: '이유', methodHeading: '적용한 방법', methodText: '이 도구는 0/1 배낭 모델을 풉니다. 각 제안에는 비용과 비교 가능한 점수가 있습니다. 가능한 조합 중 총점을 최대화하고, 동점이면 더 낮은 비용, 더 적은 제안 수, 더 이른 입력 순서를 사용합니다.', limitsHeading: '이 도구가 하지 않는 일', limitsText: '제안이 공정한지, 합법적인지, 지원 대상인지, 실행 가능한지 또는 사회적으로 더 바람직한지는 판단하지 않습니다. 참여예산 규칙이나 투표를 대신하지도 않습니다.', warningsHeading: '경계 사례와 데이터 경고', warningsText: '점수의 의미와 비용 기준을 통일하세요. 0점, 중복 이름, 불완전한 견적, 의존 관계, 나눌 수 있는 편익은 사람이 확인해야 합니다.', noProposalsWarning: '입력한 제안이 없습니다.', noFeasibleWarning: '사용 가능한 예산에 들어가는 제안이 없습니다.', invalidBudget: '0 이상인 예산을 입력하세요. 브라우저 모델은 선택한 통화로 20,000.00까지 지원합니다.', budgetTooLarge: '예산이 모델 한도 20,000.00을 초과합니다. 한도를 낮추거나 연습을 나누세요.', invalidProposal: '각 행에는 이름, 음수가 아닌 비용과 점수가 필요합니다.', costExceedsBudget: '이 비용은 사용 가능한 예산을 초과합니다. 제안을 선택할 수 없습니다.', tieBreakLabel: '결정 규칙', budgetUsedLabel: '사용', budgetLeftLabel: '잔액', selectedTilesLabel: '선택된 블록', allocationLabel: '예산 용량', statusSaved: '초안을 이 브라우저에 로컬 저장했습니다.',
8
+ };
9
+ const faq = [
10
+ { question: '이 배분 도구는 무엇을 최적화하나요?', answer: '한도를 넘지 않으면서 입력한 총점을 최대화하는 실행 가능한 전체 제안 조합을 선택합니다. 점수가 공정하거나 의미 있는지는 판단하지 않습니다.' },
11
+ { question: '제안은 왜 전부 선택되거나 전부 제외되나요?', answer: '첫 버전은 0/1 모델을 사용합니다. 제안은 전체 비용으로 실행되거나 제외되므로 완성되어야 가치가 생기는 사업에 맞습니다.' },
12
+ { question: '두 배분의 점수가 같으면 어떻게 되나요?', answer: '총비용이 낮은 조합, 제안 수가 적은 조합, 입력 순서가 빠른 조합을 차례로 선택합니다. 다른 검토자도 결과를 재현할 수 있습니다.' },
13
+ { question: '이 결과로 실제 예산을 결정할 수 있나요?', answer: '아니요. 투명한 시나리오일 뿐입니다. 자격, 의존 관계, 실행 역량, 통화 기준과 공식 절차를 확인하세요.' },
14
+ ];
15
+ const howTo = [
16
+ { name: '한도 설정', text: '이번 라운드에 사용할 금액을 입력하고 비용 기준을 통일하세요.' },
17
+ { name: '완전한 제안 추가', text: '각 제안을 한 번씩 입력하고 전체 비용과 비교 가능한 점수를 넣으세요.' },
18
+ { name: '모자이크 확인', text: '행을 수정하면서 지원 조합, 점수, 비용과 남은 예산을 살펴보세요.' },
19
+ { name: '제외 사유 읽기', text: '혼자서도 비싼 제안과 더 나은 실행 가능한 조합에 밀린 제안을 구분하세요.' },
20
+ { name: '사람의 검토 적용', text: '회의에서 사용하기 전에 규칙, 의존 관계, 실행 역량과 영향을 받는 사람을 확인하세요.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: '참여예산 배분 도구', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: '고정된 예산 한도 안에서 공공 제안을 전체 단위로 선택하고 투명한 최적화 규칙을 보여줍니다.', url: 'https://gamebob.dev/ko/participatory-budget-allocator', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: '고정된 참여예산 배분하기', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'participatory-budget-allocator', title: '참여예산 배분 도구', description: '고정된 예산 아래에서 전체 제안을 선택하고 선언한 점수를 최대화하며 각 제외의 비용과 이유를 확인하세요.', ui, seo: [
27
+ { type: 'title', text: '예산 한도를 재현 가능한 시나리오로 바꾸기', level: 2 },
28
+ { type: 'paragraph', html: '공공 예산 라운드에는 사용 가능한 돈보다 가치 있는 제안이 많은 경우가 많습니다. 이 도구는 한도를 입력하고 완전한 제안과 비교 가능한 투표 또는 편익 점수를 넣어 선택의 교환 관계를 보여줍니다.' },
29
+ { type: 'title', text: '선택 결과를 계산하는 방법', level: 2 },
30
+ { type: 'paragraph', html: '0/1 배낭 모델로 한도 이하의 조합을 비교하고 총점이 가장 높은 조합을 유지합니다. 동점이면 낮은 비용, 적은 제안 수, 빠른 입력 순서를 적용합니다. 점수는 입력한 목표이지 공공 가치를 독립적으로 측정하는 값이 아닙니다.' },
31
+ { type: 'table', headers: ['항목', '의미', '검토 질문'], rows: [['비용', '제안을 실행하는 데 필요한 전체 금액', '모든 행이 같은 기준인가요?'], ['점수', '사용자가 입력한 투표 또는 편익 값', '제안끼리 비교할 수 있나요?'], ['예산', '선택된 제안의 최대 총비용', '각 행과 같은 비용을 포함하나요?'], ['제외', '혼자서 비싸거나 더 나은 조합에 밀린 상태', '수학적 이유인가요, 정책 검토가 필요한가요?']] },
32
+ { type: 'title', text: '오해를 만들지 않는 입력 준비', level: 2 },
33
+ { type: 'list', items: ['모든 제안이 같은 라운드의 대상인지 확인하세요.', '전체 실행 비용이나 실제로 독립된 단계를 사용하세요.', '투표와 편익 점수가 만들어진 방식을 기록하세요.', '의존 관계, 유지비, 법적 검토와 실행 역량을 따로 확인하세요.', '선택 결과와 제외 사유를 검토 기록으로 저장하세요.'] },
34
+ { type: 'tip', title: '점수는 선택한 목표입니다', html: '점수가 투표라면 총투표를 최대화하고, 편익 평가라면 그 평가를 최대화합니다. 점수를 바꾸면 질문도 바뀌므로 방법을 결과와 함께 보관하세요.' },
35
+ { type: 'title', text: '지원 및 제외 조합 읽기', level: 2 },
36
+ { type: 'paragraph', html: '지원된 제안은 비용, 점수와 남은 예산을 보여줍니다. 예산에 들어가지 않는 제안은 혼자서도 한도를 초과합니다. 제외된 제안은 혼자라면 들어갈 수 있지만 선택한 목표와 동점 규칙에서는 최선의 조합이 아닙니다.' },
37
+ { type: 'title', text: '한계와 다음 확인', level: 2 },
38
+ { type: 'paragraph', html: '이 도구는 지역 간 공정성, 실행 위험, 사업 간 충돌 또는 법적 자격을 판단하지 않습니다. 정확한 검색을 위해 브라우저 모델의 한도는 선택한 통화로 20,000.00입니다.' },
39
+ { type: 'paragraph', html: '높은 점수의 조합도 비용 가정과 점수 산정 방식이 분명할 때만 신뢰할 수 있습니다.' },
40
+ { type: 'title', text: '남은 예산을 대화의 계기로 사용하기', level: 2 },
41
+ { type: 'paragraph', html: '남은 금액은 추가 제안이 현재 선택을 개선하지 못한다는 뜻일 수 있습니다. 누락된 적격 제안이나 의도적으로 남겨 둔 예산을 뜻할 수도 있습니다.' },
42
+ { type: 'tip', title: '결정 전에 확인하세요', html: '수학적 선택을 공식 참여 규칙과 영향을 받는 사람들의 의견과 함께 읽으세요.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: 'Beschikbaar budget', budgetHelp: 'Gebruik één valuta en vul de bovengrens in die niet mag worden overschreden.', proposalsHeading: 'Voorstellen met een vergelijkbare score toevoegen', proposalNameLabel: 'Naam van voorstel', proposalCostLabel: 'Kosten', proposalScoreLabel: 'Stemmen of baten score', addProposal: 'Voorstel toevoegen', removeProposal: 'Verwijderen', calculateNote: 'De selectie wordt bijgewerkt terwijl je de rijen bewerkt. Elk voorstel wordt volledig gefinancierd of weggelaten.', loadExample: 'Voorbeeld laden', printAction: 'Beoordelingsblad afdrukken', resultHeading: 'Budgetmozaïek', emptyResult: 'Voeg voorstellen toe om te zien welke volledige combinatie binnen het budget past.', excludedLabel: 'Niet gefinancierd', spentLabel: 'Totale kosten', remainingLabel: 'Resterend budget', scoreLabel: 'Totale score', proposalCountLabel: 'voorstellen', selectedStatus: 'Gefinancierd', tooExpensiveStatus: 'Past niet', notSelectedStatus: 'Weggelaten', invalidStatus: 'Corrigeren', reasonLabel: 'Waarom', methodHeading: 'Toegepaste methode', methodText: 'De tool lost een 0/1-rugzakmodel op. Elk voorstel heeft kosten en een vergelijkbare score. Toelaatbare combinaties worden gezocht, de score wordt gemaximaliseerd en daarna bepalen lagere kosten, minder voorstellen en eerdere invoer de gelijke stand.', limitsHeading: 'Wat deze tool niet doet', limitsText: 'De tool bepaalt niet of een voorstel eerlijk, legaal, subsidiabel, uitvoerbaar of maatschappelijk wenselijk is. Hij vervangt geen participatieregels of stemming.', warningsHeading: 'Randgevallen en datameldingen', warningsText: 'Houd scores vergelijkbaar en gebruik dezelfde kostenbasis. Nulwaarden, dubbele namen, onvolledige ramingen, afhankelijkheden en deelbare baten vragen menselijke controle.', noProposalsWarning: 'Er zijn geen voorstellen ingevoerd.', noFeasibleWarning: 'Geen enkel voorstel past binnen het beschikbare budget.', invalidBudget: 'Vul een niet-negatief budget in. Het browsermodel accepteert maximaal 20.000,00 in de gekozen valuta.', budgetTooLarge: 'Het budget overschrijdt de modelgrens van 20.000,00. Verlaag de bovengrens of splits de oefening.', invalidProposal: 'Elke rij heeft een naam, niet-negatieve kosten en een niet-negatieve score nodig.', costExceedsBudget: 'Deze kosten overschrijden het beschikbare budget. Het voorstel kan niet worden geselecteerd.', tieBreakLabel: 'Vaste regel', budgetUsedLabel: 'gebruikt', budgetLeftLabel: 'over', selectedTilesLabel: 'Geselecteerde blokken', allocationLabel: 'Budgetcapaciteit', statusSaved: 'Concept lokaal opgeslagen in deze browser.',
8
+ };
9
+ const faq = [
10
+ { question: 'Wat optimaliseert deze verdeler?', answer: 'Hij kiest een haalbare set volledige voorstellen die de ingevoerde totaalscore maximaliseert zonder de bovengrens te overschrijden. Hij beoordeelt niet of de score eerlijk of betekenisvol is.' },
11
+ { question: 'Waarom zijn voorstellen alles of niets?', answer: 'De eerste versie gebruikt een 0/1-model. Een voorstel wordt tegen de volledige kosten uitgevoerd of uitgesloten, passend bij projecten die pas als geheel waarde hebben.' },
12
+ { question: 'Wat gebeurt er bij dezelfde score?', answer: 'Eerst kiest de tool de laagste totale kosten, daarna minder voorstellen en vervolgens de vroegste invoer. Zo blijft de keuze reproduceerbaar.' },
13
+ { question: 'Kan dit resultaat een echt budget bepalen?', answer: 'Nee. Het is een transparant scenario. Controleer subsidiabiliteit, afhankelijkheden, uitvoeringscapaciteit, kostenbasis en de officiële procedure.' },
14
+ ];
15
+ const howTo = [
16
+ { name: 'Bovengrens instellen', text: 'Voer het beschikbare bedrag voor deze ronde in en houd de kostenbasis gelijk.' },
17
+ { name: 'Volledige voorstellen toevoegen', text: 'Voer elk voorstel één keer in met volledige kosten en een vergelijkbare stem- of batenscore.' },
18
+ { name: 'Mozaïek bekijken', text: 'Bekijk gefinancierde voorstellen, score, kosten en resterend budget terwijl de rijen veranderen.' },
19
+ { name: 'Uitsluitingen lezen', text: 'Onderscheid voorstellen die alleen te duur zijn van voorstellen die verloren van een betere haalbare combinatie.' },
20
+ { name: 'Menselijke controles uitvoeren', text: 'Vergelijk het scenario met regels, afhankelijkheden, capaciteit en betrokken inwoners voor je het gebruikt.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: 'Verdeler voor participatieve budgetten', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: 'Selecteer volledige publieke voorstellen onder een vaste budgetgrens met een transparante optimalisatieregel.', url: 'https://gamebob.dev/nl/participatieve-budgetverdeler', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: 'Een vast participatief budget verdelen', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'participatieve-budgetverdeler', title: 'Verdeler voor participatieve budgetten', description: 'Selecteer volledige voorstellen onder een vaste budgetgrens, maximaliseer een verklaarde score en zie de kosten en reden achter elke uitsluiting.', ui, seo: [
27
+ { type: 'title', text: 'Een budgetgrens omzetten in een reproduceerbaar scenario', level: 2 },
28
+ { type: 'paragraph', html: 'In een openbare budgetronde zijn er vaak meer waardevolle voorstellen dan geld. Deze verdeler maakt de afweging zichtbaar: voer de grens in, voeg volledige voorstellen toe en geef elk voorstel een vergelijkbare stem- of batenscore. Het resultaat toont een haalbare set zonder de keuze te verbergen achter één advies.' },
29
+ { type: 'title', text: 'Zo wordt de selectie berekend', level: 2 },
30
+ { type: 'paragraph', html: 'Het model is een 0/1-rugzakprobleem. De browser vergelijkt combinaties onder de grens en bewaart de combinatie met de hoogste totaalscore. Bij gelijkstand gelden lagere kosten, minder voorstellen en eerdere invoer. De score is het gekozen doel, geen onafhankelijke maat voor publieke waarde.' },
31
+ { type: 'table', headers: ['Veld', 'Betekenis', 'Controle vraag'], rows: [['Kosten', 'Volledig bedrag voor uitvoering', 'Zijn alle rijen op dezelfde basis geraamd?'], ['Score', 'Ingevoerde stemmen of batenwaarde', 'Zijn deze waarden vergelijkbaar?'], ['Budget', 'Maximale totale kosten van de selectie', 'Bevat de grens dezelfde kosten als elke rij?'], ['Uitsluiting', 'Alleen te duur of verslagen door een betere set', 'Is de reden wiskundig of beleidsmatig?']] },
32
+ { type: 'title', text: 'Misleidende invoer voorkomen', level: 2 },
33
+ { type: 'list', items: ['Bevestig dat elk voorstel voor dezelfde ronde in aanmerking komt.', 'Gebruik volledige uitvoeringskosten of echte onafhankelijke fasen.', 'Leg vast hoe stemmen of baten scores zijn gemaakt.', 'Controleer afhankelijkheden, onderhoud, recht en capaciteit apart.', 'Bewaar selectie en redenen als beoordelingsverslag.'] },
34
+ { type: 'tip', title: 'Een score is een gekozen doel', html: 'Bij stemmen maximaliseert het resultaat de totale stemmen. Bij een batenbeoordeling maximaliseert het die beoordeling. Een andere score stelt een andere vraag, dus bewaar de methode bij het resultaat.' },
35
+ { type: 'title', text: 'Gefinancierde en uitgesloten sets lezen', level: 2 },
36
+ { type: 'paragraph', html: 'Gefinancierde voorstellen tonen kosten, score en resterend budget. Een voorstel dat niet past is op zichzelf al duurder dan de grens. Een weggelaten voorstel kan alleen wel passen, maar zit onder het gekozen doel en de regel niet in de beste combinatie.' },
37
+ { type: 'title', text: 'Grenzen en volgende controles', level: 2 },
38
+ { type: 'paragraph', html: 'De verdeler beoordeelt geen rechtvaardigheid tussen wijken, uitvoeringsrisico, projectconflicten of wettelijke geschiktheid. Het browsermodel is beperkt tot 20.000,00 om exact zoeken responsief te houden.' },
39
+ { type: 'paragraph', html: 'Een combinatie met een hoge score is alleen betrouwbaar als de kostenbasis en de manier van scoren duidelijk zijn.' },
40
+ { type: 'title', text: 'Het resterende budget als gesprek gebruiken', level: 2 },
41
+ { type: 'paragraph', html: 'Een restbedrag kan betekenen dat geen extra voorstel de huidige selectie verbetert. Het kan ook wijzen op een ontbrekend geschikt voorstel of een bewust gereserveerd bedrag.' },
42
+ { type: 'tip', title: 'Controleren voor je beslist', html: 'Lees de wiskundige selectie samen met de officiële participatieregels en de stemmen van betrokken inwoners.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: 'Dostępny budżet', budgetHelp: 'Użyj jednej waluty i wpisz limit, którego nie wolno przekroczyć.', proposalsHeading: 'Dodaj propozycje z porównywalną punktacją', proposalNameLabel: 'Nazwa propozycji', proposalCostLabel: 'Koszt', proposalScoreLabel: 'Głosy lub ocena korzyści', addProposal: 'Dodaj propozycję', removeProposal: 'Usuń', calculateNote: 'Wybór aktualizuje się podczas edycji wierszy. Każda propozycja jest finansowana w całości albo odrzucona.', loadExample: 'Wczytaj przykład', printAction: 'Drukuj kartę przeglądu', resultHeading: 'Mozaika budżetu', emptyResult: 'Dodaj propozycje, aby zobaczyć pełny zestaw mieszczący się w budżecie.', excludedLabel: 'Niefinansowana', spentLabel: 'Łączny koszt', remainingLabel: 'Pozostały budżet', scoreLabel: 'Łączna punktacja', proposalCountLabel: 'propozycji', selectedStatus: 'Finansowana', tooExpensiveStatus: 'Nie mieści się', notSelectedStatus: 'Odrzucona', invalidStatus: 'Do poprawy', reasonLabel: 'Dlaczego', methodHeading: 'Zastosowana metoda', methodText: 'Narzędzie rozwiązuje model plecakowy 0/1. Każda propozycja ma koszt i porównywalną punktację. Wyszukuje wykonalne kombinacje, maksymalizuje wynik, a następnie stosuje niższy koszt, mniej propozycji i wcześniejszą kolejność wpisania jako jednoznaczne reguły rozstrzygania.', limitsHeading: 'Czego to narzędzie nie robi', limitsText: 'Nie rozstrzyga, czy propozycja jest sprawiedliwa, legalna, kwalifikowalna, wykonalna lub społecznie lepsza. Nie zastępuje zasad budżetu obywatelskiego ani głosowania.', warningsHeading: 'Przypadki graniczne i ostrzeżenia', warningsText: 'Zachowaj porównywalność ocen i tę samą podstawę kosztów. Zera, powtarzające się nazwy, niepełne wyceny, zależności i podzielne korzyści wymagają ludzkiej kontroli.', noProposalsWarning: 'Nie wpisano żadnych propozycji.', noFeasibleWarning: 'Żadna propozycja nie mieści się w dostępnym budżecie.', invalidBudget: 'Wpisz budżet nieujemny. Model przeglądarkowy obsługuje do 20 000,00 w wybranej walucie.', budgetTooLarge: 'Budżet przekracza limit modelu 20 000,00. Zmniejsz limit albo podziel ćwiczenie.', invalidProposal: 'Każdy wiersz wymaga nazwy, nieujemnego kosztu i nieujemnej oceny.', costExceedsBudget: 'Ten koszt przekracza dostępny budżet. Propozycja nie może zostać wybrana.', tieBreakLabel: 'Reguła rozstrzygania', budgetUsedLabel: 'wykorzystano', budgetLeftLabel: 'pozostało', selectedTilesLabel: 'Wybrane bloki', allocationLabel: 'Pojemność budżetu', statusSaved: 'Wersja robocza zapisana lokalnie w tej przeglądarce.',
8
+ };
9
+ const faq = [
10
+ { question: 'Co optymalizuje ten alokator?', answer: 'Wybiera wykonalny zestaw kompletnych propozycji, który maksymalizuje wpisaną łączną punktację bez przekraczania limitu. Nie ocenia, czy punktacja jest sprawiedliwa lub znacząca.' },
11
+ { question: 'Dlaczego propozycje są wybierane w całości albo wcale?', answer: 'Pierwsza wersja używa modelu 0/1. Propozycja jest realizowana za pełny koszt albo wykluczana, co pasuje do projektów, których wartość zależy od ukończenia.' },
12
+ { question: 'Co dzieje się przy takiej samej punktacji?', answer: 'Najpierw wybierany jest niższy koszt całkowity, potem mniejsza liczba propozycji, a na końcu wcześniejsza kolejność wpisania. Wynik można odtworzyć.' },
13
+ { question: 'Czy wynik może rozstrzygnąć prawdziwy budżet?', answer: 'Nie. To przejrzysty scenariusz. Sprawdź kwalifikowalność, zależności, możliwości realizacji, podstawę waluty i oficjalną procedurę.' },
14
+ ];
15
+ const howTo = [
16
+ { name: 'Ustal limit', text: 'Wpisz kwotę dostępną w tej rundzie i zachowaj spójną podstawę waluty.' },
17
+ { name: 'Dodaj kompletne propozycje', text: 'Wpisz każdą propozycję raz, z pełnym kosztem i porównywalną liczbą głosów lub oceną korzyści.' },
18
+ { name: 'Sprawdź mozaikę', text: 'Podczas edycji obserwuj finansowany zestaw, punktację, koszt i pozostały budżet.' },
19
+ { name: 'Przeczytaj wykluczenia', text: 'Odróżnij propozycje zbyt drogie samodzielnie od tych, które przegrały z lepszą wykonalną kombinacją.' },
20
+ { name: 'Wykonaj kontrolę człowieka', text: 'Przed spotkaniem porównaj scenariusz z zasadami, zależnościami, możliwościami i potrzebami mieszkańców.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: 'Alokator budżetu obywatelskiego', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: 'Wybieraj kompletne propozycje publiczne w ramach stałego limitu budżetu według przejrzystej reguły optymalizacji.', url: 'https://gamebob.dev/pl/alokator-budzetu-partycypacyjnego', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: 'Podzielić stały budżet obywatelski', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'alokator-budzetu-partycypacyjnego', title: 'Alokator budżetu obywatelskiego', description: 'Wybierz kompletne propozycje w ramach stałego budżetu, zmaksymalizuj określoną punktację i poznaj koszt oraz powód każdego wykluczenia.', ui, seo: [
27
+ { type: 'title', text: 'Zamień limit budżetu w powtarzalny scenariusz', level: 2 },
28
+ { type: 'paragraph', html: 'W rundzie budżetu publicznego często jest więcej wartościowych propozycji niż dostępnych pieniędzy. Alokator pokazuje kompromis: wpisz limit, dodaj kompletne propozycje i nadaj im porównywalną liczbę głosów lub ocenę korzyści. Wynik pokazuje wykonalny zestaw zamiast ukrywać wybór za jedną rekomendacją.' },
29
+ { type: 'title', text: 'Jak obliczany jest wybór', level: 2 },
30
+ { type: 'paragraph', html: 'Model jest problemem plecakowym 0/1. Przeglądarka porównuje kombinacje mieszczące się w limicie i zachowuje tę z najwyższą sumą punktów. Przy remisie stosuje niższy koszt, mniej propozycji i wcześniejsze wpisanie. Punktacja jest określonym przez użytkownika celem, a nie niezależną miarą wartości publicznej.' },
31
+ { type: 'table', headers: ['Pole', 'Znaczenie', 'Pytanie kontrolne'], rows: [['Koszt', 'Pełna kwota potrzebna do realizacji', 'Czy wszystkie wiersze mają tę samą podstawę?'], ['Punktacja', 'Wpisane głosy lub wartość korzyści', 'Czy wartości można porównać?'], ['Budżet', 'Maksymalny koszt wybranych propozycji', 'Czy limit obejmuje te same koszty?'], ['Wykluczenie', 'Za drogie samodzielnie albo pokonane przez lepszy zestaw', 'Czy powód jest matematyczny czy wymaga decyzji?']] },
32
+ { type: 'title', text: 'Przygotuj dane bez mylących założeń', level: 2 },
33
+ { type: 'list', items: ['Potwierdź kwalifikowalność wszystkich propozycji w tej samej rundzie.', 'Używaj pełnego kosztu albo rzeczywiście niezależnych etapów.', 'Zapisz, jak powstały głosy i oceny korzyści.', 'Osobno sprawdź zależności, utrzymanie, prawo i możliwości realizacji.', 'Zachowaj wybór i powody wykluczeń jako protokół przeglądu.'] },
34
+ { type: 'tip', title: 'Punktacja jest wybranym celem', html: 'Jeśli oznacza głosy, wynik maksymalizuje ich sumę. Jeśli oznacza korzyść, maksymalizuje tę ocenę. Zmiana punktacji zmienia pytanie, dlatego zachowaj metodę razem z wynikiem.' },
35
+ { type: 'title', text: 'Czytaj zestawy finansowane i wykluczone', level: 2 },
36
+ { type: 'paragraph', html: 'Finansowane propozycje pokazują koszt, punktację i pozostały budżet. Propozycja, która się nie mieści, przekracza limit już samodzielnie. Odrzucona propozycja może mieścić się sama, ale według wybranego celu i reguły remisu nie należy do najlepszego zestawu.' },
37
+ { type: 'title', text: 'Ograniczenia i następne kontrole', level: 2 },
38
+ { type: 'paragraph', html: 'Alokator nie ocenia sprawiedliwości między dzielnicami, ryzyka realizacji, konfliktów projektów ani zgodności z prawem. Model przeglądarkowy ma limit 20 000,00, aby dokładne wyszukiwanie pozostało szybkie.' },
39
+ { type: 'paragraph', html: 'Kombinacja z wysoką punktacją jest wiarygodna tylko wtedy, gdy jasne są także koszty i sposób oceniania.' },
40
+ { type: 'title', text: 'Wykorzystaj pozostały budżet do rozmowy', level: 2 },
41
+ { type: 'paragraph', html: 'Pozostała kwota może oznaczać, że żadna dodatkowa propozycja nie poprawia obecnego wyboru. Może też wskazywać brakującą propozycję albo celową rezerwę.' },
42
+ { type: 'tip', title: 'Sprawdź przed decyzją', html: 'Czytaj wybór matematyczny razem z oficjalnymi zasadami uczestnictwa i głosami osób, których dotyczy.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: 'Orçamento disponível', budgetHelp: 'Use uma única moeda e informe o limite que não pode ser ultrapassado.', proposalsHeading: 'Adicione propostas com uma pontuação comparável', proposalNameLabel: 'Nome da proposta', proposalCostLabel: 'Custo', proposalScoreLabel: 'Votos ou pontuação de benefício', addProposal: 'Adicionar proposta', removeProposal: 'Remover', calculateNote: 'A seleção é atualizada enquanto você edita as linhas. Cada proposta é financiada por inteiro ou fica de fora.', loadExample: 'Carregar exemplo', printAction: 'Imprimir ficha de revisão', resultHeading: 'Mosaico do orçamento', emptyResult: 'Adicione propostas para ver qual conjunto completo cabe no orçamento.', excludedLabel: 'Não financiada', spentLabel: 'Custo total', remainingLabel: 'Orçamento restante', scoreLabel: 'Pontuação total', proposalCountLabel: 'propostas', selectedStatus: 'Financiada', tooExpensiveStatus: 'Não cabe', notSelectedStatus: 'Ficou de fora', invalidStatus: 'Corrigir', reasonLabel: 'Por quê', methodHeading: 'Método aplicado', methodText: 'A ferramenta resolve um modelo de mochila 0/1. Cada proposta tem um custo e uma pontuação comparável. Ela busca combinações viáveis, maximiza a pontuação e depois usa menor custo, menos propostas e ordem de entrada como desempates determinísticos.', limitsHeading: 'O que esta ferramenta não faz', limitsText: 'Ela não decide se uma proposta é justa, legal, elegível, executável ou socialmente preferível. Também não substitui as regras do orçamento participativo nem uma votação.', warningsHeading: 'Casos extremos e alertas de dados', warningsText: 'Mantenha as pontuações comparáveis e use a mesma base de custos. Valores zero, nomes duplicados, estimativas incompletas, dependências e benefícios divisíveis exigem revisão humana.', noProposalsWarning: 'Nenhuma proposta foi informada.', noFeasibleWarning: 'Nenhuma proposta cabe no orçamento disponível.', invalidBudget: 'Informe um orçamento não negativo. O modelo do navegador aceita até 20.000,00 na moeda escolhida.', budgetTooLarge: 'O orçamento ultrapassa o limite do modelo de 20.000,00. Reduza o teto ou divida o exercício.', invalidProposal: 'Cada linha precisa de um nome, custo não negativo e pontuação não negativa.', costExceedsBudget: 'Este custo ultrapassa o orçamento disponível. A proposta não pode ser selecionada.', tieBreakLabel: 'Regra determinística', budgetUsedLabel: 'usado', budgetLeftLabel: 'restante', selectedTilesLabel: 'Blocos selecionados', allocationLabel: 'Capacidade orçamentária', statusSaved: 'Rascunho salvo localmente neste navegador.',
8
+ };
9
+ const faq = [
10
+ { question: 'O que este alocador otimiza?', answer: 'Ele escolhe um conjunto viável de propostas completas que maximiza a pontuação total informada sem ultrapassar o teto. Não decide se essa pontuação é justa ou significativa.' },
11
+ { question: 'Por que as propostas são tudo ou nada?', answer: 'A primeira versão usa um modelo 0/1. Cada proposta é financiada pelo custo completo ou excluída, o que se adapta a projetos cujo valor depende da entrega integral.' },
12
+ { question: 'O que acontece quando duas alocações têm a mesma pontuação?', answer: 'A ferramenta escolhe primeiro o menor custo total, depois menos propostas e, por fim, a ordem de entrada mais antiga. O desempate pode ser reproduzido.' },
13
+ { question: 'O resultado pode decidir um orçamento real?', answer: 'Não. É um cenário transparente. Verifique elegibilidade, dependências, capacidade de execução, base monetária e processo oficial.' },
14
+ ];
15
+ const howTo = [
16
+ { name: 'Defina o teto', text: 'Informe o valor disponível nesta rodada e mantenha a base monetária consistente.' },
17
+ { name: 'Adicione propostas completas', text: 'Inclua cada proposta uma vez com custo integral e votos ou pontuação de benefício comparáveis.' },
18
+ { name: 'Examine o mosaico', text: 'Revise conjunto financiado, pontuação, custo e orçamento restante conforme as linhas mudam.' },
19
+ { name: 'Leia as exclusões', text: 'Diferencie propostas que não cabem sozinhas das que perderam para uma combinação viável melhor.' },
20
+ { name: 'Faça verificações humanas', text: 'Compare o cenário com regras, dependências, capacidade e pessoas afetadas antes de uma reunião.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: 'Alocador de orçamento participativo', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: 'Selecione propostas públicas inteiras sob um limite orçamental fixo com uma regra de otimização transparente.', url: 'https://gamebob.dev/pt/alocador-orcamento-participativo', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: 'Distribuir um orçamento participativo fixo', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'alocador-orcamento-participativo', title: 'Alocador de orçamento participativo', description: 'Selecione propostas completas dentro de um orçamento fixo, maximize uma pontuação declarada e entenda o custo e o motivo de cada exclusão.', ui, seo: [
27
+ { type: 'title', text: 'Transforme um teto orçamental em um cenário reproduzível', level: 2 },
28
+ { type: 'paragraph', html: 'Uma rodada de orçamento público costuma ter mais propostas valiosas do que dinheiro disponível. Este alocador explicita a troca: informe o teto, adicione propostas completas e atribua a cada uma votos ou uma pontuação de benefício comparável. O resultado mostra um conjunto viável, sem esconder a escolha atrás de uma recomendação única.' },
29
+ { type: 'title', text: 'Como a seleção é calculada', level: 2 },
30
+ { type: 'paragraph', html: 'O modelo é uma mochila 0/1. O navegador compara combinações que ficam abaixo do teto e mantém a de maior pontuação total. Em caso de empate, aplica menor custo, menos propostas e ordem de entrada. A pontuação é o objetivo declarado, não uma medida independente de valor público.' },
31
+ { type: 'table', headers: ['Campo', 'Significado', 'Pergunta de revisão'], rows: [['Custo', 'Valor integral para entregar a proposta', 'Todas as linhas usam a mesma base?'], ['Pontuação', 'Votos ou valor de benefício informado', 'Os valores são comparáveis?'], ['Orçamento', 'Custo total máximo da seleção', 'O teto inclui os mesmos custos?'], ['Exclusão', 'Caro demais sozinho ou vencido por um conjunto melhor', 'A razão é matemática ou precisa de decisão?']] },
32
+ { type: 'title', text: 'Prepare entradas que não enganem', level: 2 },
33
+ { type: 'list', items: ['Confirme a elegibilidade de todas as propostas na mesma rodada.', 'Use o custo integral ou etapas realmente independentes.', 'Registre como votos e pontuações foram produzidos.', 'Verifique dependências, manutenção, questões legais e capacidade separadamente.', 'Guarde a seleção e os motivos de exclusão como registro de revisão.'] },
34
+ { type: 'tip', title: 'Uma pontuação é um objetivo escolhido', html: 'Se representa votos, o resultado maximiza os votos totais. Se representa benefício, maximiza essa avaliação. Mudar a pontuação muda a pergunta, então conserve o método junto do resultado.' },
35
+ { type: 'title', text: 'Leia os conjuntos financiado e excluído', level: 2 },
36
+ { type: 'paragraph', html: 'As propostas financiadas mostram custo, pontuação e orçamento restante. Uma proposta que não cabe custa mais que o teto sozinha. Uma proposta excluída pode caber sozinha, mas não está na melhor combinação segundo o objetivo e o desempate escolhidos.' },
37
+ { type: 'title', text: 'Limites e próximas verificações', level: 2 },
38
+ { type: 'paragraph', html: 'O alocador não avalia justiça entre bairros, risco de execução, conflitos entre projetos ou elegibilidade legal. O modelo do navegador é limitado a 20.000,00 para manter a busca exata rápida.' },
39
+ { type: 'paragraph', html: 'Uma combinação com pontuação alta só é confiável quando a base dos custos e o método de pontuação também são claros.' },
40
+ { type: 'title', text: 'Use o orçamento restante para conversar', level: 2 },
41
+ { type: 'paragraph', html: 'Um saldo pode indicar que nenhuma proposta adicional melhora a seleção atual. Também pode apontar uma proposta elegível ausente ou uma reserva intencional.' },
42
+ { type: 'tip', title: 'Revise antes de decidir', html: 'Leia a seleção matemática junto das regras oficiais de participação e das vozes das pessoas afetadas.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };
@@ -0,0 +1,43 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import { bibliography } from '../bibliography';
3
+ import type { ParticipatoryBudgetLocaleContent } from '../entry';
4
+ import type { ParticipatoryBudgetUI } from '../ui';
5
+
6
+ const ui: ParticipatoryBudgetUI = {
7
+ budgetLabel: 'Доступный бюджет', budgetHelp: 'Используйте одну валюту и укажите предел, который нельзя превышать.', proposalsHeading: 'Добавьте предложения с сопоставимой оценкой', proposalNameLabel: 'Название предложения', proposalCostLabel: 'Стоимость', proposalScoreLabel: 'Голоса или оценка пользы', addProposal: 'Добавить предложение', removeProposal: 'Удалить', calculateNote: 'Выбор обновляется при изменении строк. Каждое предложение либо финансируется полностью, либо исключается.', loadExample: 'Загрузить пример', printAction: 'Печать листа проверки', resultHeading: 'Мозаика бюджета', emptyResult: 'Добавьте предложения, чтобы увидеть полный набор, который помещается в бюджет.', excludedLabel: 'Не финансируется', spentLabel: 'Общая стоимость', remainingLabel: 'Остаток бюджета', scoreLabel: 'Общая оценка', proposalCountLabel: 'предложений', selectedStatus: 'Профинансировано', tooExpensiveStatus: 'Не помещается', notSelectedStatus: 'Исключено', invalidStatus: 'Нужно исправить', reasonLabel: 'Почему', methodHeading: 'Применённый метод', methodText: 'Инструмент решает задачу о рюкзаке 0/1. У каждого предложения есть стоимость и сопоставимая оценка. Сначала ищется допустимая комбинация с максимальной оценкой, затем применяются меньшая стоимость, меньшее число предложений и более ранний порядок ввода.', limitsHeading: 'Чего этот инструмент не делает', limitsText: 'Он не определяет, справедливо ли предложение, законно ли оно, допустимо ли, выполнимо ли или предпочтительнее для общества. Он не заменяет правила участия и голосование.', warningsHeading: 'Особые случаи и предупреждения', warningsText: 'Сохраняйте сопоставимость оценок и единую основу стоимости. Нулевые значения, повторяющиеся названия, неполные сметы, зависимости и делимые выгоды требуют проверки человеком.', noProposalsWarning: 'Предложения не введены.', noFeasibleWarning: 'Ни одно предложение не помещается в доступный бюджет.', invalidBudget: 'Введите неотрицательный бюджет. Модель браузера принимает до 20 000,00 в выбранной валюте.', budgetTooLarge: 'Бюджет превышает предел модели 20 000,00. Уменьшите предел или разделите упражнение.', invalidProposal: 'В каждой строке нужны название, неотрицательная стоимость и неотрицательная оценка.', costExceedsBudget: 'Эта стоимость превышает доступный бюджет. Предложение нельзя выбрать.', tieBreakLabel: 'Детерминированное правило', budgetUsedLabel: 'использовано', budgetLeftLabel: 'осталось', selectedTilesLabel: 'Выбранные блоки', allocationLabel: 'Ёмкость бюджета', statusSaved: 'Черновик сохранён локально в этом браузере.',
8
+ };
9
+ const faq = [
10
+ { question: 'Что оптимизирует этот распределитель?', answer: 'Он выбирает допустимый набор целых предложений, который максимизирует введённую сумму оценок и не превышает предел. Он не решает, справедлива ли сама оценка.' },
11
+ { question: 'Почему предложения выбираются целиком или не выбираются?', answer: 'Первая версия использует модель 0/1. Предложение финансируется по полной стоимости или исключается, что подходит проектам, полезным только после полного выполнения.' },
12
+ { question: 'Что происходит при одинаковой оценке?', answer: 'Сначала выбирается меньшая общая стоимость, затем меньшее число предложений, затем более ранний порядок ввода. Поэтому результат можно воспроизвести.' },
13
+ { question: 'Может ли результат решить настоящий бюджет?', answer: 'Нет. Это прозрачный сценарий. Проверьте допустимость, зависимости, возможности реализации, валютную основу и официальную процедуру.' },
14
+ ];
15
+ const howTo = [
16
+ { name: 'Задайте предел', text: 'Введите доступную сумму для этого раунда и используйте единую основу стоимости.' },
17
+ { name: 'Добавьте полные предложения', text: 'Введите каждое предложение один раз с полной стоимостью и сопоставимой оценкой голосов или пользы.' },
18
+ { name: 'Проверьте мозаику', text: 'Следите за профинансированным набором, оценкой, стоимостью и остатком при изменении строк.' },
19
+ { name: 'Прочитайте исключения', text: 'Отделите предложения, слишком дорогие сами по себе, от проигравших лучшей допустимой комбинации.' },
20
+ { name: 'Проведите проверку человеком', text: 'До обсуждения сравните сценарий с правилами, зависимостями, возможностями и интересами жителей.' },
21
+ ];
22
+ const softwareApplication: SoftwareApplication = { '@type': 'SoftwareApplication', name: 'Распределитель бюджета участия', applicationCategory: 'EducationalApplication', operatingSystem: 'Any', description: 'Выбирайте целые общественные предложения в рамках фиксированного бюджета по прозрачному правилу оптимизации.', url: 'https://gamebob.dev/ru/raspredelitel-participativnogo-byudzheta', offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' } };
23
+ const faqSchema: FAQPage = { '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: HowTo = { '@type': 'HowTo', name: 'Распределить фиксированный бюджет участия', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ParticipatoryBudgetLocaleContent = { slug: 'raspredelitel-participativnogo-byudzheta', title: 'Распределитель бюджета участия', description: 'Выберите целые предложения в рамках фиксированного бюджета, максимизируйте заявленную оценку и поймите стоимость и причину каждого исключения.', ui, seo: [
27
+ { type: 'title', text: 'Превратите предел бюджета в воспроизводимый сценарий', level: 2 },
28
+ { type: 'paragraph', html: 'В раунде общественного бюджета часто бывает больше полезных предложений, чем доступных денег. Инструмент делает компромисс явным: укажите предел, добавьте полные предложения и задайте сопоставимые голоса или оценки пользы. Результат показывает допустимый набор, а не скрытую рекомендацию.' },
29
+ { type: 'title', text: 'Как рассчитывается выбор', level: 2 },
30
+ { type: 'paragraph', html: 'Модель является задачей о рюкзаке 0/1. Браузер сравнивает комбинации в пределах бюджета и сохраняет комбинацию с наибольшей суммой оценок. При равенстве используются меньшая стоимость, меньшее число предложений и порядок ввода. Оценка является выбранной целью, а не независимой мерой общественной ценности.' },
31
+ { type: 'table', headers: ['Поле', 'Значение', 'Вопрос для проверки'], rows: [['Стоимость', 'Полная сумма для выполнения предложения', 'Все строки используют одну основу?'], ['Оценка', 'Введённые голоса или польза', 'Значения сопоставимы?'], ['Бюджет', 'Максимальная общая стоимость выбора', 'Предел включает те же расходы?'], ['Исключение', 'Слишком дорого само по себе или проиграло лучшему набору', 'Причина математическая или требует решения?']] },
32
+ { type: 'title', text: 'Подготовьте данные без вводящих в заблуждение допущений', level: 2 },
33
+ { type: 'list', items: ['Проверьте допустимость всех предложений для одного раунда.', 'Используйте полную стоимость или действительно независимые этапы.', 'Запишите происхождение голосов и оценок пользы.', 'Отдельно проверьте зависимости, обслуживание, право и возможности выполнения.', 'Сохраните выбор и причины исключений как протокол проверки.'] },
34
+ { type: 'tip', title: 'Оценка является выбранной целью', html: 'Если это голоса, результат максимизирует их сумму. Если это польза, он максимизирует эту оценку. Изменение оценки меняет вопрос, поэтому храните метод вместе с результатом.' },
35
+ { type: 'title', text: 'Читайте профинансированные и исключённые наборы', level: 2 },
36
+ { type: 'paragraph', html: 'Профинансированные предложения показывают стоимость, оценку и остаток. Предложение, которое не помещается, превышает предел само по себе. Исключённое предложение может помещаться отдельно, но не входит в лучшую комбинацию при выбранной цели и правилах равенства.' },
37
+ { type: 'title', text: 'Ограничения и следующие проверки', level: 2 },
38
+ { type: 'paragraph', html: 'Распределитель не оценивает справедливость между районами, риск выполнения, конфликты проектов или юридическую допустимость. Для быстрой точной проверки модель ограничена бюджетом 20 000,00 в выбранной валюте.' },
39
+ { type: 'paragraph', html: 'Комбинация с высокой оценкой надёжна только тогда, когда ясны основа стоимости и способ выставления оценок.' },
40
+ { type: 'title', text: 'Используйте остаток бюджета для обсуждения', level: 2 },
41
+ { type: 'paragraph', html: 'Остаток может означать, что дополнительное предложение не улучшает текущий выбор. Он также может указывать на пропущенное допустимое предложение или намеренный резерв.' },
42
+ { type: 'tip', title: 'Проверьте перед решением', html: 'Читайте математический выбор вместе с официальными правилами участия и голосами затронутых жителей.' },
43
+ ], faq, bibliography, howTo, schemas: [softwareApplication, faqSchema, howToSchema] as unknown as Record<string, unknown>[] };