Refactor character affiliations to singular form

- Updated character data structure to replace 'affiliations' and 'frAffiliations' with 'affiliation' and 'frAffiliation'.
- Modified related functions and components to accommodate the new structure.
- Adjusted database schema and server-side logic to reflect the changes in character affiliation handling.
- Ensured all references in the UI components and data import/export scripts are updated accordingly.
This commit is contained in:
2026-04-14 21:56:26 +02:00
parent fa14156d82
commit d75c74ac3c
12 changed files with 1256 additions and 107 deletions

View File

@@ -23,8 +23,8 @@ interface Character {
frOrigin: string | null;
devilFruitId: string | null;
devilFruitUrl: string | null;
affiliations: string[];
frAffiliations: string[] | null;
affiliation: string | null;
frAffiliation: string | null;
bounty: number | null;
hakiObservation: boolean;
hakiArmament: boolean;
@@ -370,7 +370,7 @@ async function fetchAllCharacters(arcsList: Arc[]): Promise<Character[]> {
Age: data.age,
Status: data.status,
Epithets: data.epithets.join(', '),
Affiliations: data.affiliations.join(', '),
Affiliation: data.affiliation,
DevilFruitId: data.devilFruitId,
DevilFruitUrl: data.devilFruitUrl,
HakiObservation: data.hakiObservation ? 'Yes' : 'No',
@@ -453,8 +453,8 @@ async function fetchCharacter(
// Extract age
const age = extractAge($);
// Extract affiliations
const affiliations = await extractAffiliations($, 'en');
// Extract affiliation
const affiliation = await extractAffiliations($, 'en');
// Extract epithets
const epithets = extractEpithets($);
@@ -513,7 +513,7 @@ async function fetchCharacter(
let frName = frjsonData?.parse?.title || null;
const frAffiliations = frjsonData
const frAffiliation = frjsonData
? await extractAffiliations(cheerio.load(frjsonData.parse?.text?.['*'] || ''), 'fr')
: null;
@@ -542,8 +542,8 @@ async function fetchCharacter(
frOrigin,
devilFruitId,
devilFruitUrl,
affiliations,
frAffiliations,
affiliation,
frAffiliation,
bounty,
hakiObservation,
hakiArmament,
@@ -591,15 +591,15 @@ function extractAge($: cheerio.CheerioAPI): number | null {
/**
* Extract affiliations from infobox
*/
async function extractAffiliations($: cheerio.CheerioAPI, lang: string): Promise<string[]> {
async function extractAffiliations($: cheerio.CheerioAPI, lang: string): Promise<string | null> {
const div = $('[data-source="affiliation"] .pi-data-value');
if (div.length === 0) return [];
if (div.length === 0) return null;
const cleanedDiv = div.clone();
cleanedDiv.find('sup').remove();
const text = cleanedDiv.html();
if (!text) return [];
if (!text) return null;
// Resolve affiliations from linked page titles.
const links = cleanedDiv.find('a').toArray();
@@ -624,14 +624,14 @@ async function extractAffiliations($: cheerio.CheerioAPI, lang: string): Promise
const uniqueLinks = Array.from(new Set(linkValues.filter(Boolean)));
if (uniqueLinks.length > 0) {
return uniqueLinks;
return uniqueLinks[0];
}
}
// Fallback to parsing text
const cleanText = text.replace(/<[^>]*>/g, '').trim();
const parts = cleanText.split(/\s*\n\s*|\s*;\s*|\s*,\s*/).filter(Boolean);
return parts.length > 0 ? parts : [];
return parts.length > 0 ? parts[0] : null;
}
/**
@@ -869,9 +869,8 @@ async function saveToCSV(characters: Character[]): Promise<void> {
status: c.status || '',
epithets: Array.isArray(c.epithets) ? c.epithets.join(', ') : c.epithets || '',
devilFruitId: c.devilFruitId || '',
affiliations: Array.isArray(c.affiliations)
? c.affiliations.join(', ')
: c.affiliations || '',
affiliation: c.affiliation || '',
frAffiliation: c.frAffiliation || '',
bounty: c.bounty ?? 0,
hakiObservation: c.hakiObservation ? 1 : 0,
hakiArmament: c.hakiArmament ? 1 : 0,