Add models for guidelines, incidents, plot points, issues, acts, and world data
- Introduced new models: `GuideLine`, `Incident`, `PlotPoint`, `Issue`, `Act`, and `World` for managing book-related entities. - Integrated encryption/decryption for sensitive properties in all models using user-specific keys. - Added methods for CRUD operations and synchronization workflows with error handling and multilingual support. - Improved maintainability with JSDoc comments and streamlined queries.
This commit is contained in:
@@ -65,50 +65,81 @@ export interface CharacterAttribute {
|
||||
values: Attribute[];
|
||||
}
|
||||
|
||||
export interface SyncedCharacter {
|
||||
id: string;
|
||||
name: string;
|
||||
lastUpdate: number;
|
||||
attributes: SyncedCharacterAttribute[];
|
||||
}
|
||||
|
||||
export interface SyncedCharacterAttribute {
|
||||
id: string;
|
||||
name: string;
|
||||
lastUpdate: number;
|
||||
}
|
||||
|
||||
export default class Character {
|
||||
/**
|
||||
* Retrieves a list of all characters for a specific book.
|
||||
* Decrypts character data using the user's encryption key.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @returns An array of decrypted character properties
|
||||
*/
|
||||
public static getCharacterList(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): CharacterProps[] {
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
const characters: CharacterResult[] = CharacterRepo.fetchCharacters(userId, bookId, lang);
|
||||
if (!characters) return [];
|
||||
if (characters.length === 0) return [];
|
||||
const characterList: CharacterProps[] = [];
|
||||
for (const character of characters) {
|
||||
characterList.push({
|
||||
id: character.character_id,
|
||||
name: character.first_name ? System.decryptDataWithUserKey(character.first_name, userKey) : '',
|
||||
lastName: character.last_name ? System.decryptDataWithUserKey(character.last_name, userKey) : '',
|
||||
title: character.title ? System.decryptDataWithUserKey(character.title, userKey) : '',
|
||||
category: character.category ? System.decryptDataWithUserKey(character.category, userKey) : '',
|
||||
image: character.image ? System.decryptDataWithUserKey(character.image, userKey) : '',
|
||||
role: character.role ? System.decryptDataWithUserKey(character.role, userKey) : '',
|
||||
biography: character.biography ? System.decryptDataWithUserKey(character.biography, userKey) : '',
|
||||
history: character.history ? System.decryptDataWithUserKey(character.history, userKey) : '',
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const encryptedCharacters: CharacterResult[] = CharacterRepo.fetchCharacters(userId, bookId, lang);
|
||||
if (!encryptedCharacters) return [];
|
||||
if (encryptedCharacters.length === 0) return [];
|
||||
const decryptedCharacterList: CharacterProps[] = [];
|
||||
for (const encryptedCharacter of encryptedCharacters) {
|
||||
decryptedCharacterList.push({
|
||||
id: encryptedCharacter.character_id,
|
||||
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
||||
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
||||
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title, userEncryptionKey) : '',
|
||||
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category, userEncryptionKey) : '',
|
||||
image: encryptedCharacter.image ? System.decryptDataWithUserKey(encryptedCharacter.image, userEncryptionKey) : '',
|
||||
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role, userEncryptionKey) : '',
|
||||
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography, userEncryptionKey) : '',
|
||||
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history, userEncryptionKey) : '',
|
||||
})
|
||||
}
|
||||
return characterList;
|
||||
return decryptedCharacterList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new character with all its attributes for a specific book.
|
||||
* Encrypts all character data before storing in the database.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param character - The character data to be created
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @param existingCharacterId - Optional existing character ID for updates or imports
|
||||
* @returns The unique identifier of the newly created character
|
||||
*/
|
||||
public static addNewCharacter(userId: string, character: CharacterPropsPost, bookId: string, lang: 'fr' | 'en' = 'fr', existingCharacterId?: string): string {
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const characterId: string = existingCharacterId || System.createUniqueId();
|
||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userKey);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userEncryptionKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userEncryptionKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userEncryptionKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userEncryptionKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userEncryptionKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userEncryptionKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userEncryptionKey);
|
||||
CharacterRepo.addNewCharacter(userId, characterId, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, bookId, lang);
|
||||
const attributes: string[] = Object.keys(character);
|
||||
for (const key of attributes) {
|
||||
if (Array.isArray(character[key as keyof CharacterPropsPost])) {
|
||||
const array = character[key as keyof CharacterPropsPost] as { name: string }[];
|
||||
if (array.length > 0) {
|
||||
for (const item of array) {
|
||||
const type: string = key;
|
||||
const name: string = item.name;
|
||||
this.addNewAttribute(characterId, userId, type, name, lang);
|
||||
const characterPropertyKeys: string[] = Object.keys(character);
|
||||
for (const propertyKey of characterPropertyKeys) {
|
||||
if (Array.isArray(character[propertyKey as keyof CharacterPropsPost])) {
|
||||
const attributeArray = character[propertyKey as keyof CharacterPropsPost] as { name: string }[];
|
||||
if (attributeArray.length > 0) {
|
||||
for (const attributeItem of attributeArray) {
|
||||
const attributeType: string = propertyKey;
|
||||
const attributeName: string = attributeItem.name;
|
||||
this.addNewAttribute(characterId, userId, attributeType, attributeName, lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,85 +147,128 @@ export default class Character {
|
||||
return characterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing character's core properties.
|
||||
* Encrypts all updated data before storing in the database.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param character - The character data with updated values
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @returns True if the update was successful, false otherwise
|
||||
*/
|
||||
static updateCharacter(userId: string, character: CharacterPropsPost, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
if (!character.id) {
|
||||
return false;
|
||||
}
|
||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userKey);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userEncryptionKey);
|
||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userEncryptionKey);
|
||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userEncryptionKey);
|
||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userEncryptionKey);
|
||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userEncryptionKey);
|
||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userEncryptionKey);
|
||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userEncryptionKey);
|
||||
return CharacterRepo.updateCharacter(userId, character.id, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, System.timeStampInSeconds(), lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new attribute to a character.
|
||||
* Attributes are categorized properties like physical traits, skills, or goals.
|
||||
* @param characterId - The unique identifier of the character
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param type - The type/category of the attribute (e.g., 'physical', 'skills')
|
||||
* @param name - The value/name of the attribute
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @param existingAttributeId - Optional existing attribute ID for updates or imports
|
||||
* @returns The unique identifier of the newly created attribute
|
||||
*/
|
||||
static addNewAttribute(characterId: string, userId: string, type: string, name: string, lang: 'fr' | 'en' = 'fr', existingAttributeId?: string): string {
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const attributeId: string = existingAttributeId || System.createUniqueId();
|
||||
const encryptedType: string = System.encryptDataWithUserKey(type, userKey);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(name, userKey);
|
||||
const encryptedType: string = System.encryptDataWithUserKey(type, userEncryptionKey);
|
||||
const encryptedName: string = System.encryptDataWithUserKey(name, userEncryptionKey);
|
||||
return CharacterRepo.insertAttribute(attributeId, characterId, userId, encryptedType, encryptedName, lang);
|
||||
}
|
||||
|
||||
static deleteAttribute(userId: string, attributeId: string, lang: 'fr' | 'en' = 'fr') {
|
||||
/**
|
||||
* Deletes an attribute from a character.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param attributeId - The unique identifier of the attribute to delete
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @returns True if the deletion was successful, false otherwise
|
||||
*/
|
||||
static deleteAttribute(userId: string, attributeId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||
return CharacterRepo.deleteAttribute(userId, attributeId, lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all attributes for a specific character, grouped by type.
|
||||
* Decrypts attribute data using the user's encryption key.
|
||||
* @param characterId - The unique identifier of the character
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @returns An array of character attributes grouped by type
|
||||
*/
|
||||
static getAttributes(characterId: string, userId: string, lang: 'fr' | 'en' = 'fr'): CharacterAttribute[] {
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
const attributes: AttributeResult[] = CharacterRepo.fetchAttributes(characterId, userId, lang);
|
||||
if (!attributes?.length) return [];
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const encryptedAttributes: AttributeResult[] = CharacterRepo.fetchAttributes(characterId, userId, lang);
|
||||
if (!encryptedAttributes?.length) return [];
|
||||
|
||||
const groupedMap: Map<string, Attribute[]> = new Map<string, Attribute[]>();
|
||||
const attributesByType: Map<string, Attribute[]> = new Map<string, Attribute[]>();
|
||||
|
||||
for (const attribute of attributes) {
|
||||
const type: string = System.decryptDataWithUserKey(attribute.attribute_name, userKey);
|
||||
const value: string = attribute.attribute_value ? System.decryptDataWithUserKey(attribute.attribute_value, userKey) : '';
|
||||
for (const encryptedAttribute of encryptedAttributes) {
|
||||
const decryptedType: string = System.decryptDataWithUserKey(encryptedAttribute.attribute_name, userEncryptionKey);
|
||||
const decryptedValue: string = encryptedAttribute.attribute_value ? System.decryptDataWithUserKey(encryptedAttribute.attribute_value, userEncryptionKey) : '';
|
||||
|
||||
if (!groupedMap.has(type)) {
|
||||
groupedMap.set(type, []);
|
||||
if (!attributesByType.has(decryptedType)) {
|
||||
attributesByType.set(decryptedType, []);
|
||||
}
|
||||
|
||||
groupedMap.get(type)!.push({
|
||||
id: attribute.attr_id,
|
||||
name: value
|
||||
attributesByType.get(decryptedType)!.push({
|
||||
id: encryptedAttribute.attr_id,
|
||||
name: decryptedValue
|
||||
});
|
||||
}
|
||||
|
||||
return Array.from<[string, Attribute[]], CharacterAttribute>(
|
||||
groupedMap,
|
||||
attributesByType,
|
||||
([type, values]: [string, Attribute[]]): CharacterAttribute => ({type, values})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves complete character data including all attributes for multiple characters.
|
||||
* Used for exporting or displaying full character profiles.
|
||||
* @param userId - The unique identifier of the user
|
||||
* @param bookId - The unique identifier of the book
|
||||
* @param characters - An array of character IDs to retrieve
|
||||
* @param lang - The language code for localization (defaults to 'fr')
|
||||
* @returns An array of complete character objects with all their attributes
|
||||
*/
|
||||
static getCompleteCharacterList(userId: string, bookId: string, characters: string[], lang: 'fr' | 'en' = 'fr'): CompleteCharacterProps[] {
|
||||
const characterList: CompleteCharacterResult[] = CharacterRepo.fetchCompleteCharacters(userId, bookId, characters, lang);
|
||||
const encryptedCharacterList: CompleteCharacterResult[] = CharacterRepo.fetchCompleteCharacters(userId, bookId, characters, lang);
|
||||
|
||||
if (!characterList || characterList.length === 0) {
|
||||
if (!encryptedCharacterList || encryptedCharacterList.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const userKey: string = getUserEncryptionKey(userId);
|
||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||
const completeCharactersMap = new Map<string, CompleteCharacterProps>();
|
||||
for (const character of characterList) {
|
||||
if (!character.character_id) {
|
||||
for (const encryptedCharacter of encryptedCharacterList) {
|
||||
if (!encryptedCharacter.character_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!completeCharactersMap.has(character.character_id)) {
|
||||
const personnageObj: CompleteCharacterProps = {
|
||||
if (!completeCharactersMap.has(encryptedCharacter.character_id)) {
|
||||
const decryptedCharacter: CompleteCharacterProps = {
|
||||
id: '',
|
||||
name: character.first_name ? System.decryptDataWithUserKey(character.first_name, userKey) : '',
|
||||
lastName: character.last_name ? System.decryptDataWithUserKey(character.last_name, userKey) : '',
|
||||
title: character.title ? System.decryptDataWithUserKey(character.title, userKey) : '',
|
||||
category: character.category ? System.decryptDataWithUserKey(character.category, userKey) : '',
|
||||
role: character.role ? System.decryptDataWithUserKey(character.role, userKey) : '',
|
||||
biography: character.biography ? System.decryptDataWithUserKey(character.biography, userKey) : '',
|
||||
history: character.history ? System.decryptDataWithUserKey(character.history, userKey) : '',
|
||||
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
||||
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
||||
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title, userEncryptionKey) : '',
|
||||
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category, userEncryptionKey) : '',
|
||||
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role, userEncryptionKey) : '',
|
||||
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography, userEncryptionKey) : '',
|
||||
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history, userEncryptionKey) : '',
|
||||
physical: [],
|
||||
psychological: [],
|
||||
relations: [],
|
||||
@@ -204,36 +278,42 @@ export default class Character {
|
||||
goals: [],
|
||||
motivations: []
|
||||
};
|
||||
completeCharactersMap.set(character.character_id, personnageObj);
|
||||
completeCharactersMap.set(encryptedCharacter.character_id, decryptedCharacter);
|
||||
}
|
||||
|
||||
const personnage: CompleteCharacterProps | undefined = completeCharactersMap.get(character.character_id);
|
||||
const characterEntry: CompleteCharacterProps | undefined = completeCharactersMap.get(encryptedCharacter.character_id);
|
||||
|
||||
if (!character.attribute_name || !personnage) {
|
||||
if (!encryptedCharacter.attribute_name || !characterEntry) {
|
||||
continue;
|
||||
}
|
||||
const decryptedName: string = System.decryptDataWithUserKey(character.attribute_name, userKey);
|
||||
const decryptedValue: string = character.attribute_value ? System.decryptDataWithUserKey(character.attribute_value, userKey) : '';
|
||||
const decryptedAttributeName: string = System.decryptDataWithUserKey(encryptedCharacter.attribute_name, userEncryptionKey);
|
||||
const decryptedAttributeValue: string = encryptedCharacter.attribute_value ? System.decryptDataWithUserKey(encryptedCharacter.attribute_value, userEncryptionKey) : '';
|
||||
|
||||
if (Array.isArray(personnage[decryptedName])) {
|
||||
personnage[decryptedName].push({
|
||||
if (Array.isArray(characterEntry[decryptedAttributeName])) {
|
||||
characterEntry[decryptedAttributeName].push({
|
||||
id: '',
|
||||
name: decryptedValue
|
||||
name: decryptedAttributeValue
|
||||
});
|
||||
}
|
||||
}
|
||||
return Array.from(completeCharactersMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a formatted vCard-style string representation of characters.
|
||||
* Useful for AI context or text-based exports.
|
||||
* @param characters - An array of complete character objects to format
|
||||
* @returns A formatted string containing all character information
|
||||
*/
|
||||
static characterVCard(characters: CompleteCharacterProps[]): string {
|
||||
const charactersMap = new Map<string, CompleteCharacterProps>();
|
||||
let charactersDescription: string = '';
|
||||
const uniqueCharactersMap = new Map<string, CompleteCharacterProps>();
|
||||
let formattedCharactersDescription: string = '';
|
||||
|
||||
characters.forEach((character: CompleteCharacterProps): void => {
|
||||
const characterKey: string = character.name || character.id || 'unknown';
|
||||
const characterIdentifier: string = character.name || character.id || 'unknown';
|
||||
|
||||
if (!charactersMap.has(characterKey)) {
|
||||
charactersMap.set(characterKey, {
|
||||
if (!uniqueCharactersMap.has(characterIdentifier)) {
|
||||
uniqueCharactersMap.set(characterIdentifier, {
|
||||
name: character.name,
|
||||
lastName: character.lastName,
|
||||
category: character.category,
|
||||
@@ -244,24 +324,24 @@ export default class Character {
|
||||
});
|
||||
}
|
||||
|
||||
const characterData: CompleteCharacterProps = charactersMap.get(characterKey)!;
|
||||
const aggregatedCharacterData: CompleteCharacterProps = uniqueCharactersMap.get(characterIdentifier)!;
|
||||
|
||||
Object.keys(character).forEach((fieldName: string): void => {
|
||||
if (Array.isArray(character[fieldName])) {
|
||||
if (!characterData[fieldName]) characterData[fieldName] = [];
|
||||
(characterData[fieldName] as Attribute[]).push(...(character[fieldName] as Attribute[]));
|
||||
Object.keys(character).forEach((propertyName: string): void => {
|
||||
if (Array.isArray(character[propertyName])) {
|
||||
if (!aggregatedCharacterData[propertyName]) aggregatedCharacterData[propertyName] = [];
|
||||
(aggregatedCharacterData[propertyName] as Attribute[]).push(...(character[propertyName] as Attribute[]));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
charactersDescription = Array.from(charactersMap.values()).map((character: CompleteCharacterProps): string => {
|
||||
const descriptionFields: string[] = [];
|
||||
formattedCharactersDescription = Array.from(uniqueCharactersMap.values()).map((character: CompleteCharacterProps): string => {
|
||||
const characterDescriptionLines: string[] = [];
|
||||
const fullName: string = [character.name, character.lastName].filter(Boolean).join(' ');
|
||||
if (fullName) descriptionFields.push(`Nom : ${fullName}`);
|
||||
if (fullName) characterDescriptionLines.push(`Nom : ${fullName}`);
|
||||
|
||||
(['category', 'title', 'role', 'biography', 'history'] as const).forEach((propertyKey) => {
|
||||
if (character[propertyKey]) {
|
||||
descriptionFields.push(`${propertyKey.charAt(0).toUpperCase() + propertyKey.slice(1)} : ${character[propertyKey]}`);
|
||||
characterDescriptionLines.push(`${propertyKey.charAt(0).toUpperCase() + propertyKey.slice(1)} : ${character[propertyKey]}`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -269,13 +349,13 @@ export default class Character {
|
||||
const propertyValue: string | Attribute[] | undefined = character[propertyKey];
|
||||
if (Array.isArray(propertyValue) && propertyValue.length > 0) {
|
||||
const capitalizedPropertyKey: string = propertyKey.charAt(0).toUpperCase() + propertyKey.slice(1);
|
||||
const formattedValues: string = propertyValue.map((item: Attribute) => item.name).join(', ');
|
||||
descriptionFields.push(`${capitalizedPropertyKey} : ${formattedValues}`);
|
||||
const formattedAttributeValues: string = propertyValue.map((attributeItem: Attribute) => attributeItem.name).join(', ');
|
||||
characterDescriptionLines.push(`${capitalizedPropertyKey} : ${formattedAttributeValues}`);
|
||||
}
|
||||
});
|
||||
|
||||
return descriptionFields.join('\n');
|
||||
return characterDescriptionLines.join('\n');
|
||||
}).join('\n\n');
|
||||
return charactersDescription;
|
||||
return formattedCharactersDescription;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user