UNPKG

@emilecalixte/ffa-categories

Version:

Package utilitaire permettant de manipuler les catégories de la Fédération Française d'Athlétisme

1 lines 22 kB
{"version":3,"sources":["../src/index.ts","../src/utils/objectUtils.ts","../src/constants/categories.ts","../src/constants/dates.ts","../src/getApplicableCategoriesYear.ts","../src/getCategories.ts","../src/getCategory.ts","../src/isCategoryCode.ts"],"sourcesContent":["// Constants\nexport { ALL_CATEGORY_CODES, ALL_CATEGORY_NAMES } from \"./constants/categories\";\n\n// Types\nexport type { CategoryCode, CategoryList, CategoryName } from \"./types/categories\";\n\n// Functions\nexport { getApplicableCategoriesYear } from \"./getApplicableCategoriesYear\";\nexport { getCategoryList } from \"./getCategories\";\nexport { getCategory } from \"./getCategory\";\nexport { isCategoryCode } from \"./isCategoryCode\";\n","/**\n * Returns a shallow copy of an object without the specified keys\n * @param object The object to copy\n * @param keys The keys to exclude\n */\nexport function excludeKeys<TObject extends object, TKey extends keyof TObject>(\n object: TObject,\n keys: TKey[],\n): Omit<TObject, TKey> {\n const result = { ...object };\n\n for (const key of keys) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete -- `delete` is used here intentionally on a cloned object.\n delete result[key];\n }\n\n return result;\n}\n\n/**\n * Wrapper of Object.keys which infers keys type\n */\nexport function objectKeys<TObject extends object>(object: TObject): Array<keyof TObject> {\n return Object.keys(object) as Array<keyof TObject>;\n}\n","import type { CategoryListMinAge } from \"../types/categories\";\nimport { excludeKeys, objectKeys } from \"../utils/objectUtils\";\n\n/**\n * Categories that existed until 2015 (History prior to 2012 is not guaranteed)\n */\nexport const CATEGORIES_2015_AND_BEFORE = {\n EA: \"École d'Athlétisme\",\n PO: \"Poussins\",\n BE: \"Benjamins\",\n MI: \"Minimes\",\n CA: \"Cadets\",\n JU: \"Juniors\",\n ES: \"Espoirs\",\n SE: \"Seniors\",\n VE: \"Vétérans\",\n} as const;\n\nexport const CATEGORIES_2015_AND_BEFORE_MIN_AGE: CategoryListMinAge<typeof CATEGORIES_2015_AND_BEFORE> = {\n EA: 0,\n PO: 10,\n BE: 12,\n MI: 14,\n CA: 16,\n JU: 18,\n ES: 20,\n SE: 23,\n VE: 40,\n};\n\n/**\n * Categories that existed until 2015 with detailed \"Vétérans\" categories\n */\nexport const DETAILED_CATEGORIES_2015_AND_BEFORE = {\n ...excludeKeys(CATEGORIES_2015_AND_BEFORE, [\"VE\"]),\n V1: \"Vétérans 1\",\n V2: \"Vétérans 2\",\n V3: \"Vétérans 3\",\n V4: \"Vétérans 4\",\n} as const;\n\nexport const DETAILED_CATEGORIES_2015_AND_BEFORE_MIN_AGE: CategoryListMinAge<\n typeof DETAILED_CATEGORIES_2015_AND_BEFORE\n> = {\n ...excludeKeys(CATEGORIES_2015_AND_BEFORE_MIN_AGE, [\"VE\"]),\n V1: 40,\n V2: 50,\n V3: 60,\n V4: 70,\n};\n\n/**\n * Categories that existed from 2016 to 2019\n */\nexport const CATEGORIES_2016_TO_2019 = {\n BB: \"Baby Athlé\",\n ...CATEGORIES_2015_AND_BEFORE,\n VE: \"Masters\",\n} as const;\n\nexport const CATEGORIES_2016_TO_2019_MIN_AGE: CategoryListMinAge<typeof CATEGORIES_2016_TO_2019> = {\n BB: 0,\n ...excludeKeys(CATEGORIES_2015_AND_BEFORE_MIN_AGE, [\"EA\"]),\n EA: 7,\n};\n\n/**\n * Categories that existed from 2016 to 2019 with detailed \"Masters\" categories\n */\nexport const DETAILED_CATEGORIES_2016_TO_2019 = {\n ...excludeKeys(CATEGORIES_2016_TO_2019, [\"VE\"]),\n V1: \"Masters 1\",\n V2: \"Masters 2\",\n V3: \"Masters 3\",\n V4: \"Masters 4\",\n V5: \"Masters 5\",\n} as const;\n\nexport const DETAILED_CATEGORIES_2016_TO_2019_MIN_AGE: CategoryListMinAge<typeof DETAILED_CATEGORIES_2016_TO_2019> = {\n ...excludeKeys(CATEGORIES_2016_TO_2019_MIN_AGE, [\"VE\"]),\n V1: 40,\n V2: 50,\n V3: 60,\n V4: 70,\n V5: 80,\n};\n\n/**\n * Categories that existed from 2020 to 2022 (equal to those of 2016 to 2019 because only the detailed “Masters” categories have changed in 2020)\n */\nexport const CATEGORIES_2020_TO_2022 = CATEGORIES_2016_TO_2019;\n\nexport const CATEGORIES_2020_TO_2022_MIN_AGE: CategoryListMinAge<typeof CATEGORIES_2020_TO_2022> = {\n ...excludeKeys(CATEGORIES_2016_TO_2019_MIN_AGE, [\"VE\"]),\n VE: 35,\n};\n\nconst DETAILED_MASTERS_CATEGORIES_2020_AND_AFTER = {\n M0: \"Masters 0\",\n M1: \"Masters 1\",\n M2: \"Masters 2\",\n M3: \"Masters 3\",\n M4: \"Masters 4\",\n M5: \"Masters 5\",\n M6: \"Masters 6\",\n M7: \"Masters 7\",\n M8: \"Masters 8\",\n M9: \"Masters 9\",\n M10: \"Masters 10\",\n} as const;\n\n/**\n * Categories that existed from 2020 to 2022 with detailed \"Masters\" categories\n */\nexport const DETAILED_CATEGORIES_2020_TO_2022 = {\n ...excludeKeys(CATEGORIES_2020_TO_2022, [\"VE\"]),\n ...DETAILED_MASTERS_CATEGORIES_2020_AND_AFTER,\n} as const;\n\nexport const DETAILED_CATEGORIES_2020_TO_2022_MIN_AGE: CategoryListMinAge<typeof DETAILED_CATEGORIES_2020_TO_2022> = {\n ...excludeKeys(CATEGORIES_2020_TO_2022_MIN_AGE, [\"VE\"]),\n M0: 35,\n M1: 40,\n M2: 45,\n M3: 50,\n M4: 55,\n M5: 60,\n M6: 65,\n M7: 70,\n M8: 75,\n M9: 80,\n M10: 85,\n};\n\n/**\n * Categories that existed from 2023 to 2024\n */\nexport const CATEGORIES_2023_TO_2024 = {\n ...CATEGORIES_2020_TO_2022,\n EA: \"Éveil Athlétique\",\n} as const;\n\n/**\n * Equal to 2020-2022, only EA name changed\n */\nexport const CATEGORIES_2023_TO_2024_MIN_AGE: CategoryListMinAge<typeof CATEGORIES_2023_TO_2024> =\n CATEGORIES_2020_TO_2022_MIN_AGE;\n\n/**\n * Categories that existed from 2023 to 2024 with detailed \"Masters\" categories\n */\nexport const DETAILED_CATEGORIES_2023_TO_2024 = {\n ...excludeKeys(CATEGORIES_2023_TO_2024, [\"VE\"]),\n ...DETAILED_MASTERS_CATEGORIES_2020_AND_AFTER,\n} as const;\n\n/**\n * Equal to 2020-2022, only EA name changed\n */\nexport const DETAILED_CATEGORIES_2023_TO_2024_MIN_AGE: CategoryListMinAge<typeof DETAILED_CATEGORIES_2023_TO_2024> =\n DETAILED_CATEGORIES_2020_TO_2022_MIN_AGE;\n\n/**\n * Existing categories since 2025\n */\nexport const CATEGORIES_2025_AND_AFTER = {\n ...excludeKeys(CATEGORIES_2023_TO_2024, [\"VE\"]),\n MA: \"Masters\",\n} as const;\n\nexport const CATEGORIES_2025_AND_AFTER_MIN_AGE: CategoryListMinAge<typeof CATEGORIES_2025_AND_AFTER> = {\n ...excludeKeys(CATEGORIES_2023_TO_2024_MIN_AGE, [\"VE\"]),\n MA: CATEGORIES_2023_TO_2024_MIN_AGE.VE,\n};\n\n/**\n * Existing categories since 2025 with detailed \"Masters\" categories\n */\nexport const DETAILED_CATEGORIES_2025_AND_AFTER = {\n ...excludeKeys(CATEGORIES_2025_AND_AFTER, [\"MA\"]),\n ...DETAILED_MASTERS_CATEGORIES_2020_AND_AFTER,\n} as const;\n\n/**\n * Equal to 2023-2024, only VE became MA but it's not in this list\n */\nexport const DETAILED_CATEGORIES_2025_AND_AFTER_MIN_AGE: CategoryListMinAge<typeof DETAILED_CATEGORIES_2025_AND_AFTER> =\n DETAILED_CATEGORIES_2023_TO_2024_MIN_AGE;\n\n/**\n * All existing category codes\n */\nexport const ALL_CATEGORY_CODES = objectKeys({\n ...CATEGORIES_2015_AND_BEFORE,\n ...DETAILED_CATEGORIES_2015_AND_BEFORE,\n ...CATEGORIES_2016_TO_2019,\n ...DETAILED_CATEGORIES_2016_TO_2019,\n ...CATEGORIES_2020_TO_2022,\n ...DETAILED_CATEGORIES_2020_TO_2022,\n ...CATEGORIES_2023_TO_2024,\n ...DETAILED_CATEGORIES_2023_TO_2024,\n ...CATEGORIES_2025_AND_AFTER,\n ...DETAILED_CATEGORIES_2025_AND_AFTER,\n});\n\n/**\n * All existing category names\n */\nexport const ALL_CATEGORY_NAMES = [\n ...Object.values(CATEGORIES_2015_AND_BEFORE),\n ...Object.values(DETAILED_CATEGORIES_2015_AND_BEFORE),\n ...Object.values(CATEGORIES_2016_TO_2019),\n ...Object.values(DETAILED_CATEGORIES_2016_TO_2019),\n ...Object.values(CATEGORIES_2020_TO_2022),\n ...Object.values(DETAILED_CATEGORIES_2020_TO_2022),\n ...Object.values(CATEGORIES_2023_TO_2024),\n ...Object.values(DETAILED_CATEGORIES_2023_TO_2024),\n ...Object.values(CATEGORIES_2025_AND_AFTER),\n ...Object.values(DETAILED_CATEGORIES_2025_AND_AFTER),\n];\n","export const DATE_MONTH_SEPTEMBER = 8;\nexport const DATE_MONTH_NOVEMBER = 10;\n","import { DATE_MONTH_NOVEMBER, DATE_MONTH_SEPTEMBER } from \"./constants/dates\";\n\n/**\n * Returns the year of the categories applicable at the date provided\n *\n * Over the years, the day and month on which the categories change has evolved\n * - Until 2012, the categories changed every January 1st\n * - Between 2013 and 2021, the categories changed every November 1st: from November 1 of year N, the categories of year N+1 are applied until October 31 of year N+1, and so on\n * - Since 2022, the categories changed every September 1st: from September 1 of year N, the categories of year N+1 are applied until August 31 of year N+1, and so on\n *\n * @param date - The date for which the categories' year should be retrieved\n * @returns The corresponding year\n *\n * @example\n * ```ts\n * getApplicableCategoriesYear(new Date(\"2000-01-01\")) // Returns 2000\n * getApplicableCategoriesYear(new Date(\"2012-12-31\")) // Returns 2012\n * getApplicableCategoriesYear(new Date(\"2013-10-31\")) // Returns 2013\n * getApplicableCategoriesYear(new Date(\"2013-11-01\")) // Returns 2014\n * getApplicableCategoriesYear(new Date(\"2014-10-31\")) // Returns 2014\n * getApplicableCategoriesYear(new Date(\"2014-11-01\")) // Returns 2015\n * getApplicableCategoriesYear(new Date(\"2022-08-31\")) // Returns 2022\n * getApplicableCategoriesYear(new Date(\"2022-09-01\")) // Returns 2023\n * getApplicableCategoriesYear(new Date(\"2023-08-31\")) // Returns 2023\n * getApplicableCategoriesYear(new Date(\"2023-09-01\")) // Returns 2024\n * ```\n */\nexport function getApplicableCategoriesYear(date: Date): number {\n const time = date.getTime();\n const year = date.getFullYear();\n\n if (time >= new Date(\"2022-09-01T00:00:00\").getTime()) {\n // Since September 1st 2022, categories change on September 1st\n return date.getMonth() >= DATE_MONTH_SEPTEMBER ? year + 1 : year;\n }\n\n if (time >= new Date(\"2013-11-01T00:00:00\").getTime()) {\n // Between November 1st 2013 and August 31 2022, categories change on November 1st\n return date.getMonth() >= DATE_MONTH_NOVEMBER ? year + 1 : year;\n }\n\n // Before 2013, categories change on January 1st\n return year;\n}\n","import {\n CATEGORIES_2015_AND_BEFORE,\n CATEGORIES_2015_AND_BEFORE_MIN_AGE,\n CATEGORIES_2016_TO_2019,\n CATEGORIES_2016_TO_2019_MIN_AGE,\n CATEGORIES_2020_TO_2022,\n CATEGORIES_2020_TO_2022_MIN_AGE,\n CATEGORIES_2023_TO_2024,\n CATEGORIES_2023_TO_2024_MIN_AGE,\n CATEGORIES_2025_AND_AFTER,\n CATEGORIES_2025_AND_AFTER_MIN_AGE,\n DETAILED_CATEGORIES_2015_AND_BEFORE,\n DETAILED_CATEGORIES_2015_AND_BEFORE_MIN_AGE,\n DETAILED_CATEGORIES_2016_TO_2019,\n DETAILED_CATEGORIES_2016_TO_2019_MIN_AGE,\n DETAILED_CATEGORIES_2020_TO_2022,\n DETAILED_CATEGORIES_2020_TO_2022_MIN_AGE,\n DETAILED_CATEGORIES_2023_TO_2024,\n DETAILED_CATEGORIES_2023_TO_2024_MIN_AGE,\n DETAILED_CATEGORIES_2025_AND_AFTER,\n DETAILED_CATEGORIES_2025_AND_AFTER_MIN_AGE,\n} from \"./constants/categories\";\nimport type { CategoryList, CategoryListMinAge } from \"./types/categories\";\n\nfunction getCategoryLists(date: Date): [CategoryList, CategoryList, CategoryListMinAge, CategoryListMinAge] {\n const time = date.getTime();\n\n if (time >= new Date(\"2024-09-01T00:00:00\").getTime()) {\n return [\n CATEGORIES_2025_AND_AFTER,\n DETAILED_CATEGORIES_2025_AND_AFTER,\n CATEGORIES_2025_AND_AFTER_MIN_AGE,\n DETAILED_CATEGORIES_2025_AND_AFTER_MIN_AGE,\n ];\n }\n\n if (time >= new Date(\"2022-09-01T00:00:00\").getTime()) {\n return [\n CATEGORIES_2023_TO_2024,\n DETAILED_CATEGORIES_2023_TO_2024,\n CATEGORIES_2023_TO_2024_MIN_AGE,\n DETAILED_CATEGORIES_2023_TO_2024_MIN_AGE,\n ];\n }\n\n if (time >= new Date(\"2019-11-01T00:00:00\").getTime()) {\n return [\n CATEGORIES_2020_TO_2022,\n DETAILED_CATEGORIES_2020_TO_2022,\n CATEGORIES_2020_TO_2022_MIN_AGE,\n DETAILED_CATEGORIES_2020_TO_2022_MIN_AGE,\n ];\n }\n\n if (time >= new Date(\"2015-11-01T00:00:00\").getTime()) {\n return [\n CATEGORIES_2016_TO_2019,\n DETAILED_CATEGORIES_2016_TO_2019,\n CATEGORIES_2016_TO_2019_MIN_AGE,\n DETAILED_CATEGORIES_2016_TO_2019_MIN_AGE,\n ];\n }\n\n return [\n CATEGORIES_2015_AND_BEFORE,\n DETAILED_CATEGORIES_2015_AND_BEFORE,\n CATEGORIES_2015_AND_BEFORE_MIN_AGE,\n DETAILED_CATEGORIES_2015_AND_BEFORE_MIN_AGE,\n ];\n}\n\n/**\n * Returns list of categories existing at a given date\n * @param date - The date for which categories should be retrieved. Default: current date\n * @param detailed - Whether or not to return detailed list (with detailed \"Vétérans\" or \"Masters\" categories). Default: true\n * @returns The category list\n */\nexport function getCategoryList(date: Date = new Date(), detailed = true): CategoryList {\n return getCategoryLists(date)[detailed ? 1 : 0];\n}\n\nexport function getCategoryMinAges(date: Date, detailed = true): CategoryListMinAge {\n return getCategoryLists(date)[detailed ? 3 : 2];\n}\n","import { getApplicableCategoriesYear } from \"./getApplicableCategoriesYear\";\nimport { getCategoryList, getCategoryMinAges } from \"./getCategories\";\nimport type { CategoryCode, CategoryData, CategoryList } from \"./types/categories\";\n\nfunction getCategoryDataFromCode(code: CategoryCode, categories: CategoryList): CategoryData {\n const name = categories[code];\n\n if (name === undefined) {\n throw new Error(`No category found with code ${code}`);\n }\n\n return {\n code,\n name,\n };\n}\n\nfunction getCategoryFromAge(date: Date, detailed: boolean, age: number): CategoryData {\n function rtrn(age: number, categoryCode: CategoryCode | null, categories: CategoryList): CategoryData {\n if (categoryCode === null) {\n throw new Error(`No category code found for age ${age}`);\n }\n\n return getCategoryDataFromCode(categoryCode, categories);\n }\n\n if (age < 0) {\n age = 0;\n }\n\n const categories = getCategoryList(date, detailed);\n const minAges = getCategoryMinAges(date, detailed);\n\n let currentCategoryCode: string | null = null;\n for (const [categoryCode, minAge] of Object.entries(minAges).sort(([, minAge1], [, minAge2]) => minAge1 - minAge2)) {\n if (age < minAge) {\n return rtrn(age, currentCategoryCode as CategoryCode | null, categories);\n }\n\n currentCategoryCode = categoryCode;\n }\n\n return rtrn(age, currentCategoryCode as CategoryCode | null, categories);\n}\n\ninterface GetCategoryOptions {\n /**\n * The date for which the category code should be determined\n * Default: current date\n */\n date: Date;\n\n /**\n * Whether or not to return a detailed code when applicable (e.g. for category Master 2, return `\"M2\"` if `true`, `\"MA\"` if `false`).\n * Default: `true`\n */\n detailed: boolean;\n}\n\n/**\n * Computes the category code corresponding to the birth year provided on the date provided, or on the current date if no date is provided\n * @param birthYear - The birth year for which the category code should be determined\n * @param options - Additional options\n * @returns The category corresponding to the birth year and date provided\n *\n * @example\n * ```ts\n * getCategory(2002, { date: new Date(\"2021-10-29\") }); // Returns { code: \"JU\", name: \"Juniors\" }\n * getCategory(2002, { date: new Date(\"2021-11-01\") }); // Returns { code: \"ES\", name: \"Espoirs\" }\n * getCategory(1970, { date: new Date(\"2025-01-01\") }); // Returns { code: \"M4\", name: \"Masters 4\" }\n * getCategory(1970, { date: new Date(\"2025-01-01\"), detailed: false }); // Returns { code: \"MA\", name: \"Masters\" }\n * getCategory(1970, { date: new Date(\"2015-01-01\") }); // Returns { code: \"V1\", name: \"Vétérans 1\" }\n * getCategory(1970, { date: new Date(\"2015-01-01\"), detailed: false }); // Returns { code: \"VE\", name: \"Vétérans\" }\n * ```\n */\nexport function getCategory(birthYear: number, options: Partial<GetCategoryOptions> = {}): CategoryData {\n const date = options.date ?? new Date();\n const detailed = options.detailed ?? true;\n\n /**\n * This is not the real age, but the age calculated based on the categories applicable on the date provided.\n * @see getApplicableCategoriesYear\n */\n const applicableAge = getApplicableCategoriesYear(date) - birthYear;\n\n return getCategoryFromAge(date, detailed, applicableAge);\n}\n","import { ALL_CATEGORY_CODES } from \"./constants/categories\";\nimport type { CategoryCode } from \"./types/categories\";\n\n/**\n * @param value The value to be checked\n * @returns True if value is a valid category code, false otherwise\n *\n * @example\n * ```ts\n * isCategoryCode(\"BB\") // Returns true\n * isCategoryCode(\"SE\") // Returns true\n * isCategoryCode(\"VE\") // Returns true\n * isCategoryCode(\"V2\") // Returns true\n * isCategoryCode(\"MA\") // Returns true\n * isCategoryCode(\"M10\") // Returns true\n * isCategoryCode(\"IN\") // Returns false\n * isCategoryCode(\"any invalid string\") // Returns false\n * ```\n */\nexport function isCategoryCode(value: string): value is CategoryCode {\n return (ALL_CATEGORY_CODES as string[]).includes(value);\n}\n"],"mappings":"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","names":["age","categories"]}