From fe5abb47ba0602d87a8532df844141e7704f3687 Mon Sep 17 00:00:00 2001 From: Lucas 'Paperboy' Rose-Winters Date: Thu, 6 Nov 2025 22:48:38 +1100 Subject: [PATCH] fix: make skills parser handle text-based proficiency levels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parser was only matching numeric levels "(Lv 5)" but AI was returning text proficiencies like "(Proficient)", "(Advanced)", causing all skills to be ignored and not categorized. Changes to parser.js: - Add fallback regex to match text proficiency format: "- Skill (Proficient)" - Map text proficiencies to numeric levels: - Initiated/Novice → Lv 1 - Basic/Beginner → Lv 2 - Intermediate → Lv 4 - Proficient → Lv 5 - Competent → Lv 6 - Advanced → Lv 7 - Expert → Lv 8 - Mastered/Master → Lv 9 - Grandmaster/Legendary → Lv 10 - Default to Lv 5 for unrecognized proficiency text - Try numeric format first, fall back to text format Changes to promptBuilder.js: - Make prompt instructions more explicit about numeric format - Add negative examples: "write 'Lv 5' not 'Proficient'" - Add guidance: "1=novice, 5=intermediate, 10=expert" - Emphasize with "IMPORTANT:" prefix Benefits: - Parser now handles both formats (backward compatible) - AI has clearer instructions to use numeric levels - Skills with text proficiencies now parse correctly and show in categories - Existing numeric format continues to work Issue Resolution: - Skills like "Demonic Qi Manipulation (Proficient)" now parse as Lv 5 - Categories like "Demonic Arts:", "Combat:", "Social:" now populate correctly - Widget displays skills organized by category instead of ignoring them Related: Skills widget, AI tracker integration --- src/systems/generation/parser.js | 42 ++++++++++++++++++++++++- src/systems/generation/promptBuilder.js | 2 +- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/systems/generation/parser.js b/src/systems/generation/parser.js index 7fec28a..f61ab4d 100644 --- a/src/systems/generation/parser.js +++ b/src/systems/generation/parser.js @@ -187,7 +187,8 @@ function extractSkills(statsText) { } // Check if this is a skill line (starts with -, has level info) - const skillMatch = line.match(/^-\s*(.+?)\s*\(Lv\s*(\d+)\)/i); + // Try numeric format first: "- Skill Name (Lv 5)" + let skillMatch = line.match(/^-\s*(.+?)\s*\(Lv\s*(\d+)\)/i); if (skillMatch) { const skillName = skillMatch[1].trim(); const level = parseInt(skillMatch[2], 10) || 1; @@ -204,6 +205,45 @@ function extractSkills(statsText) { } else if (currentCategory && skillsData.categories[currentCategory]) { skillsData.categories[currentCategory].push(skill); } + } else { + // Fallback: Try text-based proficiency format: "- Skill Name (Proficient)" + const textMatch = line.match(/^-\s*(.+?)\s*\((.+?)\)/i); + if (textMatch) { + const skillName = textMatch[1].trim(); + const proficiencyText = textMatch[2].trim().toLowerCase(); + + // Map text proficiency to numeric level + const proficiencyMap = { + 'initiated': 1, + 'novice': 1, + 'basic': 2, + 'beginner': 2, + 'intermediate': 4, + 'proficient': 5, + 'competent': 6, + 'advanced': 7, + 'expert': 8, + 'mastered': 9, + 'master': 9, + 'grandmaster': 10, + 'legendary': 10 + }; + + const level = proficiencyMap[proficiencyText] || 5; // Default to 5 if unknown + + const skill = { + name: skillName, + level: level, + xp: 0, + maxXP: 100 + }; + + if (currentCategory === 'Uncategorized' || currentCategory === null) { + skillsData.uncategorized.push(skill); + } else if (currentCategory && skillsData.categories[currentCategory]) { + skillsData.categories[currentCategory].push(skill); + } + } } } diff --git a/src/systems/generation/promptBuilder.js b/src/systems/generation/promptBuilder.js index a1dbf42..17f1547 100644 --- a/src/systems/generation/promptBuilder.js +++ b/src/systems/generation/promptBuilder.js @@ -219,7 +219,7 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon instructions += `- [Another Skill] (Lv [1-100])\n`; instructions += `Uncategorized:\n`; instructions += `- [Uncategorized Skill] (Lv [1-100])\n`; - instructions += `(Organize skills by logical categories like Combat, Magic, Social, Crafting, etc. Include level as integer 1-100. Skills without a clear category go in Uncategorized.)\n`; + instructions += `(Organize skills by logical categories like Combat, Magic, Social, Crafting, etc. IMPORTANT: Use numeric levels only - write "Lv 5" not "Proficient", "Lv 7" not "Advanced". Use integers 1-100 where 1=novice, 5=intermediate, 10=expert. Skills without a clear category go in Uncategorized.)\n`; } // Add inventory format based on feature flag