Files
dwroller/scripts/cleanup-skill-dupes.py
Alex 1e361301ad Fix rules search ranking and import clean skills/talents from Core Rulebook
- Add search relevance scoring: exact title > title prefix > title contains > Core Rulebook source > content match
- Add DB_PASSWORD env var to pm2.config.js so server can connect to MariaDB
- Add update-rules-from-sources.py: imports 45 skills from CSV and 44 talents from CR.txt, removes garbage advance-table entries
- Add fix-talent-titles.py: normalises OCR-garbled talent titles, removes 28 duplicates, fixes 65 entries
- Add cleanup-skill-dupes.py: removes duplicate skills from csv-import/fandom/sanitized sources, recategorises 55 lore entries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 18:25:08 +01:00

90 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""
Remove duplicate/inferior skill entries now that we have clean Core Rulebook versions.
Also recategorize clearly non-skill sanitized entries.
"""
import re, mysql.connector
DB = dict(host='192.168.1.113', port=3307, user='deathwatch', password='DwRoller@2025!', database='deathwatch')
db = mysql.connector.connect(**DB)
c = db.cursor()
# 1. Get all clean skill names (Core Rulebook source)
c.execute("SELECT title FROM rules WHERE source='Core Rulebook' AND category='skills'")
clean_skill_names = {row[0].lower() for row in c.fetchall()}
print(f"Clean skills: {len(clean_skill_names)}")
# 2. Delete old csv-import entries for skills we now have clean versions of
c.execute("SELECT id, title FROM rules WHERE source='csv-import' AND category IN ('skills','Skills/Rules')")
csv_skills = c.fetchall()
deleted_csv = 0
for db_id, title in csv_skills:
if title.lower() in clean_skill_names:
c.execute("DELETE FROM rules WHERE id=%s", (db_id,))
deleted_csv += 1
print(f"Deleted {deleted_csv} old csv-import skill duplicates")
# 3. Delete old fandom entries for skills we now have clean versions of
c.execute("SELECT id, title FROM rules WHERE source IN ('fandom','https://40k-rpg-ffg.fandom.com') AND category IN ('skills','Skills/Rules')")
fandom_skills = c.fetchall()
deleted_fandom = 0
for db_id, title in fandom_skills:
if title.lower() in clean_skill_names:
c.execute("DELETE FROM rules WHERE id=%s", (db_id,))
deleted_fandom += 1
print(f"Deleted {deleted_fandom} old fandom skill duplicates")
# 4. Delete sanitized duplicate skill entries (where we have an exact title match in Core Rulebook)
c.execute("SELECT id, title FROM rules WHERE source='sanitized' AND category='skills'")
sanitized_skills = c.fetchall()
deleted_san = 0
for db_id, title in sanitized_skills:
if title.lower() in clean_skill_names:
c.execute("DELETE FROM rules WHERE id=%s", (db_id,))
deleted_san += 1
print(f"Deleted {deleted_san} sanitized skill duplicates")
db.commit()
# 5. Recategorize sanitized "skills" that are clearly lore/background
# Rules whose titles suggest they're lore, not skills
lore_patterns = [
'Chapter Recruitment', 'Dark Heresy', 'Watch Fortress', 'Initiations',
'Combat Doctrine', 'THE AGES', 'Hive Fleet', 'Blood Trinity',
'Military Machine', 'Recruitment', 'Castobel', 'Warp', 'Erioch',
'Jericho', 'Tau', 'Tyranid', 'Ork', 'Eldar', 'Necron', 'Chaos',
]
c.execute("SELECT id, title FROM rules WHERE source='sanitized' AND category='skills'")
sanitized_remaining = c.fetchall()
recatd = 0
for db_id, title in sanitized_remaining:
for pat in lore_patterns:
if pat.lower() in title.lower():
c.execute("UPDATE rules SET category='lore' WHERE id=%s", (db_id,))
recatd += 1
break
print(f"Recategorized {recatd} lore entries from 'skills' to 'lore'")
# 6. Rules-category cleanup: remove duplicate numeric/fragment titles
c.execute("DELETE FROM rules WHERE source='sanitized' AND category='skills' AND title REGEXP '^[0-9]+$'")
print(f"Deleted {c.rowcount} numeric-title entries")
db.commit()
# Final stats
c.execute("SELECT category, COUNT(*) FROM rules GROUP BY category ORDER BY COUNT(*) DESC")
print("\n=== Rules by category ===")
for cat, cnt in c.fetchall():
print(f" {cat}: {cnt}")
c.execute("SELECT source, COUNT(*) FROM rules GROUP BY source ORDER BY COUNT(*) DESC")
print("\n=== Rules by source ===")
total = 0
for src, cnt in c.fetchall():
print(f" {src}: {cnt}")
total += cnt
print(f" TOTAL: {total}")
c.close()
db.close()