File
|
completion
|
completion: number
|
Type : number
|
|
id
|
id: number
|
Type : number
|
|
label
|
label: string
|
Type : string
|
|
name
|
name: string
|
Type : string
|
|
open
|
open: boolean
|
Type : boolean
|
import { Grade } from "./exercices";
import { Journey } from "./journey";
export interface Domain {
id : number;
name : string;
subDomains : SubDomain[];
picture : string;
locked : boolean;
}
export interface SubDomain {
id : number;
JourneyDifficultys ? : JourneyDifficulty[];
subSections ? : SubSection[];
name : string;
//app visual name
label : string;
picture : string;
locked : boolean;
color : ColorName;
completion?: number;
reward?: RewardType;
bilan?: Array<{id: number, type: string, grade: Grade, done?: boolean}>;
}
export interface SubSection {
id : number;
name : string;
label : string;
JourneyDifficultys : JourneyDifficulty[];
completion?: number;
open ? : boolean;
}
export interface JourneyDifficulty {
id : number;
journeys : (Journey | number)[];
name : string;
//app visual name
label : string;
locked : boolean;
grade : Grade
completion?: number;
parent? : SubSection;
}
/**
* Filters `Domain` or `SubDomain` items by a given `Grade`.
*
* @template T - either `Domain` or `SubDomain`
* @param {T[]} items - Array of items to filter. If `grade` is falsy, a shallow copy of `items` is returned.
* @param {Grade} [grade] - Grade to filter by.
* @returns {T[]} Filtered array of the same element type.
*
* @remarks
* - An item is kept when at least one `JourneyDifficulty` with the specified `grade` exists.
* - For `Domain`, the function checks each `subDomain`'s `JourneyDifficultys`; for `SubDomain`, it checks its `JourneyDifficultys`.
* - The function is pure and does not mutate the input array or its items.
* - Complexity: O(n * m) where n = items.length and m = average number of `JourneyDifficulty` entries per item.
*
* @example
* const filteredDomains = filterByGrade(domains, Grade.Primary);
*/
export function filterByGrade<T extends Domain | SubDomain>(items: T[], grade?: Grade): T[] {
if (!grade) return items.slice();
return items.filter(item => {
// Domain contient `subDomains`
if ((item as Domain).subDomains !== undefined) {
const domain = item as Domain;
return domain.subDomains.some(sd =>
Array.isArray(sd.JourneyDifficultys) && sd.JourneyDifficultys.some(jd => jd.grade === grade)
);
}
// SubDomain contient `JourneyDifficultys` ou `subSections`
if ((item as SubDomain).JourneyDifficultys !== undefined || (item as SubDomain).subSections !== undefined) {
const sd = item as SubDomain;
// Check direct JourneyDifficultys
const hasDirectJourneys = Array.isArray(sd.JourneyDifficultys) &&
sd.JourneyDifficultys.some(jd => jd.grade === grade);
// Check JourneyDifficultys in subSections
const hasSubSectionJourneys = Array.isArray(sd.subSections) &&
sd.subSections.some(ss =>
Array.isArray(ss.JourneyDifficultys) && ss.JourneyDifficultys.some(jd => jd.grade === grade)
);
return hasDirectJourneys || hasSubSectionJourneys;
}
return false;
});
}
/**
* Predefined color names (English).
*
* Use the `name` value from this enum as the canonical color identifier.
* The human-facing `label` should come from localization resources.
*/
export enum ColorName {
Purple = 'Purple',
Green = 'Green',
Turquoise = 'Turquoise',
Red = 'Red',
Pink = 'Pink',
Orange = 'Orange',
Yellow = 'Yellow',
Blue = 'Blue'
}
/**
* Get the localized label for a `ColorName`.
*
* @param name - The `ColorName` enum value to localize.
* @returns The localized label string for the given color.
*
* @remarks
* Each returned string is a `$localize` literal with an explicit message id
* (`@@colors.<name>`) so extraction tools can include them in XLIFF.
*/
export function getColorLabel(name: ColorName): string {
switch (name) {
case ColorName.Purple:
return $localize`:@@colors.purple:Violet`;
case ColorName.Green:
return $localize`:@@colors.green:Vert`;
case ColorName.Turquoise:
return $localize`:@@colors.turquoise:Turquoise`;
case ColorName.Red:
return $localize`:@@colors.red:Rouge`;
case ColorName.Pink:
return $localize`:@@colors.pink:Rose`;
case ColorName.Orange:
return $localize`:@@colors.orange:Orange`;
case ColorName.Yellow:
return $localize`:@@colors.yellow:Jaune`;
case ColorName.Blue:
return $localize`:@@colors.blue:Bleu`;
default:
return $localize`:@@colors.unknown:Couleur`;
}
}
/**
* Types of rewards available in the app.
*/
export enum RewardType {
Diamond = 'Diamond',
Star = 'Star',
Key = 'Key',
Crown = 'Crown',
Amulet = 'Amulet',
Ring = 'Ring',
Hourglass = 'Hourglass'
}
/**
* Get the localized label for a `RewardType`.
*
* @param name - The `RewardType` enum value to localize.
* @returns The localized label string for the given reward.
*
* @remarks
* Each returned string is a `$localize` literal with an explicit message id
* (`@@rewards.<name>`) so extraction tools can include them in XLIFF.
*/
export function getRewardLabel(name: RewardType, withPronom = false): string {
switch (name) {
case RewardType.Diamond:
return $localize`:@@rewards.diamond:Diamant`;
case RewardType.Star:
return $localize`:@@rewards.star:Étoile`;
case RewardType.Key:
return $localize`:@@rewards.key:Clé`;
case RewardType.Crown:
return $localize`:@@rewards.crown:Couronne`;
case RewardType.Amulet:
return $localize`:@@rewards.amulet:Amulette`;
case RewardType.Ring:
return $localize`:@@rewards.ring:Anneau`;
case RewardType.Hourglass:
return $localize`:@@rewards.hourglass:Sablier`;
default:
return $localize`:@@rewards.unknown:Récompense`;
}
}
export function getRewardNameInPhrase(name: RewardType, plural = false): string {
let str = getRewardLabel(name);
str = str[0].toLocaleLowerCase() + str.substring(1);
switch (name) {
case RewardType.Diamond:
case RewardType.Hourglass:
return plural ? `des ${str}s` : `un ${str}`;
case RewardType.Star:
case RewardType.Key:
case RewardType.Crown:
case RewardType.Amulet:
return plural ? `des ${str}s` : `une ${str}`;
case RewardType.Ring:
return plural ? `des ${str}x` : `un ${str}`;
default:
return plural ? `des récompenses` : `une récompense`;
}
function rewardToFile(reward: RewardType): string {
switch (reward) {
case RewardType.Diamond: return 'Diamant';
case RewardType.Star: return 'Etoile';
case RewardType.Key: return 'Cle';
case RewardType.Crown: return 'Couronne';
case RewardType.Amulet: return 'Amulette';
case RewardType.Ring: return 'Anneau';
case RewardType.Hourglass: return 'Sablier';
default: return '';
}
}
function colorToFile(color: ColorName): string {
switch (color) {
case ColorName.Blue: return 'Bleu';
case ColorName.Yellow: return 'Jaune';
case ColorName.Orange: return 'Orange';
case ColorName.Pink: return 'Rose';
case ColorName.Red: return 'Rouge';
case ColorName.Turquoise: return 'Turquoise';
case ColorName.Green: return 'Vert';
case ColorName.Purple: return 'Violet';
default: return '';
}
}
}