enefel 2.8.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/getRaceSpecialSkills.test.ts +58 -0
- package/career.ts +2 -10
- package/dist/__tests__/getRaceSpecialSkills.test.d.ts +1 -0
- package/dist/__tests__/getRaceSpecialSkills.test.js +48 -0
- package/dist/career.d.ts +2 -3
- package/dist/career.js +1 -2
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/dist/race.d.ts +5 -55
- package/dist/race.js +31 -1
- package/{jest.config.ts → jest.config.js} +6 -0
- package/package.json +1 -1
- package/race.ts +41 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
import { CAREER_ID, RACE } from "../career";
|
|
3
|
+
import { getRaceFromCareer, getRaceSpecialSkills } from "../race";
|
|
4
|
+
import { isSpecialSkill, SKILL_NAMES } from "../skill";
|
|
5
|
+
|
|
6
|
+
describe("getRaceSpecialSkills", () => {
|
|
7
|
+
it("devrait retourner les compétences spéciales communes à une race", () => {
|
|
8
|
+
const imperialSkills = getRaceSpecialSkills(RACE.IMPERIAL);
|
|
9
|
+
|
|
10
|
+
// Imperial devrait avoir 'specialist' car 3/5 carrières l'ont
|
|
11
|
+
expect(imperialSkills).toContain("specialist");
|
|
12
|
+
expect(imperialSkills.length).toBeGreaterThan(0);
|
|
13
|
+
|
|
14
|
+
// Vérifier que toutes les compétences retournées sont bien spéciales
|
|
15
|
+
imperialSkills.forEach((skill) => {
|
|
16
|
+
expect(isSpecialSkill(skill as SKILL_NAMES)).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("devrait retourner 'star' pour Vampire", () => {
|
|
21
|
+
const vampireSkills = getRaceSpecialSkills(RACE.VAMPIRE);
|
|
22
|
+
expect(vampireSkills).toContain("star");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("devrait retourner 'specialist' pour Amazon", () => {
|
|
26
|
+
const amazonSkills = getRaceSpecialSkills(RACE.AMAZON);
|
|
27
|
+
expect(amazonSkills).toContain("specialist");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("devrait retourner un tableau vide pour une race sans compétences spéciales communes", () => {
|
|
31
|
+
const humanSkills = getRaceSpecialSkills(RACE.HUMAN);
|
|
32
|
+
// Human n'a pas de compétences spéciales communes à toutes les carrières
|
|
33
|
+
expect(Array.isArray(humanSkills)).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("devrait fonctionner avec un RACE obtenu depuis un CAREER_ID", () => {
|
|
37
|
+
const careerId = CAREER_ID.IMPERIAL_BODYGUARD;
|
|
38
|
+
const race = getRaceFromCareer(careerId);
|
|
39
|
+
|
|
40
|
+
expect(race).toBe(RACE.IMPERIAL);
|
|
41
|
+
|
|
42
|
+
const skills = getRaceSpecialSkills(race!);
|
|
43
|
+
expect(skills.length).toBeGreaterThan(0);
|
|
44
|
+
expect(skills).toContain("specialist");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("devrait retourner les compétences qui apparaissent dans au moins 50% des carrières", () => {
|
|
48
|
+
const imperialSkills = getRaceSpecialSkills(RACE.IMPERIAL);
|
|
49
|
+
|
|
50
|
+
// Imperial a 5 carrières, donc le seuil est 3 (50% de 5 = 2.5, arrondi à 3)
|
|
51
|
+
// 'specialist' apparaît dans 3 carrières (thrower, blitzer, bodyguard)
|
|
52
|
+
// Donc 'specialist' devrait être retourné
|
|
53
|
+
expect(imperialSkills).toContain("specialist");
|
|
54
|
+
|
|
55
|
+
// 'big-guy' apparaît seulement dans 1 carrière (ogre), donc ne devrait pas être retourné
|
|
56
|
+
expect(imperialSkills).not.toContain("big-guy");
|
|
57
|
+
});
|
|
58
|
+
});
|
package/career.ts
CHANGED
|
@@ -180,7 +180,7 @@ enum CAREER_VERSION {
|
|
|
180
180
|
V2020 = "v2020",
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
type Career = {
|
|
183
|
+
export type Career = {
|
|
184
184
|
MA: number;
|
|
185
185
|
ST: number;
|
|
186
186
|
AG: number;
|
|
@@ -2162,12 +2162,4 @@ const getCareers = (): Record<CAREER_ID, Career> => {
|
|
|
2162
2162
|
return CAREER;
|
|
2163
2163
|
};
|
|
2164
2164
|
|
|
2165
|
-
export {
|
|
2166
|
-
AVATAR,
|
|
2167
|
-
AVATAR_RARITY,
|
|
2168
|
-
CAREER,
|
|
2169
|
-
CAREER_ID,
|
|
2170
|
-
CAREER_VERSION,
|
|
2171
|
-
getCareers,
|
|
2172
|
-
RACE,
|
|
2173
|
-
};
|
|
2165
|
+
export { AVATAR, AVATAR_RARITY, CAREER_ID, CAREER_VERSION, getCareers, RACE };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const globals_1 = require("@jest/globals");
|
|
4
|
+
const career_1 = require("../career");
|
|
5
|
+
const race_1 = require("../race");
|
|
6
|
+
const skill_1 = require("../skill");
|
|
7
|
+
(0, globals_1.describe)("getRaceSpecialSkills", () => {
|
|
8
|
+
(0, globals_1.it)("devrait retourner les compétences spéciales communes à une race", () => {
|
|
9
|
+
const imperialSkills = (0, race_1.getRaceSpecialSkills)(career_1.RACE.IMPERIAL);
|
|
10
|
+
// Imperial devrait avoir 'specialist' car 3/5 carrières l'ont
|
|
11
|
+
(0, globals_1.expect)(imperialSkills).toContain("specialist");
|
|
12
|
+
(0, globals_1.expect)(imperialSkills.length).toBeGreaterThan(0);
|
|
13
|
+
// Vérifier que toutes les compétences retournées sont bien spéciales
|
|
14
|
+
imperialSkills.forEach((skill) => {
|
|
15
|
+
(0, globals_1.expect)((0, skill_1.isSpecialSkill)(skill)).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
(0, globals_1.it)("devrait retourner 'star' pour Vampire", () => {
|
|
19
|
+
const vampireSkills = (0, race_1.getRaceSpecialSkills)(career_1.RACE.VAMPIRE);
|
|
20
|
+
(0, globals_1.expect)(vampireSkills).toContain("star");
|
|
21
|
+
});
|
|
22
|
+
(0, globals_1.it)("devrait retourner 'specialist' pour Amazon", () => {
|
|
23
|
+
const amazonSkills = (0, race_1.getRaceSpecialSkills)(career_1.RACE.AMAZON);
|
|
24
|
+
(0, globals_1.expect)(amazonSkills).toContain("specialist");
|
|
25
|
+
});
|
|
26
|
+
(0, globals_1.it)("devrait retourner un tableau vide pour une race sans compétences spéciales communes", () => {
|
|
27
|
+
const humanSkills = (0, race_1.getRaceSpecialSkills)(career_1.RACE.HUMAN);
|
|
28
|
+
// Human n'a pas de compétences spéciales communes à toutes les carrières
|
|
29
|
+
(0, globals_1.expect)(Array.isArray(humanSkills)).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
(0, globals_1.it)("devrait fonctionner avec un RACE obtenu depuis un CAREER_ID", () => {
|
|
32
|
+
const careerId = career_1.CAREER_ID.IMPERIAL_BODYGUARD;
|
|
33
|
+
const race = (0, race_1.getRaceFromCareer)(careerId);
|
|
34
|
+
(0, globals_1.expect)(race).toBe(career_1.RACE.IMPERIAL);
|
|
35
|
+
const skills = (0, race_1.getRaceSpecialSkills)(race);
|
|
36
|
+
(0, globals_1.expect)(skills.length).toBeGreaterThan(0);
|
|
37
|
+
(0, globals_1.expect)(skills).toContain("specialist");
|
|
38
|
+
});
|
|
39
|
+
(0, globals_1.it)("devrait retourner les compétences qui apparaissent dans au moins 50% des carrières", () => {
|
|
40
|
+
const imperialSkills = (0, race_1.getRaceSpecialSkills)(career_1.RACE.IMPERIAL);
|
|
41
|
+
// Imperial a 5 carrières, donc le seuil est 3 (50% de 5 = 2.5, arrondi à 3)
|
|
42
|
+
// 'specialist' apparaît dans 3 carrières (thrower, blitzer, bodyguard)
|
|
43
|
+
// Donc 'specialist' devrait être retourné
|
|
44
|
+
(0, globals_1.expect)(imperialSkills).toContain("specialist");
|
|
45
|
+
// 'big-guy' apparaît seulement dans 1 carrière (ogre), donc ne devrait pas être retourné
|
|
46
|
+
(0, globals_1.expect)(imperialSkills).not.toContain("big-guy");
|
|
47
|
+
});
|
|
48
|
+
});
|
package/dist/career.d.ts
CHANGED
|
@@ -159,7 +159,7 @@ declare enum CAREER_VERSION {
|
|
|
159
159
|
V6 = "v6",
|
|
160
160
|
V2020 = "v2020"
|
|
161
161
|
}
|
|
162
|
-
type Career = {
|
|
162
|
+
export type Career = {
|
|
163
163
|
MA: number;
|
|
164
164
|
ST: number;
|
|
165
165
|
AG: number;
|
|
@@ -177,6 +177,5 @@ type Career = {
|
|
|
177
177
|
hasSprite?: boolean;
|
|
178
178
|
version: CAREER_VERSION;
|
|
179
179
|
};
|
|
180
|
-
declare const CAREER: Record<CAREER_ID, Career>;
|
|
181
180
|
declare const getCareers: () => Record<CAREER_ID, Career>;
|
|
182
|
-
export { AVATAR, AVATAR_RARITY,
|
|
181
|
+
export { AVATAR, AVATAR_RARITY, CAREER_ID, CAREER_VERSION, getCareers, RACE };
|
package/dist/career.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// AG: Agility
|
|
5
5
|
// AV: Armour Value
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.RACE = exports.getCareers = exports.CAREER_VERSION = exports.CAREER_ID = exports.
|
|
7
|
+
exports.RACE = exports.getCareers = exports.CAREER_VERSION = exports.CAREER_ID = exports.AVATAR_RARITY = exports.AVATAR = void 0;
|
|
8
8
|
const skill_1 = require("./skill");
|
|
9
9
|
var RACE;
|
|
10
10
|
(function (RACE) {
|
|
@@ -2119,7 +2119,6 @@ const CAREER = {
|
|
|
2119
2119
|
version: CAREER_VERSION.V6,
|
|
2120
2120
|
},
|
|
2121
2121
|
};
|
|
2122
|
-
exports.CAREER = CAREER;
|
|
2123
2122
|
const getCareers = () => {
|
|
2124
2123
|
return CAREER;
|
|
2125
2124
|
};
|
package/dist/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "enefel",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "enefel",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.9.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"seedrandom": "3.0.5",
|
package/dist/package.json
CHANGED
package/dist/race.d.ts
CHANGED
|
@@ -4,61 +4,10 @@ declare const ANIMOSITY_NUMBER = 2;
|
|
|
4
4
|
declare const isPrivateRace: (race: RACE) => boolean;
|
|
5
5
|
declare const hasUnlockRace: (user: User, race: RACE) => boolean;
|
|
6
6
|
declare const hasUnlockCareer: (user: User, careerId: string) => boolean;
|
|
7
|
-
declare const getCareerFromKey: (key: CAREER_ID) =>
|
|
8
|
-
MA: number;
|
|
9
|
-
ST: number;
|
|
10
|
-
AG: number;
|
|
11
|
-
PA: number;
|
|
12
|
-
AV: number;
|
|
13
|
-
normal: string;
|
|
14
|
-
double: string;
|
|
15
|
-
normalCoach: string;
|
|
16
|
-
icons: string[];
|
|
17
|
-
skills: (import("./skill").SKILL_NAMES | [import("./skill").SKILL_NAMES, number])[];
|
|
18
|
-
avatars: AVATAR[];
|
|
19
|
-
badge: RACE;
|
|
20
|
-
range: number;
|
|
21
|
-
cost: number;
|
|
22
|
-
hasSprite?: boolean;
|
|
23
|
-
version: import("./career").CAREER_VERSION;
|
|
24
|
-
};
|
|
7
|
+
declare const getCareerFromKey: (key: CAREER_ID) => import("./career").Career;
|
|
25
8
|
declare const getCareerKeyFromPlayer: (player: Player) => CAREER_ID;
|
|
26
|
-
declare const getCareerFromPlayer: (player: Player) =>
|
|
27
|
-
|
|
28
|
-
ST: number;
|
|
29
|
-
AG: number;
|
|
30
|
-
PA: number;
|
|
31
|
-
AV: number;
|
|
32
|
-
normal: string;
|
|
33
|
-
double: string;
|
|
34
|
-
normalCoach: string;
|
|
35
|
-
icons: string[];
|
|
36
|
-
skills: (import("./skill").SKILL_NAMES | [import("./skill").SKILL_NAMES, number])[];
|
|
37
|
-
avatars: AVATAR[];
|
|
38
|
-
badge: RACE;
|
|
39
|
-
range: number;
|
|
40
|
-
cost: number;
|
|
41
|
-
hasSprite?: boolean;
|
|
42
|
-
version: import("./career").CAREER_VERSION;
|
|
43
|
-
};
|
|
44
|
-
declare const getCareerFromIcon: (nameIcon: string) => {
|
|
45
|
-
MA: number;
|
|
46
|
-
ST: number;
|
|
47
|
-
AG: number;
|
|
48
|
-
PA: number;
|
|
49
|
-
AV: number;
|
|
50
|
-
normal: string;
|
|
51
|
-
double: string;
|
|
52
|
-
normalCoach: string;
|
|
53
|
-
icons: string[];
|
|
54
|
-
skills: (import("./skill").SKILL_NAMES | [import("./skill").SKILL_NAMES, number])[];
|
|
55
|
-
avatars: AVATAR[];
|
|
56
|
-
badge: RACE;
|
|
57
|
-
range: number;
|
|
58
|
-
cost: number;
|
|
59
|
-
hasSprite?: boolean;
|
|
60
|
-
version: import("./career").CAREER_VERSION;
|
|
61
|
-
} | null;
|
|
9
|
+
declare const getCareerFromPlayer: (player: Player) => import("./career").Career;
|
|
10
|
+
declare const getCareerFromIcon: (nameIcon: string) => import("./career").Career | null;
|
|
62
11
|
declare const getPlayerAvatarDefault: (player: Player) => string | null;
|
|
63
12
|
declare const getPlayerAvatar: (player: Player) => string | null;
|
|
64
13
|
declare const getPlayerAvatarPath: (player: Player) => "tile/shop/avatar" | "tile/shop/avatar-default" | null;
|
|
@@ -96,4 +45,5 @@ declare const getPlayersByState: (players: Player[]) => {
|
|
|
96
45
|
inactives: Player[];
|
|
97
46
|
lastRetired: Player[];
|
|
98
47
|
};
|
|
99
|
-
|
|
48
|
+
declare const getRaceSpecialSkills: (race: RACE) => string[];
|
|
49
|
+
export { ANIMOSITY_NUMBER, COMPATIBILITY, GAIN_CAREER_POINT, GAIN_CAREER_POINT_FRIENDLY, getAvatarTypeFromPlayer, getCareerFromIcon, getCareerFromKey, getCareerFromPlayer, getCareerKeyFromPlayer, getCareerRanges, getCareersByRace, getPlayerAvatar, getPlayerAvatarDefault, getPlayerAvatarPath, getPlayerCompatibility, getPlayerGroup, getPlayersAvailableForPromo, getPlayersByState, getPriceCareer, getPromoCareer, getRaceCompatibility, getRaceFromCareer, getRaceFromPlayer, getRaceGroup, getRaceSpecialSkills, getTeamGroups, getTeamIncompatibleGroups, GROUP_NAME, hasUnlockCareer, hasUnlockRace, isNeutralGroup, isPlayerNeutralGroup, isPrivateRace, };
|
package/dist/race.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.isPrivateRace = exports.hasUnlockRace = exports.hasUnlockCareer = exports.GROUP_NAME = exports.getRaceGroup = exports.getRaceFromPlayer = exports.getRaceFromCareer = exports.getRaceCompatibility = exports.getPlayersByState = exports.getPlayerGroup = exports.getPlayerCompatibility = exports.getPlayerAvatarPath = exports.getPlayerAvatarDefault = exports.getPlayerAvatar = exports.getCareersByRace = exports.getCareerKeyFromPlayer = exports.getCareerFromPlayer = exports.getCareerFromKey = exports.getCareerFromIcon = exports.getAvatarTypeFromPlayer = exports.GAIN_CAREER_POINT_FRIENDLY = exports.GAIN_CAREER_POINT = exports.COMPATIBILITY = exports.ANIMOSITY_NUMBER = void 0;
|
|
6
|
+
exports.isPrivateRace = exports.hasUnlockRace = exports.hasUnlockCareer = exports.GROUP_NAME = exports.getRaceSpecialSkills = exports.getRaceGroup = exports.getRaceFromPlayer = exports.getRaceFromCareer = exports.getRaceCompatibility = exports.getPlayersByState = exports.getPlayerGroup = exports.getPlayerCompatibility = exports.getPlayerAvatarPath = exports.getPlayerAvatarDefault = exports.getPlayerAvatar = exports.getCareersByRace = exports.getCareerKeyFromPlayer = exports.getCareerFromPlayer = exports.getCareerFromKey = exports.getCareerFromIcon = exports.getAvatarTypeFromPlayer = exports.GAIN_CAREER_POINT_FRIENDLY = exports.GAIN_CAREER_POINT = exports.COMPATIBILITY = exports.ANIMOSITY_NUMBER = void 0;
|
|
7
7
|
exports.getCareerRanges = getCareerRanges;
|
|
8
8
|
exports.getPlayersAvailableForPromo = getPlayersAvailableForPromo;
|
|
9
9
|
exports.getPriceCareer = getPriceCareer;
|
|
@@ -18,6 +18,7 @@ const avatarsDefault_1 = require("./avatarsDefault");
|
|
|
18
18
|
const badge_1 = require("./badge");
|
|
19
19
|
const career_1 = require("./career");
|
|
20
20
|
const random_1 = require("./random");
|
|
21
|
+
const skill_1 = require("./skill");
|
|
21
22
|
const state_1 = require("./state");
|
|
22
23
|
const ANIMOSITY_NUMBER = 2;
|
|
23
24
|
exports.ANIMOSITY_NUMBER = ANIMOSITY_NUMBER;
|
|
@@ -353,3 +354,32 @@ const getPlayersByState = (players) => {
|
|
|
353
354
|
};
|
|
354
355
|
};
|
|
355
356
|
exports.getPlayersByState = getPlayersByState;
|
|
357
|
+
const getRaceSpecialSkills = (race) => {
|
|
358
|
+
const careers = (0, career_1.getCareers)();
|
|
359
|
+
const raceCareerIds = Object.keys(careers).filter((careerId) => careers[careerId].badge === race);
|
|
360
|
+
if (raceCareerIds.length === 0) {
|
|
361
|
+
return [];
|
|
362
|
+
}
|
|
363
|
+
// Compter la fréquence des compétences spéciales dans la race
|
|
364
|
+
const skillCount = {};
|
|
365
|
+
raceCareerIds.forEach((careerId) => {
|
|
366
|
+
const careerSkills = careers[careerId].skills;
|
|
367
|
+
careerSkills.forEach((skill) => {
|
|
368
|
+
const skillName = Array.isArray(skill) ? skill[0] : skill;
|
|
369
|
+
// Ne compter que les compétences spéciales
|
|
370
|
+
if ((0, skill_1.isSpecialSkill)(skillName)) {
|
|
371
|
+
skillCount[skillName] = (skillCount[skillName] || 0) + 1;
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
// Retourner les compétences spéciales qui apparaissent dans au moins 50% des carrières
|
|
376
|
+
// Exclure les compétences de joueur individuel (specialist, big-guy) qui ne sont pas des compétences de race
|
|
377
|
+
const threshold = Math.ceil(raceCareerIds.length * 0.5);
|
|
378
|
+
const representativeSkills = Object.entries(skillCount)
|
|
379
|
+
.filter(([_, count]) => count >= threshold)
|
|
380
|
+
.map(([skillName, _]) => skillName)
|
|
381
|
+
.filter((skillName) => skillName !== skill_1.SKILL_NAMES.SPECIALIST &&
|
|
382
|
+
skillName !== skill_1.SKILL_NAMES.BIG_GUY);
|
|
383
|
+
return representativeSkills;
|
|
384
|
+
};
|
|
385
|
+
exports.getRaceSpecialSkills = getRaceSpecialSkills;
|
package/package.json
CHANGED
package/race.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { AVATAR_DEFAULT_LIST } from "./avatarsDefault";
|
|
|
4
4
|
import { BADGE_NAMES, hasBadge } from "./badge";
|
|
5
5
|
import { AVATAR, CAREER_ID, getCareers, RACE } from "./career";
|
|
6
6
|
import { getRandomNumber } from "./random";
|
|
7
|
+
import { isSpecialSkill, SKILL_NAMES } from "./skill";
|
|
7
8
|
import { canBeSelectedByUser } from "./state";
|
|
8
9
|
import { Player, Team, User } from "./types/models";
|
|
9
10
|
|
|
@@ -373,6 +374,45 @@ const getPlayersByState = (players: Player[]) => {
|
|
|
373
374
|
),
|
|
374
375
|
};
|
|
375
376
|
};
|
|
377
|
+
const getRaceSpecialSkills = (race: RACE) => {
|
|
378
|
+
const careers = getCareers();
|
|
379
|
+
const raceCareerIds = Object.keys(careers).filter(
|
|
380
|
+
(careerId) => careers[careerId as CAREER_ID].badge === race
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
if (raceCareerIds.length === 0) {
|
|
384
|
+
return [];
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Compter la fréquence des compétences spéciales dans la race
|
|
388
|
+
const skillCount: Record<string, number> = {};
|
|
389
|
+
|
|
390
|
+
raceCareerIds.forEach((careerId) => {
|
|
391
|
+
const careerSkills = careers[careerId as CAREER_ID].skills;
|
|
392
|
+
careerSkills.forEach((skill) => {
|
|
393
|
+
const skillName = Array.isArray(skill) ? skill[0] : skill;
|
|
394
|
+
// Ne compter que les compétences spéciales
|
|
395
|
+
if (isSpecialSkill(skillName)) {
|
|
396
|
+
skillCount[skillName] = (skillCount[skillName] || 0) + 1;
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// Retourner les compétences spéciales qui apparaissent dans au moins 50% des carrières
|
|
402
|
+
// Exclure les compétences de joueur individuel (specialist, big-guy) qui ne sont pas des compétences de race
|
|
403
|
+
const threshold = Math.ceil(raceCareerIds.length * 0.5);
|
|
404
|
+
const representativeSkills = Object.entries(skillCount)
|
|
405
|
+
.filter(([_, count]) => count >= threshold)
|
|
406
|
+
.map(([skillName, _]) => skillName)
|
|
407
|
+
.filter(
|
|
408
|
+
(skillName) =>
|
|
409
|
+
skillName !== SKILL_NAMES.SPECIALIST &&
|
|
410
|
+
skillName !== SKILL_NAMES.BIG_GUY
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
return representativeSkills;
|
|
414
|
+
};
|
|
415
|
+
|
|
376
416
|
export {
|
|
377
417
|
ANIMOSITY_NUMBER,
|
|
378
418
|
COMPATIBILITY,
|
|
@@ -398,6 +438,7 @@ export {
|
|
|
398
438
|
getRaceFromCareer,
|
|
399
439
|
getRaceFromPlayer,
|
|
400
440
|
getRaceGroup,
|
|
441
|
+
getRaceSpecialSkills,
|
|
401
442
|
getTeamGroups,
|
|
402
443
|
getTeamIncompatibleGroups,
|
|
403
444
|
GROUP_NAME,
|