placementt-core 1.400.1118 → 1.400.1120

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.
@@ -1,4 +1,18 @@
1
1
  import { z } from "zod";
2
+ /**
3
+ * Contracts for the `he` backend module
4
+ * (`Placementt-Backend/functions/src/heImport.ts`).
5
+ *
6
+ * Admin-only controls for the weekly mirror of the HESA Discover Uni dataset
7
+ * into `heCourses` / `heProviders`. The status document (`heMeta/status`) is
8
+ * the source of truth the admin card reads live, so the responses only echo
9
+ * enough to confirm the call landed - an import can outlive the client's
10
+ * callable deadline and the card still resolves.
11
+ */
12
+ /** Every enrichment source, in the order the admin card lists them. The
13
+ * orchestrator runs "areas" first (the city sources key on its output) and
14
+ * "finalise" last. */
15
+ export declare const HE_ENRICHMENT_SOURCES: readonly ["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation", "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"];
2
16
  export declare const heCallables: {
3
17
  /** Run a full import now. `storagePath` names a zip already uploaded to
4
18
  * Cloud Storage (`heImports/<file>.zip`) to use instead of the URL in
@@ -79,6 +93,33 @@ export declare const heCallables: {
79
93
  };
80
94
  }>;
81
95
  };
96
+ /**
97
+ * Run the university enrichment: one status entry per source in
98
+ * `heMeta/enrichmentStatus`, one Cloud Task per source, then a finalise
99
+ * task that computes provider / area percentiles and reapplies course
100
+ * percentiles. `sources` limits the run to those sources (a retry of the
101
+ * ones that failed); omitted, every source runs. Returns as soon as the
102
+ * tasks are queued; the admin card follows the status document.
103
+ */
104
+ "he-runEnrichment": {
105
+ request: z.ZodObject<{
106
+ sources: z.ZodOptional<z.ZodArray<z.ZodEnum<["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation", "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"]>, "many">>;
107
+ }, "strip", z.ZodTypeAny, {
108
+ sources?: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[] | undefined;
109
+ }, {
110
+ sources?: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[] | undefined;
111
+ }>;
112
+ response: z.ZodObject<{
113
+ runId: z.ZodString;
114
+ queued: z.ZodArray<z.ZodEnum<["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation", "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"]>, "many">;
115
+ }, "strip", z.ZodTypeAny, {
116
+ runId: string;
117
+ queued: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[];
118
+ }, {
119
+ runId: string;
120
+ queued: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[];
121
+ }>;
122
+ };
82
123
  /** Clear a stuck "running" state. The mirror and its manifest are left
83
124
  * alone. */
84
125
  "he-resetRun": {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.heCallables = void 0;
3
+ exports.heCallables = exports.HE_ENRICHMENT_SOURCES = void 0;
4
4
  const zod_1 = require("zod");
5
5
  /**
6
6
  * Contracts for the `he` backend module
@@ -12,6 +12,11 @@ const zod_1 = require("zod");
12
12
  * enough to confirm the call landed - an import can outlive the client's
13
13
  * callable deadline and the card still resolves.
14
14
  */
15
+ /** Every enrichment source, in the order the admin card lists them. The
16
+ * orchestrator runs "areas" first (the city sources key on its output) and
17
+ * "finalise" last. */
18
+ exports.HE_ENRICHMENT_SOURCES = ["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation",
19
+ "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"];
15
20
  const importCounts = zod_1.z.object({
16
21
  coursesAssembled: zod_1.z.number(),
17
22
  coursesWritten: zod_1.z.number(),
@@ -39,6 +44,23 @@ exports.heCallables = {
39
44
  counts: importCounts,
40
45
  }),
41
46
  },
47
+ /**
48
+ * Run the university enrichment: one status entry per source in
49
+ * `heMeta/enrichmentStatus`, one Cloud Task per source, then a finalise
50
+ * task that computes provider / area percentiles and reapplies course
51
+ * percentiles. `sources` limits the run to those sources (a retry of the
52
+ * ones that failed); omitted, every source runs. Returns as soon as the
53
+ * tasks are queued; the admin card follows the status document.
54
+ */
55
+ "he-runEnrichment": {
56
+ request: zod_1.z.object({
57
+ sources: zod_1.z.array(zod_1.z.enum(exports.HE_ENRICHMENT_SOURCES)).optional(),
58
+ }),
59
+ response: zod_1.z.object({
60
+ runId: zod_1.z.string(),
61
+ queued: zod_1.z.array(zod_1.z.enum(exports.HE_ENRICHMENT_SOURCES)),
62
+ }),
63
+ },
42
64
  /** Clear a stuck "running" state. The mirror and its manifest are left
43
65
  * alone. */
44
66
  "he-resetRun": {
@@ -1 +1 @@
1
- {"version":3,"file":"he.js","sourceRoot":"","sources":["../../src/callables/he.ts"],"names":[],"mappings":";;;AAAA,6BAAsB;AAGtB;;;;;;;;;GASG;AAEH,MAAM,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1B,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE;IAC5B,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE;IAC1B,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE;IAC5B,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE;IAC1B,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE;IAC5B,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE;CACjC,CAAC,CAAC;AAEU,QAAA,WAAW,GAAG;IACvB;;;4BAGwB;IACxB,cAAc,EAAE;QACZ,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC;YACd,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SACrC,CAAC;QACF,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;YACjB,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE;YAC1B,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;gBACb,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBAChC,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;aAClB,CAAC;YACF,MAAM,EAAE,YAAY;SACvB,CAAC;KACL;IACD;gBACY;IACZ,aAAa,EAAE;QACX,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,EAAE,EAAE,OAAC,CAAC,OAAO,CAAC,IAAI,CAAC;SACtB,CAAC;KACL;CACoB,CAAC"}
1
+ {"version":3,"file":"he.js","sourceRoot":"","sources":["../../src/callables/he.ts"],"names":[],"mappings":";;;AAAA,6BAAsB;AAGtB;;;;;;;;;GASG;AAEH;;sBAEsB;AACT,QAAA,qBAAqB,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,uBAAuB;IAC5G,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,CAAU,CAAC;AAEzG,MAAM,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1B,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE;IAC5B,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE;IAC1B,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE;IAC5B,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE;IAC1B,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE;IAC5B,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE;CACjC,CAAC,CAAC;AAEU,QAAA,WAAW,GAAG;IACvB;;;4BAGwB;IACxB,cAAc,EAAE;QACZ,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC;YACd,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SACrC,CAAC;QACF,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;YACjB,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE;YAC1B,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC;gBACb,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBAChC,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE;aAClB,CAAC;YACF,MAAM,EAAE,YAAY;SACvB,CAAC;KACL;IACD;;;;;;;OAOG;IACH,kBAAkB,EAAE;QAChB,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC;YACd,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,IAAI,CAAC,6BAAqB,CAAC,CAAC,CAAC,QAAQ,EAAE;SAC7D,CAAC;QACF,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;YACjB,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,IAAI,CAAC,6BAAqB,CAAC,CAAC;SACjD,CAAC;KACL;IACD;gBACY;IACZ,aAAa,EAAE;QACX,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,EAAE,EAAE,OAAC,CAAC,OAAO,CAAC,IAAI,CAAC;SACtB,CAAC;KACL;CACoB,CAAC"}
@@ -618,6 +618,25 @@ export declare const allCallables: {
618
618
  };
619
619
  }>;
620
620
  };
621
+ "he-runEnrichment": {
622
+ request: z.ZodObject<{
623
+ sources: z.ZodOptional<z.ZodArray<z.ZodEnum<["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation", "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"]>, "many">>;
624
+ }, "strip", z.ZodTypeAny, {
625
+ sources?: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[] | undefined;
626
+ }, {
627
+ sources?: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[] | undefined;
628
+ }>;
629
+ response: z.ZodObject<{
630
+ runId: z.ZodString;
631
+ queued: z.ZodArray<z.ZodEnum<["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation", "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"]>, "many">;
632
+ }, "strip", z.ZodTypeAny, {
633
+ runId: string;
634
+ queued: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[];
635
+ }, {
636
+ runId: string;
637
+ queued: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[];
638
+ }>;
639
+ };
621
640
  "he-resetRun": {
622
641
  request: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
623
642
  response: z.ZodObject<{
@@ -2354,6 +2373,25 @@ export declare const callableGroups: {
2354
2373
  };
2355
2374
  }>;
2356
2375
  };
2376
+ "he-runEnrichment": {
2377
+ request: z.ZodObject<{
2378
+ sources: z.ZodOptional<z.ZodArray<z.ZodEnum<["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation", "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"]>, "many">>;
2379
+ }, "strip", z.ZodTypeAny, {
2380
+ sources?: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[] | undefined;
2381
+ }, {
2382
+ sources?: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[] | undefined;
2383
+ }>;
2384
+ response: z.ZodObject<{
2385
+ runId: z.ZodString;
2386
+ queued: z.ZodArray<z.ZodEnum<["areas", "hesaSsr", "hesaFinance", "hesaStudents", "wideningParticipation", "openAlex", "rent", "crime", "localJobs", "weather", "amenities", "population", "finalise"]>, "many">;
2387
+ }, "strip", z.ZodTypeAny, {
2388
+ runId: string;
2389
+ queued: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[];
2390
+ }, {
2391
+ runId: string;
2392
+ queued: ("areas" | "hesaSsr" | "hesaFinance" | "hesaStudents" | "wideningParticipation" | "openAlex" | "rent" | "crime" | "localJobs" | "weather" | "amenities" | "population" | "finalise")[];
2393
+ }>;
2394
+ };
2357
2395
  "he-resetRun": {
2358
2396
  request: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
2359
2397
  response: z.ZodObject<{
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Lookup tables joining Discover Uni courses to the other HE sources.
3
+ *
4
+ * A course carries CAH subject codes (Common Aggregation Hierarchy, e.g.
5
+ * "CAH10-01-02"). The HESA finance and staff tables are published by cost
6
+ * centre instead, so each CAH code is mapped to the cost centre that teaches
7
+ * it, most specific match first: a level-3 code, then its level-2 parent
8
+ * ("CAH10-01"), then its level-1 parent ("CAH10").
9
+ *
10
+ * The CAH -> cost centre table follows HESA's own CAH/cost-centre guidance at
11
+ * the grain a student would recognise. It is deliberately coarse: a cost
12
+ * centre is a budget line, not a course, so any mapping is an approximation
13
+ * and every surface says the figure is for the subject area at that
14
+ * university.
15
+ */
16
+ /** HESA cost centres (2019/20 onward) by code. */
17
+ export declare const HESA_COST_CENTRES: {
18
+ [code: string]: string;
19
+ };
20
+ /**
21
+ * CAH code (level 1, 2 or 3) -> HESA cost centre. Looked up most specific
22
+ * first by `costCentreForCah`. CAH23 (combined and general studies) has no
23
+ * cost centre, so courses under it carry no subject stats.
24
+ */
25
+ export declare const CAH_TO_COST_CENTRE: {
26
+ [cah: string]: string;
27
+ };
28
+ /**
29
+ * The CAH level-1, level-2 and level-3 codes of a subject, most specific
30
+ * first. A malformed code yields just itself.
31
+ *
32
+ * @param {string} cah a CAH code at any level, e.g. "CAH10-01-02".
33
+ * @return {string[]} e.g. ["CAH10-01-02", "CAH10-01", "CAH10"].
34
+ */
35
+ export declare function cahAncestors(cah: string): string[];
36
+ /**
37
+ * The HESA cost centre a CAH subject is taught under, most specific mapping
38
+ * first.
39
+ *
40
+ * @param {string|undefined} cah a CAH code at any level.
41
+ * @return {string|undefined} the cost centre code, or undefined when none
42
+ * applies (combined studies, or an unknown code).
43
+ */
44
+ export declare function costCentreForCah(cah: string | undefined): string | undefined;
45
+ /**
46
+ * BRES broad industrial groups, as Nomis labels them, keyed by a stable id.
47
+ * The ids are what `HeArea.jobsBySector` and the `jobs_<id>` percentile keys
48
+ * use.
49
+ */
50
+ export declare const BRES_SECTORS: {
51
+ [id: string]: string;
52
+ };
53
+ /**
54
+ * Resolve a Nomis BRES industry label to its sector id. Nomis prefixes the
55
+ * labels with a number and suffixes the SIC section letters ("8 : Transport
56
+ * & storage (inc postal) (H)"), and the edition may swap "&" for "and", so
57
+ * the match ignores all three. Only a trailing group of section letters is
58
+ * dropped, so "(inc postal)" still counts.
59
+ *
60
+ * @param {string} label the label as it appears in the CSV.
61
+ * @return {string|undefined} the sector id, or undefined.
62
+ */
63
+ export declare function bresSectorForLabel(label: string): string | undefined;
64
+ /**
65
+ * Careers library category -> the BRES sectors its jobs mostly sit in, so
66
+ * "jobs in the sector you're interested in near this university" can be
67
+ * scored from the student's interests.
68
+ */
69
+ export declare const CAREER_CATEGORY_SECTORS: {
70
+ [category: string]: string[];
71
+ };
72
+ /**
73
+ * The BRES sectors for a set of career interest categories, de-duplicated in
74
+ * the order the categories were given.
75
+ *
76
+ * @param {string[]} categories careers library categories.
77
+ * @return {string[]} sector ids.
78
+ */
79
+ export declare function sectorsForCategories(categories: string[]): string[];
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ /**
3
+ * Lookup tables joining Discover Uni courses to the other HE sources.
4
+ *
5
+ * A course carries CAH subject codes (Common Aggregation Hierarchy, e.g.
6
+ * "CAH10-01-02"). The HESA finance and staff tables are published by cost
7
+ * centre instead, so each CAH code is mapped to the cost centre that teaches
8
+ * it, most specific match first: a level-3 code, then its level-2 parent
9
+ * ("CAH10-01"), then its level-1 parent ("CAH10").
10
+ *
11
+ * The CAH -> cost centre table follows HESA's own CAH/cost-centre guidance at
12
+ * the grain a student would recognise. It is deliberately coarse: a cost
13
+ * centre is a budget line, not a course, so any mapping is an approximation
14
+ * and every surface says the figure is for the subject area at that
15
+ * university.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.CAREER_CATEGORY_SECTORS = exports.BRES_SECTORS = exports.CAH_TO_COST_CENTRE = exports.HESA_COST_CENTRES = void 0;
19
+ exports.cahAncestors = cahAncestors;
20
+ exports.costCentreForCah = costCentreForCah;
21
+ exports.bresSectorForLabel = bresSectorForLabel;
22
+ exports.sectorsForCategories = sectorsForCategories;
23
+ /** HESA cost centres (2019/20 onward) by code. */
24
+ exports.HESA_COST_CENTRES = {
25
+ "101": "Clinical medicine",
26
+ "102": "Clinical dentistry",
27
+ "103": "Nursing and allied health professions",
28
+ "104": "Psychology and behavioural sciences",
29
+ "105": "Health and community studies",
30
+ "106": "Anatomy and physiology",
31
+ "107": "Pharmacy and pharmacology",
32
+ "108": "Sports science and leisure studies",
33
+ "109": "Veterinary science",
34
+ "110": "Agriculture, forestry and food science",
35
+ "111": "Earth, marine and environmental sciences",
36
+ "112": "Biosciences",
37
+ "113": "Chemistry",
38
+ "114": "Physics",
39
+ "115": "General engineering",
40
+ "116": "Chemical engineering",
41
+ "117": "Mineral, metallurgy and materials engineering",
42
+ "118": "Civil engineering",
43
+ "119": "Electrical, electronic and computer engineering",
44
+ "120": "Mechanical, aero and production engineering",
45
+ "121": "IT, systems sciences and computer software engineering",
46
+ "122": "Mathematics",
47
+ "123": "Architecture, built environment and planning",
48
+ "124": "Geography and environmental studies",
49
+ "125": "Area studies",
50
+ "126": "Archaeology",
51
+ "127": "Anthropology and development studies",
52
+ "128": "Politics and international studies",
53
+ "129": "Economics and econometrics",
54
+ "130": "Law",
55
+ "131": "Social work and social policy",
56
+ "132": "Sociology",
57
+ "133": "Business and management studies",
58
+ "134": "Catering and hospitality management",
59
+ "135": "Education",
60
+ "136": "Continuing education",
61
+ "137": "Modern languages",
62
+ "138": "English language and literature",
63
+ "139": "History",
64
+ "140": "Classics",
65
+ "141": "Philosophy",
66
+ "142": "Theology and religious studies",
67
+ "143": "Art and design",
68
+ "144": "Music, dance, drama and performing arts",
69
+ "145": "Media studies",
70
+ };
71
+ /**
72
+ * CAH code (level 1, 2 or 3) -> HESA cost centre. Looked up most specific
73
+ * first by `costCentreForCah`. CAH23 (combined and general studies) has no
74
+ * cost centre, so courses under it carry no subject stats.
75
+ */
76
+ exports.CAH_TO_COST_CENTRE = {
77
+ // Medicine and dentistry
78
+ "CAH01": "101",
79
+ "CAH01-01-04": "102",
80
+ // Subjects allied to medicine
81
+ "CAH02": "103",
82
+ "CAH02-01": "107",
83
+ "CAH02-02": "106",
84
+ // Biological and sport sciences
85
+ "CAH03": "112",
86
+ "CAH03-02": "108",
87
+ // Psychology
88
+ "CAH04": "104",
89
+ // Veterinary sciences
90
+ "CAH05": "109",
91
+ // Agriculture, food and related studies
92
+ "CAH06": "110",
93
+ // Physical sciences
94
+ "CAH07": "114",
95
+ "CAH07-01": "114",
96
+ "CAH07-02": "113",
97
+ // Mathematical sciences
98
+ "CAH09": "122",
99
+ // Engineering and technology
100
+ "CAH10": "115",
101
+ "CAH10-01-01": "115",
102
+ "CAH10-01-02": "120",
103
+ "CAH10-01-03": "120",
104
+ "CAH10-01-04": "120",
105
+ "CAH10-01-05": "120",
106
+ "CAH10-01-06": "115",
107
+ "CAH10-01-07": "118",
108
+ "CAH10-01-08": "119",
109
+ "CAH10-01-09": "116",
110
+ "CAH10-03": "117",
111
+ // Computing
112
+ "CAH11": "121",
113
+ // Architecture, building and planning
114
+ "CAH13": "123",
115
+ // Social sciences
116
+ "CAH15": "132",
117
+ "CAH15-01": "132",
118
+ "CAH15-02": "129",
119
+ "CAH15-03": "128",
120
+ "CAH15-04": "131",
121
+ // Law
122
+ "CAH16": "130",
123
+ // Business and management
124
+ "CAH17": "133",
125
+ // Language and area studies
126
+ "CAH19": "137",
127
+ "CAH19-01": "138",
128
+ // Historical, philosophical and religious studies
129
+ "CAH20": "139",
130
+ "CAH20-01": "139",
131
+ "CAH20-02": "141",
132
+ // Education and teaching
133
+ "CAH22": "135",
134
+ // Media, journalism and communications
135
+ "CAH24": "145",
136
+ // Design, and creative and performing arts
137
+ "CAH25": "143",
138
+ "CAH25-01": "143",
139
+ "CAH25-02": "144",
140
+ // Geography, earth and environmental studies
141
+ "CAH26": "124",
142
+ };
143
+ /**
144
+ * The CAH level-1, level-2 and level-3 codes of a subject, most specific
145
+ * first. A malformed code yields just itself.
146
+ *
147
+ * @param {string} cah a CAH code at any level, e.g. "CAH10-01-02".
148
+ * @return {string[]} e.g. ["CAH10-01-02", "CAH10-01", "CAH10"].
149
+ */
150
+ function cahAncestors(cah) {
151
+ const code = (cah || "").trim().toUpperCase();
152
+ const m = /^(CAH\d{2})(?:-(\d{2}))?(?:-(\d{2}))?$/.exec(code);
153
+ if (!m)
154
+ return code ? [code] : [];
155
+ const out = [];
156
+ if (m[3])
157
+ out.push(`${m[1]}-${m[2]}-${m[3]}`);
158
+ if (m[2])
159
+ out.push(`${m[1]}-${m[2]}`);
160
+ out.push(m[1]);
161
+ return out;
162
+ }
163
+ /**
164
+ * The HESA cost centre a CAH subject is taught under, most specific mapping
165
+ * first.
166
+ *
167
+ * @param {string|undefined} cah a CAH code at any level.
168
+ * @return {string|undefined} the cost centre code, or undefined when none
169
+ * applies (combined studies, or an unknown code).
170
+ */
171
+ function costCentreForCah(cah) {
172
+ if (!cah)
173
+ return undefined;
174
+ for (const code of cahAncestors(cah)) {
175
+ const cc = exports.CAH_TO_COST_CENTRE[code];
176
+ if (cc)
177
+ return cc;
178
+ }
179
+ return undefined;
180
+ }
181
+ /**
182
+ * BRES broad industrial groups, as Nomis labels them, keyed by a stable id.
183
+ * The ids are what `HeArea.jobsBySector` and the `jobs_<id>` percentile keys
184
+ * use.
185
+ */
186
+ exports.BRES_SECTORS = {
187
+ agriculture: "Agriculture, forestry & fishing",
188
+ utilities: "Mining, quarrying & utilities",
189
+ manufacturing: "Manufacturing",
190
+ construction: "Construction",
191
+ motor: "Motor trades",
192
+ wholesale: "Wholesale",
193
+ retail: "Retail",
194
+ transport: "Transport & storage (inc postal)",
195
+ hospitality: "Accommodation & food services",
196
+ ict: "Information & communication",
197
+ finance: "Financial & insurance",
198
+ property: "Property",
199
+ professional: "Professional, scientific & technical",
200
+ business: "Business administration & support services",
201
+ publicAdmin: "Public administration & defence",
202
+ education: "Education",
203
+ health: "Health",
204
+ arts: "Arts, entertainment, recreation & other services",
205
+ };
206
+ /**
207
+ * Resolve a Nomis BRES industry label to its sector id. Nomis prefixes the
208
+ * labels with a number and suffixes the SIC section letters ("8 : Transport
209
+ * & storage (inc postal) (H)"), and the edition may swap "&" for "and", so
210
+ * the match ignores all three. Only a trailing group of section letters is
211
+ * dropped, so "(inc postal)" still counts.
212
+ *
213
+ * @param {string} label the label as it appears in the CSV.
214
+ * @return {string|undefined} the sector id, or undefined.
215
+ */
216
+ function bresSectorForLabel(label) {
217
+ const norm = (s) => s.toLowerCase()
218
+ .replace(/^\s*\d+\s*:\s*/, "")
219
+ .replace(/\((part\s+)?[a-u](\s*(,|and|-)\s*[a-u])*\)\s*$/i, "")
220
+ .replace(/\band\b/g, "&")
221
+ .replace(/[^a-z&]+/g, "");
222
+ const target = norm(label);
223
+ if (!target)
224
+ return undefined;
225
+ return Object.keys(exports.BRES_SECTORS).find((id) => norm(exports.BRES_SECTORS[id]) === target);
226
+ }
227
+ /**
228
+ * Careers library category -> the BRES sectors its jobs mostly sit in, so
229
+ * "jobs in the sector you're interested in near this university" can be
230
+ * scored from the student's interests.
231
+ */
232
+ exports.CAREER_CATEGORY_SECTORS = {
233
+ "Technology & Computing": ["ict"],
234
+ "Engineering & Manufacturing": ["manufacturing", "utilities"],
235
+ "Science & Research": ["professional"],
236
+ "Medicine & Healthcare": ["health"],
237
+ "Education & Training": ["education"],
238
+ "Business & Finance": ["finance", "business"],
239
+ "Law & Public Services": ["publicAdmin", "professional"],
240
+ "Creative Arts & Design": ["arts", "professional"],
241
+ "Media & Communications": ["ict", "arts"],
242
+ "Sport & Leisure": ["arts"],
243
+ "Hospitality & Tourism": ["hospitality"],
244
+ "Construction & Property": ["construction", "property"],
245
+ "Agriculture & Environment": ["agriculture"],
246
+ "Social Care & Charity": ["health"],
247
+ "Armed Forces & Emergency Services": ["publicAdmin"],
248
+ "Retail & Sales": ["retail", "wholesale"],
249
+ "Transport & Logistics": ["transport", "motor"],
250
+ };
251
+ /**
252
+ * The BRES sectors for a set of career interest categories, de-duplicated in
253
+ * the order the categories were given.
254
+ *
255
+ * @param {string[]} categories careers library categories.
256
+ * @return {string[]} sector ids.
257
+ */
258
+ function sectorsForCategories(categories) {
259
+ const out = [];
260
+ for (const c of categories) {
261
+ for (const s of exports.CAREER_CATEGORY_SECTORS[c] ?? []) {
262
+ if (!out.includes(s))
263
+ out.push(s);
264
+ }
265
+ }
266
+ return out;
267
+ }
268
+ //# sourceMappingURL=heMappings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heMappings.js","sourceRoot":"","sources":["../src/heMappings.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAmIH,oCASC;AAUD,4CAOC;AAsCD,gDASC;AAkCD,oDAQC;AApPD,kDAAkD;AACrC,QAAA,iBAAiB,GAA6B;IACvD,KAAK,EAAE,mBAAmB;IAC1B,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE,uCAAuC;IAC9C,KAAK,EAAE,qCAAqC;IAC5C,KAAK,EAAE,8BAA8B;IACrC,KAAK,EAAE,wBAAwB;IAC/B,KAAK,EAAE,2BAA2B;IAClC,KAAK,EAAE,oCAAoC;IAC3C,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE,wCAAwC;IAC/C,KAAK,EAAE,0CAA0C;IACjD,KAAK,EAAE,aAAa;IACpB,KAAK,EAAE,WAAW;IAClB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,qBAAqB;IAC5B,KAAK,EAAE,sBAAsB;IAC7B,KAAK,EAAE,+CAA+C;IACtD,KAAK,EAAE,mBAAmB;IAC1B,KAAK,EAAE,iDAAiD;IACxD,KAAK,EAAE,6CAA6C;IACpD,KAAK,EAAE,wDAAwD;IAC/D,KAAK,EAAE,aAAa;IACpB,KAAK,EAAE,8CAA8C;IACrD,KAAK,EAAE,qCAAqC;IAC5C,KAAK,EAAE,cAAc;IACrB,KAAK,EAAE,aAAa;IACpB,KAAK,EAAE,sCAAsC;IAC7C,KAAK,EAAE,oCAAoC;IAC3C,KAAK,EAAE,4BAA4B;IACnC,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,+BAA+B;IACtC,KAAK,EAAE,WAAW;IAClB,KAAK,EAAE,iCAAiC;IACxC,KAAK,EAAE,qCAAqC;IAC5C,KAAK,EAAE,WAAW;IAClB,KAAK,EAAE,sBAAsB;IAC7B,KAAK,EAAE,kBAAkB;IACzB,KAAK,EAAE,iCAAiC;IACxC,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,UAAU;IACjB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,gCAAgC;IACvC,KAAK,EAAE,gBAAgB;IACvB,KAAK,EAAE,yCAAyC;IAChD,KAAK,EAAE,eAAe;CACzB,CAAC;AAEF;;;;GAIG;AACU,QAAA,kBAAkB,GAA4B;IACvD,yBAAyB;IACzB,OAAO,EAAE,KAAK;IACd,aAAa,EAAE,KAAK;IACpB,8BAA8B;IAC9B,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,gCAAgC;IAChC,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,aAAa;IACb,OAAO,EAAE,KAAK;IACd,sBAAsB;IACtB,OAAO,EAAE,KAAK;IACd,wCAAwC;IACxC,OAAO,EAAE,KAAK;IACd,oBAAoB;IACpB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,wBAAwB;IACxB,OAAO,EAAE,KAAK;IACd,6BAA6B;IAC7B,OAAO,EAAE,KAAK;IACd,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE,KAAK;IACjB,YAAY;IACZ,OAAO,EAAE,KAAK;IACd,sCAAsC;IACtC,OAAO,EAAE,KAAK;IACd,kBAAkB;IAClB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,MAAM;IACN,OAAO,EAAE,KAAK;IACd,0BAA0B;IAC1B,OAAO,EAAE,KAAK;IACd,4BAA4B;IAC5B,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,kDAAkD;IAClD,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,yBAAyB;IACzB,OAAO,EAAE,KAAK;IACd,uCAAuC;IACvC,OAAO,EAAE,KAAK;IACd,2CAA2C;IAC3C,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,6CAA6C;IAC7C,OAAO,EAAE,KAAK;CACjB,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,GAAW;IACpC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,CAAC,GAAG,wCAAwC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9D,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,CAAC,CAAC,CAAC,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,CAAC,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACf,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,gBAAgB,CAAC,GAAuB;IACpD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,0BAAkB,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACU,QAAA,YAAY,GAA2B;IAChD,WAAW,EAAE,iCAAiC;IAC9C,SAAS,EAAE,+BAA+B;IAC1C,aAAa,EAAE,eAAe;IAC9B,YAAY,EAAE,cAAc;IAC5B,KAAK,EAAE,cAAc;IACrB,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,kCAAkC;IAC7C,WAAW,EAAE,+BAA+B;IAC5C,GAAG,EAAE,6BAA6B;IAClC,OAAO,EAAE,uBAAuB;IAChC,QAAQ,EAAE,UAAU;IACpB,YAAY,EAAE,sCAAsC;IACpD,QAAQ,EAAE,4CAA4C;IACtD,WAAW,EAAE,iCAAiC;IAC9C,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,kDAAkD;CAC3D,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAAC,KAAa;IAC5C,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE;SACtC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,OAAO,CAAC,iDAAiD,EAAE,EAAE,CAAC;SAC9D,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,oBAAY,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,oBAAY,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACU,QAAA,uBAAuB,GAAmC;IACnE,wBAAwB,EAAE,CAAC,KAAK,CAAC;IACjC,6BAA6B,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC;IAC7D,oBAAoB,EAAE,CAAC,cAAc,CAAC;IACtC,uBAAuB,EAAE,CAAC,QAAQ,CAAC;IACnC,sBAAsB,EAAE,CAAC,WAAW,CAAC;IACrC,oBAAoB,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;IAC7C,uBAAuB,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC;IACxD,wBAAwB,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC;IAClD,wBAAwB,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;IACzC,iBAAiB,EAAE,CAAC,MAAM,CAAC;IAC3B,uBAAuB,EAAE,CAAC,aAAa,CAAC;IACxC,yBAAyB,EAAE,CAAC,cAAc,EAAE,UAAU,CAAC;IACvD,2BAA2B,EAAE,CAAC,aAAa,CAAC;IAC5C,uBAAuB,EAAE,CAAC,QAAQ,CAAC;IACnC,mCAAmC,EAAE,CAAC,aAAa,CAAC;IACpD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;IACzC,uBAAuB,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC;CAClD,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAAC,UAAoB;IACrD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,+BAAuB,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const heMappings_1 = require("./heMappings");
4
+ const lmiCategories_1 = require("./lmiCategories");
5
+ describe("cahAncestors", () => {
6
+ it("lists a level-3 code's parents, most specific first", () => {
7
+ expect((0, heMappings_1.cahAncestors)("CAH10-01-02")).toEqual(["CAH10-01-02", "CAH10-01", "CAH10"]);
8
+ });
9
+ it("handles level-2 and level-1 codes and normalises case", () => {
10
+ expect((0, heMappings_1.cahAncestors)("cah10-01")).toEqual(["CAH10-01", "CAH10"]);
11
+ expect((0, heMappings_1.cahAncestors)("CAH11")).toEqual(["CAH11"]);
12
+ });
13
+ it("returns a malformed code as itself and nothing for blank", () => {
14
+ expect((0, heMappings_1.cahAncestors)("X1")).toEqual(["X1"]);
15
+ expect((0, heMappings_1.cahAncestors)("")).toEqual([]);
16
+ });
17
+ });
18
+ describe("costCentreForCah", () => {
19
+ it("prefers the most specific mapping", () => {
20
+ expect((0, heMappings_1.costCentreForCah)("CAH10-01-07")).toBe("118");
21
+ expect((0, heMappings_1.costCentreForCah)("CAH10-02-01")).toBe("115");
22
+ expect((0, heMappings_1.costCentreForCah)("CAH15-02-01")).toBe("129");
23
+ });
24
+ it("falls back to the level-1 mapping", () => {
25
+ expect((0, heMappings_1.costCentreForCah)("CAH11-01-05")).toBe("121");
26
+ });
27
+ it("has no cost centre for combined studies or unknown codes", () => {
28
+ expect((0, heMappings_1.costCentreForCah)("CAH23-01-01")).toBeUndefined();
29
+ expect((0, heMappings_1.costCentreForCah)(undefined)).toBeUndefined();
30
+ expect((0, heMappings_1.costCentreForCah)("CAH99")).toBeUndefined();
31
+ });
32
+ it("maps only to cost centres that exist", () => {
33
+ Object.values(heMappings_1.CAH_TO_COST_CENTRE).forEach((cc) => expect(heMappings_1.HESA_COST_CENTRES[cc]).toBeDefined());
34
+ });
35
+ });
36
+ describe("bresSectorForLabel", () => {
37
+ it("matches Nomis labels with their numeric prefix and SIC letters", () => {
38
+ expect((0, heMappings_1.bresSectorForLabel)("10 : Information & communication (J)")).toBe("ict");
39
+ expect((0, heMappings_1.bresSectorForLabel)("18 : Arts, entertainment, recreation & other services (R,S,T and U)")).toBe("arts");
40
+ expect((0, heMappings_1.bresSectorForLabel)("Transport & storage (inc postal)")).toBe("transport");
41
+ });
42
+ it("maps every broad industrial group label Nomis NM_189_1 served in 2026", () => {
43
+ const labels = ["1 : Agriculture, forestry & fishing (A)", "2 : Mining, quarrying & utilities (B,D and E)", "3 : Manufacturing (C)",
44
+ "4 : Construction (F)", "5 : Motor trades (Part G)", "6 : Wholesale (Part G)", "7 : Retail (Part G)",
45
+ "8 : Transport & storage (inc postal) (H)", "9 : Accommodation & food services (I)", "10 : Information & communication (J)",
46
+ "11 : Financial & insurance (K)", "12 : Property (L)", "13 : Professional, scientific & technical (M)",
47
+ "14 : Business administration & support services (N)", "15 : Public administration & defence (O)", "16 : Education (P)",
48
+ "17 : Health (Q)", "18 : Arts, entertainment, recreation & other services (R,S,T and U)"];
49
+ expect(new Set(labels.map(heMappings_1.bresSectorForLabel))).toEqual(new Set(Object.keys(heMappings_1.BRES_SECTORS)));
50
+ });
51
+ it("treats 'and' like '&'", () => {
52
+ expect((0, heMappings_1.bresSectorForLabel)("Agriculture, forestry and fishing")).toBe("agriculture");
53
+ });
54
+ it("is undefined for anything else", () => {
55
+ expect((0, heMappings_1.bresSectorForLabel)("Total")).toBeUndefined();
56
+ expect((0, heMappings_1.bresSectorForLabel)("")).toBeUndefined();
57
+ });
58
+ });
59
+ describe("career category sectors", () => {
60
+ it("covers every careers library category with known sectors", () => {
61
+ lmiCategories_1.CAREER_LIBRARY_CATEGORIES.forEach((c) => {
62
+ expect(heMappings_1.CAREER_CATEGORY_SECTORS[c]?.length).toBeGreaterThan(0);
63
+ heMappings_1.CAREER_CATEGORY_SECTORS[c].forEach((s) => expect(heMappings_1.BRES_SECTORS[s]).toBeDefined());
64
+ });
65
+ });
66
+ it("de-duplicates in order", () => {
67
+ expect((0, heMappings_1.sectorsForCategories)(["Technology & Computing", "Media & Communications"])).toEqual(["ict", "arts"]);
68
+ expect((0, heMappings_1.sectorsForCategories)(["Unknown"])).toEqual([]);
69
+ });
70
+ });
71
+ //# sourceMappingURL=heMappings.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heMappings.test.js","sourceRoot":"","sources":["../src/heMappings.test.ts"],"names":[],"mappings":";;AAAA,6CASsB;AACtB,mDAA0D;AAE1D,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,IAAA,yBAAY,EAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,IAAA,yBAAY,EAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,IAAA,yBAAY,EAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,IAAA,yBAAY,EAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAA,yBAAY,EAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,IAAA,6BAAgB,EAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,CAAC,IAAA,6BAAgB,EAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,CAAC,IAAA,6BAAgB,EAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,IAAA,6BAAgB,EAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,IAAA,6BAAgB,EAAC,aAAa,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,CAAC,IAAA,6BAAgB,EAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACpD,MAAM,CAAC,IAAA,6BAAgB,EAAC,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,MAAM,CAAC,+BAAkB,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,8BAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,IAAA,+BAAkB,EAAC,sCAAsC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAA,+BAAkB,EAAC,qEAAqE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/G,MAAM,CAAC,IAAA,+BAAkB,EAAC,kCAAkC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC7E,MAAM,MAAM,GAAG,CAAC,yCAAyC,EAAE,+CAA+C,EAAE,uBAAuB;YAC/H,sBAAsB,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,qBAAqB;YACpG,0CAA0C,EAAE,uCAAuC,EAAE,sCAAsC;YAC3H,gCAAgC,EAAE,mBAAmB,EAAE,+CAA+C;YACtG,qDAAqD,EAAE,0CAA0C,EAAE,oBAAoB;YACvH,iBAAiB,EAAE,qEAAqE,CAAC,CAAC;QAC9F,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,+BAAkB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAY,CAAC,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,IAAA,+BAAkB,EAAC,mCAAmC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,IAAA,+BAAkB,EAAC,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACpD,MAAM,CAAC,IAAA,+BAAkB,EAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAChE,yCAAyB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,MAAM,CAAC,oCAAuB,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAC9D,oCAAuB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,yBAAY,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,IAAA,iCAAoB,EAAC,CAAC,wBAAwB,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5G,MAAM,CAAC,IAAA,iCAAoB,EAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}