From 1896f55fd42008cb560e40e3c0e8b086d8adaaa9 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 4 Mar 2021 15:35:19 -0500 Subject: [PATCH] Record and compute sub-requirement progress in a fine-grained way --- src/requirement-types.d.ts | 33 +- src/requirements/README.md | 22 +- .../requirement-data-id.test.ts.snap | 8 +- src/requirements/data/checkers-common.ts | 13 +- src/requirements/data/colleges/ag.ts | 59 +- src/requirements/data/colleges/asPreFA2020.ts | 158 +- src/requirements/data/colleges/en.ts | 114 +- src/requirements/data/colleges/he.ts | 4 +- src/requirements/data/colleges/il.ts | 10 +- src/requirements/data/majors/aem.ts | 34 +- src/requirements/data/majors/be.ts | 18 +- src/requirements/data/majors/bio.ts | 36 +- src/requirements/data/majors/bme.ts | 21 +- src/requirements/data/majors/ce.ts | 15 +- src/requirements/data/majors/chemE.ts | 61 +- src/requirements/data/majors/comm.ts | 15 +- src/requirements/data/majors/crp.ts | 70 +- src/requirements/data/majors/cs.ts | 46 +- src/requirements/data/majors/dea.ts | 64 +- src/requirements/data/majors/econ.ts | 12 +- src/requirements/data/majors/engl.ts | 42 +- src/requirements/data/majors/govt.ts | 7 +- src/requirements/data/majors/hadm.ts | 33 +- src/requirements/data/majors/hist.ts | 9 +- src/requirements/data/majors/info.ts | 9 +- src/requirements/data/majors/isst.ts | 15 +- src/requirements/data/majors/me.ts | 8 +- src/requirements/data/majors/orie.ts | 8 +- src/requirements/data/minors/bu.ts | 18 +- src/requirements/data/minors/cogsci.ts | 9 +- src/requirements/data/minors/cs.ts | 9 +- src/requirements/data/minors/dbme.ts | 12 +- src/requirements/data/minors/isst.ts | 6 +- src/requirements/data/minors/math.ts | 3 +- src/requirements/data/minors/orms.ts | 6 +- src/requirements/data/minors/psych.ts | 2 +- .../data/requirement-data-consistency.test.ts | 49 + src/requirements/data/university/index.ts | 5 +- src/requirements/decorated-requirements.json | 1419 ++++++++++------- .../requirement-frontend-computation.ts | 88 +- .../requirement-frontend-utils.ts | 85 +- .../requirement-json-generator.ts | 8 +- src/requirements/types.ts | 2 +- 43 files changed, 1450 insertions(+), 1215 deletions(-) create mode 100644 src/requirements/data/requirement-data-consistency.test.ts diff --git a/src/requirement-types.d.ts b/src/requirement-types.d.ts index c0ee64007..cff69c908 100644 --- a/src/requirement-types.d.ts +++ b/src/requirement-types.d.ts @@ -24,32 +24,21 @@ type RequirementFulfillmentInformation> = readonly minCount?: number; } | ({ - /** Defines how courses in a sub-requirement can be all counted towards a stat. */ - readonly subRequirementProgress: 'every-course-needed' | 'any-can-count'; - readonly fulfilledBy: 'courses'; - /** The minimum number of courses required to fulfill this requirement. */ - readonly minCount: number; - } & T) - | ({ - readonly fulfilledBy: 'credits'; - /** The minimum number of credits required to fulfill this requirement. */ - readonly minCount: number; + readonly fulfilledBy: 'courses' | 'credits'; + /** The minimum number of courses/credits required to fulfill each sub-requirement. */ + readonly perSlotMinCount: readonly number[]; + /** When we care more about how many slots are filled with some courses */ + readonly minNumberOfSlots?: number; } & T) | { readonly fulfilledBy: 'toggleable'; readonly fulfillmentOptions: { - readonly [optionName: string]: - | ({ - readonly minCount: number; - readonly counting: 'courses'; - readonly subRequirementProgress: 'every-course-needed' | 'any-can-count'; - readonly description: string; - } & T) - | ({ - readonly minCount: number; - readonly counting: 'credits'; - readonly description: string; - } & T); + readonly [optionName: string]: { + readonly counting: 'courses' | 'credits'; + readonly perSlotMinCount: readonly number[]; + readonly minNumberOfSlots?: number; + readonly description: string; + } & T; }; }; diff --git a/src/requirements/README.md b/src/requirements/README.md index 49d1b5ac7..50c80beee 100644 --- a/src/requirements/README.md +++ b/src/requirements/README.md @@ -98,24 +98,12 @@ To reiterate, this phase computes a list of satisfying courses for each requirem 4. Now we created [`decorated-requirements.json`](./decorated-requirements.json). Pre-computation is done. -Each checker is either: +Each checker is a list of functions `(course: Course) => boolean`, where each function checks +whether the course satisfies one of the sub-requirements that this checker correspond to. -- a TypeScript function `(course: Course) => boolean` that directly tells whether the course - satisfies the requirement that this checker correspond to. -- or a list of such functions, where each function checks whether the course satisfies one of the - sub-requirements that this checker correspond to. - -This is how you should use your checkers: - -- Case 1: the requirement contains no sub-requirement. Use option 1. Example: CS major practicum. -- Case 2: the requirement contains sub-requirements. Use option 2. Example: CS Core requirement. - -Also consider the cases of computing the progress with `subRequirementProgress`: - -- Operator type 'every-course-needed' indicates that all instances of a sub-requirement is necessary. - Example: CS Introductory Programming -- Operator type 'any-can-count' indicates that only one instance of a sub-requirement can be used. - Example: ENGL Four 4000 Levels +For each checker, there is an associated minimal number of course/credit required for that +sub-requirement stored in `perSlotMinCount`. There can also be a `minNumberOfSlots` field, which +specifies that we don't need to fulfill every slot, but only `minNumberOfSlots` of sub-requirements. ### Frontend Computation Phase diff --git a/src/requirements/__test__/__snapshots__/requirement-data-id.test.ts.snap b/src/requirements/__test__/__snapshots__/requirement-data-id.test.ts.snap index cf5a8c185..0c82bac53 100644 --- a/src/requirements/__test__/__snapshots__/requirement-data-id.test.ts.snap +++ b/src/requirements/__test__/__snapshots__/requirement-data-id.test.ts.snap @@ -17,9 +17,7 @@ Array [ "College-AS1-Foreign Language", "College-AS1-Geographic Breadth Requirement (GB)", "College-AS1-Historic Breadth Requirement (HB)", - "College-AS1-Mathematics & Quantitative Reasoning (MQR-AS)", - "College-AS1-PBS-AS or MQR-AS", - "College-AS1-Physical & Biological Sceiences (PBS-AS/PBSS-AS)", + "College-AS1-PBS and MQR courses", "College-EN-Advisor-Approved Electives", "College-EN-Chemistry", "College-EN-Computing", @@ -94,11 +92,9 @@ Array [ "Major-COMM-Upper-Level COMM", "Major-CRP-Core Classes", "Major-CRP-Distribution Requirements: 5 Courses", - "Major-CRP-Distribution Requirements: MQR", - "Major-CRP-Distribution Requirements: MQR OR PBS", - "Major-CRP-Distribution Requirements: PBS", "Major-CRP-Five CRP Classes", "Major-CRP-Microeconomics", + "Major-CRP-PBS and MQR courses", "Major-CRP-Statistics", "Major-CS-Computer Science Core", "Major-CS-CS Electives", diff --git a/src/requirements/data/checkers-common.ts b/src/requirements/data/checkers-common.ts index beb9e45fc..93049c670 100644 --- a/src/requirements/data/checkers-common.ts +++ b/src/requirements/data/checkers-common.ts @@ -1,4 +1,4 @@ -import { Course } from '../types'; +import { Course, RequirementChecker } from '../types'; import { FWS_COURSE_ID } from './constants'; /** @@ -66,11 +66,14 @@ export const courseIsFWS = (course: Course): boolean => * ``` * * @param includes a list of course code pattern to check against. - * @returns a checker that can be directly assigned to requirement object. + * @returns a list with a single checker that checks whether this single sub-requirement can be + * fulfilled by courses. */ -export const includesWithSingleRequirement = (...includes: readonly string[]) => ( - course: Course -): boolean => courseMatchesCodeOptions(course, includes); +export const includesWithSingleRequirement = ( + ...includes: readonly string[] +): readonly RequirementChecker[] => [ + (course: Course): boolean => courseMatchesCodeOptions(course, includes), +]; /** * This function returns an array of checkers. diff --git a/src/requirements/data/colleges/ag.ts b/src/requirements/data/colleges/ag.ts index b9aa7ff6c..359d27cb5 100644 --- a/src/requirements/data/colleges/ag.ts +++ b/src/requirements/data/colleges/ag.ts @@ -10,13 +10,15 @@ const calsCreditsRequirement: CollegeOrMajorRequirement = { 'and The Department of Statistics and Data Science.', source: 'https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements', - checker: (course: Course): boolean => - ['AG'].includes(course.acadGroup) || - ['AEM', 'BIOEE', 'BIOMG', 'BIOMI', 'BIONB', 'BSOC', 'EAS', 'INFO', 'NS', 'STSCI'].includes( - course.subject - ), + checker: [ + (course: Course): boolean => + ['AG'].includes(course.acadGroup) || + ['AEM', 'BIOEE', 'BIOMG', 'BIOMI', 'BIONB', 'BSOC', 'EAS', 'INFO', 'NS', 'STSCI'].includes( + course.subject + ), + ], fulfilledBy: 'credits', - minCount: 55, + perSlotMinCount: [55], }; const calsIntroductoryLifeSciencesOrBiologyRequirement: CollegeOrMajorRequirement = { @@ -99,7 +101,7 @@ const calsIntroductoryLifeSciencesOrBiologyRequirement: CollegeOrMajorRequiremen 'VIEN 2204' ), fulfilledBy: 'credits', - minCount: 6, + perSlotMinCount: [6], }; const calsPhysicalAndLifeSciencesRequirement: CollegeOrMajorRequirement = { @@ -118,9 +120,9 @@ const calsChemistryOrPhysicsRequiement: CollegeOrMajorRequirement = { 'Includes all Cornell courses with the CHEM or PHYS prefix at Cornell (excluding courses that are supplemental, independent study, research, TA, internship, and First-Year Writing Seminar).', source: 'https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements', - checker: (course: Course): boolean => ['CHEM', 'CHEME', 'PHYS'].includes(course.subject), + checker: [(course: Course): boolean => ['CHEM', 'CHEME', 'PHYS'].includes(course.subject)], fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }; const calsQuantitativeLiteracyRequirement: CollegeOrMajorRequirement = { @@ -131,10 +133,9 @@ const calsQuantitativeLiteracyRequirement: CollegeOrMajorRequirement = { 'or transfer an approved calculus or statistics course with a minimum letter grade of “C” or better; or take an approved calculus or statistics course at Cornell.', source: 'https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements', - checker: (course: Course): boolean => ['MATH', 'STSCI'].includes(course.subject), - subRequirementProgress: 'any-can-count', + checker: [(course: Course): boolean => ['MATH', 'STSCI'].includes(course.subject)], fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }; const calsSocialSciencesAndHumanitiesRequiement: CollegeOrMajorRequirement = { @@ -155,9 +156,9 @@ const calsSocialSciencesAndHumanitiesRequiement: CollegeOrMajorRequirement = { (course: Course): boolean => course.catalogDistr?.includes('LA-') ?? false, (course: Course): boolean => course.catalogDistr?.includes('SBA-') ?? false, ], - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1], + minNumberOfSlots: 4, }; const calsHumanDiversityRequirement: CollegeOrMajorRequirement = { @@ -166,10 +167,9 @@ const calsHumanDiversityRequirement: CollegeOrMajorRequirement = { 'At least one course category MUST be completed in three different categories. Human Diversity (D) is a required category and MUST be completed.', source: 'https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements', - checker: (course: Course): boolean => course.catalogDistr?.includes('(D-') ?? false, - subRequirementProgress: 'any-can-count', + checker: [(course: Course): boolean => course.catalogDistr?.includes('(D-') ?? false], fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }; const calsWrittenAndOralExpressionRequirement: CollegeOrMajorRequirement = { @@ -180,12 +180,14 @@ const calsWrittenAndOralExpressionRequirement: CollegeOrMajorRequirement = { 'If not required, all nine credits may be in written expression. Writing in the Majors courses do not count towards the writing requirement.', source: 'https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements', - checker: (course: Course): boolean => - ['written expression', 'oral expression', 'First-Year Writing Seminar'].some( - keyword => course.catalogSatisfiesReq?.includes(keyword) ?? false - ), + checker: [ + (course: Course): boolean => + ['written expression', 'oral expression', 'First-Year Writing Seminar'].some( + keyword => course.catalogSatisfiesReq?.includes(keyword) ?? false + ), + ], fulfilledBy: 'credits', - minCount: 9, + perSlotMinCount: [9], }; const calsWrittenExpressionRequirement: CollegeOrMajorRequirement = { @@ -193,12 +195,15 @@ const calsWrittenExpressionRequirement: CollegeOrMajorRequirement = { description: 'At least six credits must be in written expression.', source: 'https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements', - checker: (course: Course): boolean => - ['written expression', 'First-Year Writing Seminar'].some( - keyword => course.catalogSatisfiesReq?.includes(keyword) ?? false - ), + checker: [ + (course: Course): boolean => + ['written expression', 'First-Year Writing Seminar'].some( + keyword => course.catalogSatisfiesReq?.includes(keyword) ?? false + ), + ], fulfilledBy: 'credits', - minCount: 6, + perSlotMinCount: [6], + allowCourseDoubleCounting: true, }; const calsRequirements: readonly CollegeOrMajorRequirement[] = [ diff --git a/src/requirements/data/colleges/asPreFA2020.ts b/src/requirements/data/colleges/asPreFA2020.ts index 3e93ee84e..5e4afafcd 100644 --- a/src/requirements/data/colleges/asPreFA2020.ts +++ b/src/requirements/data/colleges/asPreFA2020.ts @@ -10,12 +10,14 @@ const casPreFA2020Requirements: readonly CollegeOrMajorRequirement[] = [ 'they can also take all their credits in Arts & Sciences and accumulate more than 120. ' + 'Note: AP, IB, and A-Level credits count toward the 120 total credits but not toward the 100 A&S credits.', source: 'https://as.cornell.edu/education/old-degree-requirements', - checker: (course: Course): boolean => - course.acadGroup.includes('AS') || - course.subject === 'CS' || - (course.catalogDistr?.includes('-AS') ?? false), + checker: [ + (course: Course): boolean => + course.acadGroup.includes('AS') || + course.subject === 'CS' || + (course.catalogDistr?.includes('-AS') ?? false), + ], fulfilledBy: 'credits', - minCount: 100, + perSlotMinCount: [100], allowCourseDoubleCounting: true, }, { @@ -24,11 +26,10 @@ const casPreFA2020Requirements: readonly CollegeOrMajorRequirement[] = [ 'A 5 on either the AP English Composition or Literature exam, or a 7 on the IB HL English Literature or Language exam will count towards one of these seminars. ' + 'First-year students should plan to take an FWS during their first semester at Cornell.', source: 'https://as.cornell.edu/education/old-degree-requirements', - checker: courseIsFWS, + checker: [courseIsFWS], fulfilledBy: 'credits', - minCount: 6, + perSlotMinCount: [6], }, - { name: 'Foreign Language', description: @@ -73,85 +74,73 @@ const casPreFA2020Requirements: readonly CollegeOrMajorRequirement[] = [ 'ZULU 2***' ), counting: 'courses', - subRequirementProgress: 'any-can-count', - minCount: 1, + perSlotMinCount: [1], }, 'Option 2': { description: 'Complete at least 11 credits of study (2 or 3 semesters) in a single foreign language taken in the appropriate sequence at Cornell.', - checker: (course: Course): boolean => - [ - 'ARAB', - 'BENGL', - 'BURM', - 'CHIN', - 'FREN', - 'GERST', - 'GREEK', - 'HEBRW', - 'HINDI', - 'INDO', - 'ITAL', - 'JAPAN', - 'KHMER', - 'KOREA', - 'LATIN', - 'NEPAL', - 'PERSN', - 'POLSH', - 'PORT', - 'RUSSA', - 'SANSK', - 'SINHA', - 'SPAN', - 'SWAHL', - 'TAG', - 'THAI', - 'TURK', - 'VIET', - 'YORUB', - 'ZULU', - ].includes(course.subject), + checker: [ + (course: Course): boolean => + [ + 'ARAB', + 'BENGL', + 'BURM', + 'CHIN', + 'FREN', + 'GERST', + 'GREEK', + 'HEBRW', + 'HINDI', + 'INDO', + 'ITAL', + 'JAPAN', + 'KHMER', + 'KOREA', + 'LATIN', + 'NEPAL', + 'PERSN', + 'POLSH', + 'PORT', + 'RUSSA', + 'SANSK', + 'SINHA', + 'SPAN', + 'SWAHL', + 'TAG', + 'THAI', + 'TURK', + 'VIET', + 'YORUB', + 'ZULU', + ].includes(course.subject), + ], counting: 'credits', - minCount: 11, + perSlotMinCount: [11], }, }, }, { - name: 'Physical & Biological Sceiences (PBS-AS/PBSS-AS)', - description: 'Students must take 2 courses in Physical & Biological Sciences (PBS/PBSS-AS).', - source: 'https://as.cornell.edu/education/old-degree-requirements', - checker: (course: Course): boolean => - ['PBS-AS', 'PBSS-AS'].some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), - subRequirementProgress: 'any-can-count', - fulfilledBy: 'courses', - minCount: 2, - allowCourseDoubleCounting: true, - }, - { - name: 'Mathematics & Quantitative Reasoning (MQR-AS)', - description: 'Students must take 1 course in Mathematics & Quantitative Reasoning (MQR-AS).', + name: 'PBS and MQR courses', + description: + 'Students must take 2 courses in Physical & Biological Sciences (PBS/PBSS-AS). ' + + 'Students must take 1 course in Mathematics & Quantitative Reasoning (MQR-AS). ' + + 'Students must take 1 course that is either in PBS-AS or MQR-AS.', source: 'https://as.cornell.edu/education/old-degree-requirements', - checker: (course: Course): boolean => course.catalogDistr?.includes('MQR-AS') ?? false, - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => + ['PBS-AS', 'PBSS-AS'].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + (course: Course): boolean => course.catalogDistr?.includes('MQR-AS') ?? false, + (course: Course): boolean => + ['PBS-AS', 'PBSS-AS', 'MQR-AS'].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [2, 1, 1], allowCourseDoubleCounting: true, }, - { - name: 'PBS-AS or MQR-AS', - description: 'Students must take 1 course that is either in PBS-AS or MQR-AS', - source: 'https://as.cornell.edu/education/old-degree-requirements', - checker: (course: Course): boolean => - ['PBS-AS', 'PBSS-AS', 'MQR-AS'].some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), - subRequirementProgress: 'any-can-count', - fulfilledBy: 'courses', - minCount: 1, - }, { name: 'Distribution Requirement', description: @@ -165,9 +154,8 @@ const casPreFA2020Requirements: readonly CollegeOrMajorRequirement[] = [ (course: Course): boolean => course.catalogDistr?.includes('LA-AS') ?? false, (course: Course): boolean => course.catalogDistr?.includes('SBA-AS') ?? false, ], - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], allowCourseDoubleCounting: true, }, { @@ -176,11 +164,12 @@ const casPreFA2020Requirements: readonly CollegeOrMajorRequirement[] = [ 'One course that focuses on an area or a people other than those of the United States, Canada, or Europe. ' + 'Courses fulfilling this requirement are marked with a GB/GHB in the Class Roster.', source: 'https://as.cornell.edu/education/old-degree-requirements', - checker: (course: Course): boolean => - ['GB', 'GHB'].some(breadth => course.catalogBreadth?.includes(breadth) ?? false), - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => + ['GB', 'GHB'].some(breadth => course.catalogBreadth?.includes(breadth) ?? false), + ], fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], allowCourseDoubleCounting: true, }, { @@ -189,11 +178,12 @@ const casPreFA2020Requirements: readonly CollegeOrMajorRequirement[] = [ 'One course that focuses on an historic period before the 20th century. ' + 'Courses fulfilling this requirement are marked with an HB/GHB in the Class Roster.', source: 'https://as.cornell.edu/education/old-degree-requirements', - checker: (course: Course): boolean => - ['HB', 'GHB'].some(breadth => course.catalogBreadth?.includes(breadth) ?? false), - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => + ['HB', 'GHB'].some(breadth => course.catalogBreadth?.includes(breadth) ?? false), + ], fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], allowCourseDoubleCounting: true, }, ]; diff --git a/src/requirements/data/colleges/en.ts b/src/requirements/data/colleges/en.ts index 05b9d50bc..1f420d064 100644 --- a/src/requirements/data/colleges/en.ts +++ b/src/requirements/data/colleges/en.ts @@ -29,9 +29,8 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', checker: includesWithSubRequirements(['MATH 1910'], ['MATH 1920'], ['MATH 2930', 'MATH 2940']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Physics', @@ -40,9 +39,8 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', checker: includesWithSubRequirements(['PHYS 1112'], ['PHYS 2213']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Chemistry', @@ -53,19 +51,17 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', checker: includesWithSingleRequirement('CHEM 2090'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'First-Year Writing Seminars', description: 'All students are required to take two first-year writing seminars.', source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', - checker: courseIsFWS, - subRequirementProgress: 'any-can-count', + checker: [courseIsFWS], fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2], }, { name: 'Computing', @@ -73,18 +69,17 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', checker: includesWithSingleRequirement('CS 1110', 'CS 1112', 'CS 1114', 'CS 1115'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Introduction to Engineering', description: 'One introduction to engineering (ENGRI) course.', source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', - checker: (course: Course): boolean => course.subject === 'ENGRI', + checker: [(course: Course): boolean => course.subject === 'ENGRI'], fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Engineering Distribution', @@ -92,10 +87,9 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ 'Two different category distribution courses (ENGRD), one of which may be required by the Major.', source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', - checker: (course: Course): boolean => course.subject === 'ENGRD', - subRequirementProgress: 'any-can-count', + checker: [(course: Course): boolean => course.subject === 'ENGRD'], fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2], }, { name: 'Liberal Studies Distribution: 6 courses', @@ -104,13 +98,14 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ 'At least two courses must be at the 2000 level or higher.', source: 'https://www.engineering.cornell.edu/students/undergraduate-students/advising/liberal-studies', - checker: (course: Course): boolean => - engineeringLiberalArtsDistributions.some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => + engineeringLiberalArtsDistributions.some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'courses', - minCount: 6, + perSlotMinCount: [6], }, { name: 'Liberal Studies Distribution: 3 categories', @@ -127,10 +122,10 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ course.catalogDistr?.includes(distribution) ?? false ), ], - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + minNumberOfSlots: 3, allowCourseDoubleCounting: true, - minCount: 3, }, { name: 'Liberal Studies Distribution: 18 credits', @@ -138,13 +133,15 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ 'In addition to six courses, the liberal studies distribution must total a minimum of 18 credits.', source: 'https://www.engineering.cornell.edu/students/undergraduate-students/advising/liberal-studies', - checker: (course: Course): boolean => - engineeringLiberalArtsDistributions.some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), + checker: [ + (course: Course): boolean => + engineeringLiberalArtsDistributions.some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'credits', + perSlotMinCount: [18], allowCourseDoubleCounting: true, - minCount: 18, }, { name: 'Advisor-Approved Electives', @@ -162,37 +159,38 @@ const engineeringRequirements: readonly CollegeOrMajorRequirement[] = [ 'Students can fulfill the upper-level engineering communications requirement in one of the six ways.', source: 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/engineering-communications-program/technical', - allowCourseDoubleCounting: true, - checker: includesWithSubRequirements( - ['ENGRC 3500'], - ['ENGRC 3020'], - ['ENGRC 3350'], - ['ENGRC 3340'], - ['ENGRD 2640'], - ['AEP 2640'], - ['CHEME 4320'], - ['MAE 4272'], - ['BEE 4730'], - ['BEE 4890'], - ['BEE 4530'], - ['BEE 4590'], - ['CIS 3000'], - ['INFO 1200'], - ['COMM 3030'], - ['COMM 3020'], - ['ENGRC 3023'], - ['ENGRC 2640'], - ['ENGRC 3152'], - ['ENGRC 3160'], - ['ENGRC 4152'], - ['ENGRC 4530'], - ['ENGRC 4890'], - ['MSE 4030', 'MSE 4040'], - ['MSE 4050', 'MSE 4060'] + checker: includesWithSingleRequirement( + 'ENGRC 3500', + 'ENGRC 3020', + 'ENGRC 3350', + 'ENGRC 3340', + 'ENGRD 2640', + 'AEP 2640', + 'CHEME 4320', + 'MAE 4272', + 'BEE 4730', + 'BEE 4890', + 'BEE 4530', + 'BEE 4590', + 'CIS 3000', + 'INFO 1200', + 'COMM 3030', + 'COMM 3020', + 'ENGRC 3023', + 'ENGRC 2640', + 'ENGRC 3152', + 'ENGRC 3160', + 'ENGRC 4152', + 'ENGRC 4530', + 'ENGRC 4890', + 'MSE 4030', + 'MSE 4040', + 'MSE 4050', + 'MSE 4060' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], + allowCourseDoubleCounting: true, }, ]; diff --git a/src/requirements/data/colleges/he.ts b/src/requirements/data/colleges/he.ts index fa0962164..44755de96 100644 --- a/src/requirements/data/colleges/he.ts +++ b/src/requirements/data/colleges/he.ts @@ -6,9 +6,9 @@ const humanEcologyRequirements: readonly CollegeOrMajorRequirement[] = [ description: 'Students must complete a minimum of 43 Human Ecology credits from College Distribution, Major Requirements and electives.', source: 'https://www.human.cornell.edu/academics/policies/requirements', - checker: (course: Course): boolean => course.acadGroup.includes('HE'), + checker: [(course: Course): boolean => course.acadGroup.includes('HE')], fulfilledBy: 'credits', - minCount: 43, + perSlotMinCount: [43], }, { name: 'Technical Communication', diff --git a/src/requirements/data/colleges/il.ts b/src/requirements/data/colleges/il.ts index 1d880650b..f1da1ab6a 100644 --- a/src/requirements/data/colleges/il.ts +++ b/src/requirements/data/colleges/il.ts @@ -23,9 +23,8 @@ const ilrRequirements: readonly CollegeOrMajorRequirement[] = [ ['ILRLR 2050'], ['ILRLE 2400'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 9, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1, 1, 1], }, { name: 'First-Year Writing Seminars', @@ -33,9 +32,9 @@ const ilrRequirements: readonly CollegeOrMajorRequirement[] = [ 'Students are required to fulfill the following writing requirements for a letter grade:', source: 'https://www.ilr.cornell.edu/student-experience/curriculum-requirements/undergraduate-requirements', - checker: courseIsFWS, + checker: [courseIsFWS], fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'ILR Advance Writing', @@ -54,9 +53,8 @@ const ilrRequirements: readonly CollegeOrMajorRequirement[] = [ 'ENGL 2880', 'ENGL 2890' ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Distribution Requirements', diff --git a/src/requirements/data/majors/aem.ts b/src/requirements/data/majors/aem.ts index 82cde8d84..bfd409c34 100644 --- a/src/requirements/data/majors/aem.ts +++ b/src/requirements/data/majors/aem.ts @@ -10,13 +10,15 @@ const aemRequirements: readonly CollegeOrMajorRequirement[] = [ 'Biological Sciences, Biology & Society, Earth and Atmospheric Sciences, Information Science, Nutritional Science, ' + 'and The Department of Statistics and Data Science.', source: 'https://dyson.cornell.edu/programs/undergraduate/degree-requirements/distribution/', - checker: (course: Course): boolean => - ['AG'].includes(course.acadGroup) || - ['AEM', 'BIOEE', 'BIOMG', 'BIOMI', 'BIONB', 'BSOC', 'EAS', 'INFO', 'NS', 'STSCI'].includes( - course.subject - ), + checker: [ + (course: Course): boolean => + ['AG'].includes(course.acadGroup) || + ['AEM', 'BIOEE', 'BIOMG', 'BIOMI', 'BIONB', 'BSOC', 'EAS', 'INFO', 'NS', 'STSCI'].includes( + course.subject + ), + ], fulfilledBy: 'credits', - minCount: 55, + perSlotMinCount: [55], }, { name: 'AEM Concentration Requirement', @@ -44,9 +46,8 @@ const aemRequirements: readonly CollegeOrMajorRequirement[] = [ ['AEM 3200'], ['AEM 3230'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 7, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1], }, { name: 'Economics Requirements', @@ -54,18 +55,16 @@ const aemRequirements: readonly CollegeOrMajorRequirement[] = [ 'ECON 1110, ECON 1120, AND AEM 2600. For students concentrating in environmental, energy, and resource economics, ECON 3030 is required instead of AEM 2600.', source: 'https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/', checker: includesWithSubRequirements(['ECON 1110'], ['ECON 1120'], ['AEM 2600', 'ECON 3030']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Quantitative Methods Requirements', description: 'AEM 2100, MATH 1110 OR MATH 1120, AND AEM 2010', source: 'https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/', checker: includesWithSubRequirements(['AEM 2100'], ['MATH 1110', 'MATH 1120'], ['AEM 2010']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Quantitative Methods Elective Requirements', @@ -91,7 +90,7 @@ const aemRequirements: readonly CollegeOrMajorRequirement[] = [ 'ILRST 3110' ), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Applied Economics Requirements', @@ -116,27 +115,24 @@ const aemRequirements: readonly CollegeOrMajorRequirement[] = [ 'AEM 2805', 'AEM 4940' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Grand Challenges Reqiurement Part 2: Pre-Project Weekend Immersion', description: 'Junior year: 1.5 credits. Focus: Working as part of a team', source: 'https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/', checker: includesWithSingleRequirement('AEM 3000'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Grand Challenges Reqiurement Part 3: Project Course', description: 'Senior year, 3 credits. Focus: Local and global community involvement', source: 'https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/', checker: includesWithSingleRequirement('AEM 4000'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, ]; diff --git a/src/requirements/data/majors/be.ts b/src/requirements/data/majors/be.ts index e0a2138d4..b4c3be702 100644 --- a/src/requirements/data/majors/be.ts +++ b/src/requirements/data/majors/be.ts @@ -8,9 +8,8 @@ const bioEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14', checker: includesWithSubRequirements(['ENGRD 2020'], ['ENGRD 2600', 'ENGRD 2510']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Intro Bio', @@ -24,9 +23,8 @@ const bioEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ 'BIOG 1445', 'BIOEE/BIOSM 1610' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2], }, { name: 'Required Major Courses', @@ -42,9 +40,8 @@ const bioEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ ['BEE 3600'], ['BEE 4500'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 6, + perSlotMinCount: [1, 1, 1, 1, 1, 1], }, { name: 'Biochemistry', @@ -55,9 +52,8 @@ const bioEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ ['BIOMG 3300', 'BIOMG 3330', 'BIOMG 3350', 'BIOMG 3310'], ['BIOMG 3320'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Upper-level Biology', @@ -82,9 +78,8 @@ const bioEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ ['BEE 2220', 'ENGRD 2210', 'CHEME 3130', 'MSE 3030'], ['CEE 3040', 'ENGRD 2700'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'BE Focus Area Elective', @@ -155,9 +150,8 @@ const bioEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ 'BEE 4880', 'BEE 7540' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [4], }, ]; diff --git a/src/requirements/data/majors/bio.ts b/src/requirements/data/majors/bio.ts index e9e29b1b9..4829f93de 100644 --- a/src/requirements/data/majors/bio.ts +++ b/src/requirements/data/majors/bio.ts @@ -12,27 +12,25 @@ const bioRequirements: readonly CollegeOrMajorRequirement[] = [ ['BIOG 1440', 'BIOG 1445'], ['BIOEE 1610', 'BIOSM 1610'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1, 1], + minNumberOfSlots: 2, }, { name: 'Investigative Laboratory', description: 'BIOG 1500 OR BIOSM 1500', source: 'http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535', checker: includesWithSubRequirements(['BIOG 1500', 'BIOSM 1500']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Evolutionary Biology and Diversity', description: 'BIOEE 1780 OR BIOEE 1781 OR BIOSM 1780', source: 'http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535', checker: includesWithSubRequirements(['BIOEE 1780', 'BIOEE 1781', 'BIOSM 1780']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'General Chemistry', @@ -44,15 +42,13 @@ const bioRequirements: readonly CollegeOrMajorRequirement[] = [ description: 'CHEM 2070 AND CHEM 2080', checker: includesWithSubRequirements(['CHEM 2070'], ['CHEM 2080']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 2, + perSlotMinCount: [1, 1], }, 'Option 2': { description: 'CHEM 2150', checker: includesWithSubRequirements(['CHEM 2150']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, }, }, @@ -78,9 +74,8 @@ const bioRequirements: readonly CollegeOrMajorRequirement[] = [ 'SOC 3010', ] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, // TODO: problem for reqs w options and diff minCount { @@ -93,9 +88,9 @@ const bioRequirements: readonly CollegeOrMajorRequirement[] = [ ['CHEM 3590', 'CHEM 3600'], ['CHEM 3530'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 2, 2, 1], + minNumberOfSlots: 1, }, { name: 'Physics', @@ -106,18 +101,17 @@ const bioRequirements: readonly CollegeOrMajorRequirement[] = [ ['PHYS 2207', 'PHYS 2208'], ['PHYS 1112', 'PHYS 2213'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2, 2, 2], + minNumberOfSlots: 1, }, { name: 'Genetics and Genomics', description: 'Lecture must be taken either concurrently or before the laboratory', source: 'http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535', checker: includesWithSubRequirements(['BIOMG 2800'], ['BIOMG 2801']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, // TODO: temp fix for reqs w options and diff minCount { @@ -125,18 +119,16 @@ const bioRequirements: readonly CollegeOrMajorRequirement[] = [ description: 'BIOMG 3300 OR BIOMG 3350 OR BIOMG 3310', source: 'http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535', checker: includesWithSubRequirements(['BIOMG 3300', 'BIOMG 3350', 'BIOMG 3310']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Biochemistry and Molecular Biology Part 2', description: 'BIOMG 3300 OR BIOMG 3350 OR BIOMG 3320', source: 'http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535', checker: includesWithSubRequirements(['BIOMG 3300', 'BIOMG 3350', 'BIOMG 3320']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Concentration', diff --git a/src/requirements/data/majors/bme.ts b/src/requirements/data/majors/bme.ts index db2f7b89d..e1979e966 100644 --- a/src/requirements/data/majors/bme.ts +++ b/src/requirements/data/majors/bme.ts @@ -9,9 +9,8 @@ const biomedicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = 'Curriculum distribution requirement and also fulfills a required Major course. It is best taken during semester 3 and must be completed before semester 5', source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19808', checker: includesWithSingleRequirement('ENGRD 2202'), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], allowCourseDoubleCounting: true, }, { @@ -27,9 +26,8 @@ const biomedicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = ['ENGRD 2020'], ['BTRY 3010', 'CEE 3040', 'ENGRD 2700'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 6, + perSlotMinCount: [1, 1, 1, 1, 1, 1], }, { name: 'Core Courses Part 2', @@ -44,9 +42,8 @@ const biomedicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = ['BME 4080'], ['BME 4090'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 7, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1], }, { name: 'Biomedical Engineering Concentrations', @@ -64,8 +61,7 @@ const biomedicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = ['BME 5830', 'BME 5850', 'BTRY 4381', 'BTRY 4840', 'CHEM 4810', 'CHEME 5430', 'CS 4780'] ), counting: 'courses', - subRequirementProgress: 'any-can-count', - minCount: 13, + perSlotMinCount: [1, 1, 1, 6], }, 'Biomedical Materials and Drug Delivery (BMDD)': { description: @@ -89,8 +85,7 @@ const biomedicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = ] ), counting: 'courses', - subRequirementProgress: 'any-can-count', - minCount: 13, + perSlotMinCount: [1, 1, 1, 6], }, 'Biomedical Imaging and Instrumentation (BMII)': { description: @@ -111,8 +106,7 @@ const biomedicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = ] ), counting: 'courses', - subRequirementProgress: 'any-can-count', - minCount: 13, + perSlotMinCount: [1, 1, 1, 6], }, 'Biomedical Mechanics and Mechanobiology (BMMB)': { description: @@ -133,8 +127,7 @@ const biomedicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = ] ), counting: 'courses', - subRequirementProgress: 'any-can-count', - minCount: 13, + perSlotMinCount: [1, 1, 1, 6], }, }, }, diff --git a/src/requirements/data/majors/ce.ts b/src/requirements/data/majors/ce.ts index fa45e8b20..603c6a325 100644 --- a/src/requirements/data/majors/ce.ts +++ b/src/requirements/data/majors/ce.ts @@ -12,9 +12,8 @@ const civilRequirements: readonly CollegeOrMajorRequirement[] = [ ['ENGRD 2020'], ['ENGRD 2610', 'ENGRD 2210', 'ENGRD 2110', 'ENGRD 2510'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], allowCourseDoubleCounting: true, }, { @@ -34,9 +33,8 @@ const civilRequirements: readonly CollegeOrMajorRequirement[] = [ ['CEE 3610'], ['CEE 3710'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 9, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1, 1, 1], }, { name: 'Capstone Design Elective', @@ -55,9 +53,8 @@ const civilRequirements: readonly CollegeOrMajorRequirement[] = [ 'CEE 4660', 'CEE 4740', ]), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Two Design Electives', @@ -76,9 +73,8 @@ const civilRequirements: readonly CollegeOrMajorRequirement[] = [ 'CEE 6370', 'MSE 5150', ]), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2], }, { name: 'Two Major-Approved Electives', @@ -118,9 +114,8 @@ const civilRequirements: readonly CollegeOrMajorRequirement[] = [ 'MSE 5550', 'CEE 3720', ]), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2], }, ]; diff --git a/src/requirements/data/majors/chemE.ts b/src/requirements/data/majors/chemE.ts index fc25bfa79..d6fa93f23 100644 --- a/src/requirements/data/majors/chemE.ts +++ b/src/requirements/data/majors/chemE.ts @@ -16,15 +16,13 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ description: 'CHEM 2090 AND CHEM 2080', checker: includesWithSubRequirements(['CHEM 2090'], ['CHEM 2080']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 2, + perSlotMinCount: [1, 1], }, 'Option 2': { description: 'CHEM 2150 with AP credit', checker: includesWithSubRequirements(['CHEM 2150']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, }, allowCourseDoubleCounting: true, @@ -39,9 +37,8 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ ['CHEM 3890'], ['ENGRD 2190'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [1, 1, 1, 1], allowCourseDoubleCounting: true, }, { @@ -54,9 +51,8 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ ['CHEM 3090'], ['CHEM 2900'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [1, 1, 1, 1], allowCourseDoubleCounting: true, }, { @@ -72,54 +68,49 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ 'A score of 5 on the CEEB AP Biology exam or a score of 7 on the IB Higher Level exam', checker: includesWithSubRequirements(['BIOG 1105'], ['BIOG 1107'], ['BIOG 1500']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, 'CHEME 2880': { description: 'CHEME 2880', checker: includesWithSubRequirements(['CHEME 2880']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, 'CHEME 5430': { description: 'CHEME 5430', checker: includesWithSubRequirements(['CHEME 5430']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, - '8 credits of pre-med biology sequence': { - description: - 'Take BIOG 1500, BIOMG 1350, and BIOG 1440. Or take BIOG 1107, BIOG 1108, and BIOG 1500', - checker: includesWithSubRequirements( - ['BIOG 1500', 'BIOMG 1350', 'BIOG 1440'], - ['BIOG 1107', 'BIOG 1108', 'BIOG 1500'] - ), + '8 credits of pre-med biology sequence: option 1': { + description: 'Take BIOG 1500, BIOMG 1350, and BIOG 1440', + checker: includesWithSubRequirements(['BIOG 1500', 'BIOMG 1350', 'BIOG 1440']), + counting: 'courses', + perSlotMinCount: [3], + }, + '8 credits of pre-med biology sequence: option 2': { + description: 'Take BIOG 1107, BIOG 1108, and BIOG 1500', + checker: includesWithSubRequirements(['BIOG 1107', 'BIOG 1108', 'BIOG 1500']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 3, + perSlotMinCount: [3], }, 'BIOMI 2900': { description: 'BIOMI 2900', checker: includesWithSubRequirements(['BIOMI 2900']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, 'BIOMG 3300 or BIOMG 3350': { description: 'BIOMG 3300 or BIOMG 3350', checker: includesWithSubRequirements(['BIOMG 3300', 'BIOMG 3350']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, 'BIOMG 3310 and BIOMG 3320': { description: 'BIOMG 3310 and BIOMG 3320', checker: includesWithSubRequirements(['BIOMG 3310'], ['BIOMG 3320']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 2, + perSlotMinCount: [1, 1], }, }, }, @@ -135,9 +126,8 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ ['CHEME 3130'], ['CHEME 3240'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], allowCourseDoubleCounting: true, }, { @@ -175,9 +165,8 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ ['CHEME 3720'], ['CHEME 3900'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], }, { name: 'Semester 7', @@ -210,9 +199,8 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ 'CHEME 6800', ] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Semester 8', @@ -225,9 +213,8 @@ const chemERequirements: readonly CollegeOrMajorRequirement[] = [ ['CHEME 3130'], ['CHEME 3240'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], }, { name: 'Major-Approved Electives', diff --git a/src/requirements/data/majors/comm.ts b/src/requirements/data/majors/comm.ts index ef08eff3d..b94e65d90 100644 --- a/src/requirements/data/majors/comm.ts +++ b/src/requirements/data/majors/comm.ts @@ -14,8 +14,7 @@ const commRequirements: readonly CollegeOrMajorRequirement[] = [ ['COMM 2820'] ), fulfilledBy: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], }, { name: 'Focus Area', @@ -23,8 +22,7 @@ const commRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://communication.cals.cornell.edu/undergraduate-program/major-requirements/', checker: includesWithSingleRequirement('COMM 2200', 'COMM 2450', 'COMM 2760', 'COMM 2850'), fulfilledBy: 'courses', - subRequirementProgress: 'any-can-count', - minCount: 2, + perSlotMinCount: [2], }, { name: 'Focus Area Upper Level', @@ -46,7 +44,7 @@ const commRequirements: readonly CollegeOrMajorRequirement[] = [ 'COMM 6***' ), fulfilledBy: 'credits', - minCount: 6, + perSlotMinCount: [6], }, { name: 'Upper-Level COMM', @@ -100,7 +98,7 @@ const commRequirements: readonly CollegeOrMajorRequirement[] = [ 'COMM 4990' ), fulfilledBy: 'credits', - minCount: 15, + perSlotMinCount: [15], }, { name: 'Communication Practica', @@ -108,7 +106,7 @@ const commRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://communication.cals.cornell.edu/undergraduate-program/major-requirements/', checker: includesWithSingleRequirement('COMM 30**'), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Introductory Statistics Class', @@ -132,9 +130,8 @@ const commRequirements: readonly CollegeOrMajorRequirement[] = [ 'PSYCH 2500', 'SOC 3010' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, ]; diff --git a/src/requirements/data/majors/crp.ts b/src/requirements/data/majors/crp.ts index 6193a7f87..842ee6955 100644 --- a/src/requirements/data/majors/crp.ts +++ b/src/requirements/data/majors/crp.ts @@ -3,35 +3,26 @@ import { includesWithSingleRequirement, includesWithSubRequirements } from '../c const crpRequirements: readonly CollegeOrMajorRequirement[] = [ { - name: 'Distribution Requirements: MQR', + name: 'PBS and MQR courses', description: - 'At least one class must be classified as mathematics and quantitative reasoning (MQR)', - source: 'http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145', - checker: (course: Course): boolean => course.catalogDistr?.includes('MQR-AS') ?? false, - subRequirementProgress: 'any-can-count', - fulfilledBy: 'courses', - minCount: 1, - }, - { - name: 'Distribution Requirements: PBS', - description: 'At least two classes must be classified as PBS', - source: 'http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145', - checker: (course: Course): boolean => course.catalogDistr?.includes('PBS-AS') ?? false, - subRequirementProgress: 'any-can-count', - fulfilledBy: 'courses', - minCount: 2, - }, - { - name: 'Distribution Requirements: MQR OR PBS', - description: 'At least one class must be classified as MQR or PBS', - source: 'http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145', - checker: (course: Course): boolean => - ['PBS-AS', 'PBSS-AS', 'MQR-AS'].some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), - subRequirementProgress: 'any-can-count', + 'Students must take 2 courses in Physical & Biological Sciences (PBS/PBSS-AS). ' + + 'Students must take 1 course in Mathematics & Quantitative Reasoning (MQR-AS). ' + + 'Students must take 1 course that is either in PBS-AS or MQR-AS.', + source: 'https://as.cornell.edu/education/old-degree-requirements', + checker: [ + (course: Course): boolean => + ['PBS-AS', 'PBSS-AS'].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + (course: Course): boolean => course.catalogDistr?.includes('MQR-AS') ?? false, + (course: Course): boolean => + ['PBS-AS', 'PBSS-AS', 'MQR-AS'].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [2, 1, 1], + allowCourseDoubleCounting: true, }, { name: 'Distribution Requirements: 5 Courses', @@ -39,13 +30,14 @@ const crpRequirements: readonly CollegeOrMajorRequirement[] = [ 'Must be selected from at least four of these five categories (i.e., CA, HA, KCM, LA, and SBA).' + 'No more than three of these five courses can be taken in any one department.', source: 'http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145', - checker: (course: Course): boolean => - ['CA', 'HA', 'LA/LAD', 'KCM', 'SBA'].some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => + ['CA', 'HA', 'LA/LAD', 'KCM', 'SBA'].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [5], }, { name: 'Core Classes', @@ -58,9 +50,8 @@ const crpRequirements: readonly CollegeOrMajorRequirement[] = [ ['CRP 2010'], ['CRP 3210'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], }, { name: 'Microeconomics', @@ -73,9 +64,8 @@ const crpRequirements: readonly CollegeOrMajorRequirement[] = [ 'ECON 3030', 'PAM 2000', ]), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Statistics', @@ -97,9 +87,8 @@ const crpRequirements: readonly CollegeOrMajorRequirement[] = [ 'STSCI 2100', 'STSCI 3080', ]), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Five CRP Classes', @@ -107,9 +96,8 @@ const crpRequirements: readonly CollegeOrMajorRequirement[] = [ 'Take five additional CRP classes at the 3000-level or higher, for a minimum of 3 credits each', source: 'http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145', checker: includesWithSingleRequirement('CRP 3***', 'CRP 4***', 'CRP 5***', 'CRP 6***'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [5], }, ]; diff --git a/src/requirements/data/majors/cs.ts b/src/requirements/data/majors/cs.ts index d51aa473c..170664b0b 100644 --- a/src/requirements/data/majors/cs.ts +++ b/src/requirements/data/majors/cs.ts @@ -17,9 +17,8 @@ const csRequirements: readonly CollegeOrMajorRequirement[] = [ ['CS 1110', 'CS 1112', 'CS 1114', 'CS 1115'], ['CS 2110', 'CS 2112'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Computer Science Core', @@ -32,9 +31,8 @@ const csRequirements: readonly CollegeOrMajorRequirement[] = [ ['CS 4820'], ['CS 4410'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], }, { name: 'CS Electives', @@ -42,17 +40,18 @@ const csRequirements: readonly CollegeOrMajorRequirement[] = [ 'Three 4000+ CS electives each at 3 credits. CS 4090, CS 4998, and CS 4998 are NOT allowed.', source: 'http://www.cs.cornell.edu/undergrad/rulesandproceduresengineering/choosingyourelectives', - checker: (course: Course): boolean => { - if ( - courseMatchesCodeOptions(course, ['CS 4090', 'CS 4998', 'CS 4998', 'CS 4410', 'CS 4820']) - ) { - return false; - } - return ifCodeMatch(course.subject, 'CS') && ifCodeMatch(course.catalogNbr, '4***'); - }, - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => { + if ( + courseMatchesCodeOptions(course, ['CS 4090', 'CS 4998', 'CS 4998', 'CS 4410', 'CS 4820']) + ) { + return false; + } + return ifCodeMatch(course.subject, 'CS') && ifCodeMatch(course.catalogNbr, '4***'); + }, + ], fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, { name: 'CS Practicum or Project', @@ -75,22 +74,22 @@ const csRequirements: readonly CollegeOrMajorRequirement[] = [ 'CS 5625', 'CS 5643' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Technical Electives', description: 'Three 3000-level or above (3+ credits each) courses with technical content', source: 'https://www.cs.cornell.edu/undergrad/csmajor/technicalelectives', - checker: (course: Course): boolean => { - const { catalogNbr } = course; - return catalogNbr.startsWith('3'); - }, + checker: [ + (course: Course): boolean => { + const { catalogNbr } = course; + return catalogNbr.startsWith('3'); + }, + ], checkerWarning: 'We do not check that the courses are considered technical.', fulfilledBy: 'courses', - subRequirementProgress: 'any-can-count', - minCount: 3, + perSlotMinCount: [3], }, { name: 'External Specialization', @@ -125,9 +124,8 @@ const csRequirements: readonly CollegeOrMajorRequirement[] = [ 'ENGRD 2700', 'MATH 4710', ]), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, ]; diff --git a/src/requirements/data/majors/dea.ts b/src/requirements/data/majors/dea.ts index a9827dc21..06f8d4652 100644 --- a/src/requirements/data/majors/dea.ts +++ b/src/requirements/data/majors/dea.ts @@ -21,9 +21,8 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ ['DEA 4040'], ['DEA 5304'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 11, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], }, { name: 'DEA Thematic Courses', @@ -63,9 +62,8 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ 'DEA 5305', 'DEA 5560', ]), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 9, + perSlotMinCount: [9], }, { name: 'Research Methods Course', @@ -73,9 +71,8 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements', checker: includesWithSubRequirements(['DEA 3550', 'ILROB 4710', 'PAM 3120']), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Human Development or Psychology', @@ -83,9 +80,8 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements', checker: includesWithSubRequirements(['HD 1150', 'HC 1170', 'PSYCH 1101']), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Introductory Microeconomics', @@ -93,22 +89,22 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements', checker: includesWithSubRequirements(['ECON 1110']), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Humanities', description: 'Choose any course with the Course Distribution HA, LA or CA.', source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements', - checker: (course: Course): boolean => - ['CA', 'HA', 'LA', 'LAD'].some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => + ['CA', 'HA', 'LA', 'LAD'].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Statistics', @@ -118,9 +114,8 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements', checker: includesWithSubRequirements(['PAM 2100', 'AEM 2100', 'ILRST 2100', 'PSYCH 2500']), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Natural Science I', @@ -141,22 +136,19 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ 'BIOG 1445', ]), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, Chemistry: { description: 'Take 1: CHEM 1560, CHEM 2070, CHEM 2080, or 5 on AP Chemistry', checker: includesWithSubRequirements(['CHEM 1560', 'CHEM 2070', 'CHEM 2080']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, Physics: { description: 'Take 1: PHYS 1101, PHYS 2207, PHYS 1102, PHYS 2208, or 5 on AP Physics', checker: includesWithSubRequirements(['PHYS 1101', 'PHYS 2207', 'PHYS 1102', 'PHYS 2208']), counting: 'courses', - subRequirementProgress: 'every-course-needed', - minCount: 1, + perSlotMinCount: [1], }, }, }, @@ -166,12 +158,14 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ 'Choose any 3 credit course with a PBS, BIOLS-AG, or BIONLS-AG Course Distribution.', source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements', - checker: (course: Course): boolean => - ['PBS', 'BIOLS-AG', 'BIONLS-AG '].some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), + checker: [ + (course: Course): boolean => + ['PBS', 'BIOLS-AG', 'BIONLS-AG '].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'DEA Additional Requirements', @@ -179,12 +173,14 @@ const deaRequirements: readonly CollegeOrMajorRequirement[] = [ 'Any course with the Course Distribution PBS, BIOLS-AG, BIONLS-AG, SBA, KCM, MQR, LA, CA, or HA. Language courses may count here.', source: 'http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements', - checker: (course: Course): boolean => - ['PBS', 'BIOLS-AG', 'BIONLS-AG', 'SBA', 'KCM', 'MQR', 'LA', 'CA', 'HA', 'FL'].some( - distribution => course.catalogDistr?.includes(distribution) ?? false - ), + checker: [ + (course: Course): boolean => + ['PBS', 'BIOLS-AG', 'BIONLS-AG', 'SBA', 'KCM', 'MQR', 'LA', 'CA', 'HA', 'FL'].some( + distribution => course.catalogDistr?.includes(distribution) ?? false + ), + ], fulfilledBy: 'credits', - minCount: 6, + perSlotMinCount: [6], }, ]; diff --git a/src/requirements/data/majors/econ.ts b/src/requirements/data/majors/econ.ts index 20126a2e2..a4f618b6e 100644 --- a/src/requirements/data/majors/econ.ts +++ b/src/requirements/data/majors/econ.ts @@ -8,9 +8,8 @@ const economicsRequirements: readonly CollegeOrMajorRequirement[] = [ 'Before applying for admission to the Economics Major, students must complete ECON 1110, ECON 1120, and MATH 1110 (or equivalents).', source: 'https://economics.cornell.edu/major', checker: includesWithSubRequirements(['ECON 1110'], ['ECON 1120'], ['MATH 1110']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Core Economics', @@ -23,18 +22,16 @@ const economicsRequirements: readonly CollegeOrMajorRequirement[] = [ ['ECON 3110', 'ECON 3130'], ['ECON 3120', 'ECON 3140'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [1, 1, 1, 1], }, { name: '4000-level Courses', description: 'All students must take at least three courses at the 4000-level or higher.', source: 'https://economics.cornell.edu/major', checker: includesWithSingleRequirement('ECON 4***'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Basic Requirements', @@ -42,9 +39,8 @@ const economicsRequirements: readonly CollegeOrMajorRequirement[] = [ 'Twelve courses listed by the Department of Economics, or approved by the student’s major advisor', source: 'https://economics.cornell.edu/major', checker: includesWithSingleRequirement('ECON 1110', 'ECON 1120', 'ECON 3***', 'ECON 4***'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 12, + perSlotMinCount: [12], }, ]; diff --git a/src/requirements/data/majors/engl.ts b/src/requirements/data/majors/engl.ts index 8b20178a3..fcbaadb0a 100644 --- a/src/requirements/data/majors/engl.ts +++ b/src/requirements/data/majors/engl.ts @@ -9,20 +9,24 @@ const englishRequirements: readonly CollegeOrMajorRequirement[] = [ 'All 2000-level ENGL courses (with the exception of 2800-2810 and 2880-2890) count for the major, as do all 3000-and 4000-level courses.', source: 'https://english.cornell.edu/majoring-and-minoring-english-cornell#requirements-for-the-major', - checker: (course: Course): boolean => { - if (courseMatchesCodeOptions(course, ['ENGL 2800', 'ENGL 2810', 'ENGL 2880', 'ENGL 2890'])) { - return false; - } - return courseMatchesCodeOptions(course, [ - 'ENGL 2***', - 'ENGL 3***', - 'ENGL 4***', - 'ENGL 5***', - 'ENGL 6***', - ]); - }, + checker: [ + (course: Course): boolean => { + if ( + courseMatchesCodeOptions(course, ['ENGL 2800', 'ENGL 2810', 'ENGL 2880', 'ENGL 2890']) + ) { + return false; + } + return courseMatchesCodeOptions(course, [ + 'ENGL 2***', + 'ENGL 3***', + 'ENGL 4***', + 'ENGL 5***', + 'ENGL 6***', + ]); + }, + ], fulfilledBy: 'credits', - minCount: 40, + perSlotMinCount: [40], }, { name: 'Pre-1800', @@ -31,11 +35,13 @@ const englishRequirements: readonly CollegeOrMajorRequirement[] = [ 'before 1800 (such courses are indicated in the English course listings)', source: 'https://english.cornell.edu/majoring-and-minoring-english-cornell#requirements-for-the-major', - checker: (course: Course): boolean => - (course.catalogComments?.includes('pre-1800') ?? false) || - (course.catalogSatisfiesReq?.includes('pre-1800') ?? false), + checker: [ + (course: Course): boolean => + (course.catalogComments?.includes('pre-1800') ?? false) || + (course.catalogSatisfiesReq?.includes('pre-1800') ?? false), + ], fulfilledBy: 'credits', - minCount: 12, + perSlotMinCount: [12], }, { name: '4000 or Above', @@ -44,7 +50,7 @@ const englishRequirements: readonly CollegeOrMajorRequirement[] = [ 'https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements', checker: includesWithSingleRequirement('ENGL 4***'), fulfilledBy: 'credits', - minCount: 8, + perSlotMinCount: [8], }, { name: 'Concentration', diff --git a/src/requirements/data/majors/govt.ts b/src/requirements/data/majors/govt.ts index 66608e623..8dc7ae546 100644 --- a/src/requirements/data/majors/govt.ts +++ b/src/requirements/data/majors/govt.ts @@ -16,9 +16,8 @@ const governmentRequirements: readonly CollegeOrMajorRequirement[] = [ 'GOVT 1817', 'GOVT 1827' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2], }, { name: 'Government Coursework', @@ -28,7 +27,7 @@ const governmentRequirements: readonly CollegeOrMajorRequirement[] = [ 'https://government.cornell.edu/sites/govt/files/Majorchecklist%202017_2018%20rv%20untrckd.pdf', checker: includesWithSingleRequirement('GOVT 2***'), fulfilledBy: 'credits', - minCount: 28, + perSlotMinCount: [28], }, { name: 'Tenth Government Course', @@ -38,7 +37,7 @@ const governmentRequirements: readonly CollegeOrMajorRequirement[] = [ 'https://government.cornell.edu/sites/govt/files/Majorchecklist%202017_2018%20rv%20untrckd.pdf', checker: includesWithSingleRequirement('GOVT ****'), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Government Seminar', diff --git a/src/requirements/data/majors/hadm.ts b/src/requirements/data/majors/hadm.ts index b7a6629fa..07b9fd498 100644 --- a/src/requirements/data/majors/hadm.ts +++ b/src/requirements/data/majors/hadm.ts @@ -17,9 +17,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ ['HADM 2220'], ['HADM 3210'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [1, 1, 1, 1], }, { name: 'Employment Relations; HR; Law', @@ -27,9 +26,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSubRequirements(['HADM 1150'], ['HADM 2810'], ['HADM 3870']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Food and Beverage Management', @@ -37,9 +35,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSubRequirements(['HADM 2360'], ['HADM 3350']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Information Systems', @@ -47,9 +44,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSingleRequirement('HADM 1740'), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Management Communication', @@ -57,9 +53,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSubRequirements(['HADM 1650'], ['HADM 3650']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Operations', @@ -72,9 +67,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ ['HADM 2010'], ['HADM 3010'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [1, 1, 1, 1], }, { name: 'Properties Development and Management', @@ -82,9 +76,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSubRequirements(['HADM 2550'], ['HADM 3550']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Services Marketing', @@ -92,9 +85,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSubRequirements(['HADM 1410'], ['HADM 2430']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Strategy', @@ -102,9 +94,8 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSingleRequirement('HADM 4410'), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'SHA Electives', @@ -113,7 +104,7 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', checker: includesWithSingleRequirement('HADM 3***'), fulfilledBy: 'credits', - minCount: 14, + perSlotMinCount: [14], }, { name: 'Non-HADM Electives', @@ -130,9 +121,9 @@ const hotelAdminRequirements: readonly CollegeOrMajorRequirement[] = [ 'A minimum of 18 credits, to be taken outside SHA. 3 of these 18 credits must be FWS.', source: 'https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/', - checker: courseIsFWS, + checker: [courseIsFWS], fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Free Electives', diff --git a/src/requirements/data/majors/hist.ts b/src/requirements/data/majors/hist.ts index 2e4785df1..008edfad4 100644 --- a/src/requirements/data/majors/hist.ts +++ b/src/requirements/data/majors/hist.ts @@ -20,11 +20,12 @@ const historyRequirements: readonly CollegeOrMajorRequirement[] = [ '3 of the nine courses must be in history before 1800 ' + '(Courses that fulfill the Arts & Sciences historical breadth requirement do not necessarily fulfill the History pre-1800 requirement.)', source: 'https://history.cornell.edu/undergraduate', - checker: (course: Course): boolean => - course.catalogCourseSubfield != null && course.catalogCourseSubfield.includes('HPE'), - subRequirementProgress: 'any-can-count', + checker: [ + (course: Course): boolean => + course.catalogCourseSubfield != null && course.catalogCourseSubfield.includes('HPE'), + ], fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Seminars', diff --git a/src/requirements/data/majors/info.ts b/src/requirements/data/majors/info.ts index 7055bacc8..53b2a478c 100644 --- a/src/requirements/data/majors/info.ts +++ b/src/requirements/data/majors/info.ts @@ -15,9 +15,8 @@ const infoRequirements: readonly CollegeOrMajorRequirement[] = [ ['INFO 2450'], ['INFO 2950'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 5, + perSlotMinCount: [1, 1, 1, 1, 1], }, { name: 'Programming and Math Requirements', @@ -50,9 +49,8 @@ const infoRequirements: readonly CollegeOrMajorRequirement[] = [ 'STSCI 2200', ] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Concentration', @@ -82,9 +80,8 @@ const infoRequirements: readonly CollegeOrMajorRequirement[] = [ 'INFO 5***', 'INFO 6***' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, ]; diff --git a/src/requirements/data/majors/isst.ts b/src/requirements/data/majors/isst.ts index 99a349631..2f8581667 100644 --- a/src/requirements/data/majors/isst.ts +++ b/src/requirements/data/majors/isst.ts @@ -8,9 +8,8 @@ const isstRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/core', checker: includesWithSubRequirements(['ORIE 3300'], ['ORIE 3500']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Information Systems', @@ -21,9 +20,8 @@ const isstRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/core', checker: includesWithSubRequirements(['INFO 2300'], ['ORIE 3800'], ['INFO 3300', 'INFO 4300']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Economic, Organization, and Social Context', @@ -32,9 +30,8 @@ const isstRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/core', checker: includesWithSubRequirements(['INFO 2040'], ['INFO 2450', 'ENGRC 3350']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, { name: 'Engineering Mathematics', @@ -48,9 +45,8 @@ const isstRequirements: readonly CollegeOrMajorRequirement[] = [ ['MATH 2940'], ['MATH 2930', 'MATH 3040', 'CS 2800'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [1, 1, 1, 1], }, { name: 'Engineering Distributions', @@ -60,9 +56,8 @@ const isstRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/math', checker: includesWithSubRequirements(['ENGRD 2110'], ['ENGRD 2700']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, ]; diff --git a/src/requirements/data/majors/me.ts b/src/requirements/data/majors/me.ts index 73e414158..56cd9a782 100644 --- a/src/requirements/data/majors/me.ts +++ b/src/requirements/data/majors/me.ts @@ -8,9 +8,8 @@ const mechnicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14', checker: includesWithSingleRequirement('ENGRD 2020'), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Required Major Courses', @@ -30,9 +29,8 @@ const mechnicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ ['MAE 4272'], ['MAE 4300'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 10, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], }, { name: 'M.E. Major Electives', @@ -66,7 +64,7 @@ const mechnicalEngineeringRequirements: readonly CollegeOrMajorRequirement[] = [ 'CS 2800' ), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Technical Elective', diff --git a/src/requirements/data/majors/orie.ts b/src/requirements/data/majors/orie.ts index 50e04db78..82dd646c5 100644 --- a/src/requirements/data/majors/orie.ts +++ b/src/requirements/data/majors/orie.ts @@ -17,9 +17,8 @@ const orieRequirements: readonly CollegeOrMajorRequirement[] = [ ['ORIE 3510'], ['ORIE 4580'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 7, + perSlotMinCount: [1, 1, 1, 1, 1, 1, 1], }, { name: 'ORIE Electives', @@ -27,7 +26,7 @@ const orieRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://www.orie.cornell.edu/orie/programs/undergraduate-programs/degree-requirements', checker: includesWithSingleRequirement('ORIE 4***', 'ORIE 5***', 'ORIE 6***'), fulfilledBy: 'credits', - minCount: 9, + perSlotMinCount: [9], }, { name: 'Engineering Distribution Courses', @@ -38,9 +37,8 @@ const orieRequirements: readonly CollegeOrMajorRequirement[] = [ ['ENGRD 2***', 'ENGRD 3***'], ['ENGRI 1***'] ), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [1, 1, 1], }, { name: 'Major Approved Electives (Non–ORIE)', diff --git a/src/requirements/data/minors/bu.ts b/src/requirements/data/minors/bu.ts index 6fe9990b5..ceb5b9712 100644 --- a/src/requirements/data/minors/bu.ts +++ b/src/requirements/data/minors/bu.ts @@ -34,54 +34,48 @@ const buMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'STSCI 3110', 'SOC 3010' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Microeconomics Prerequisite', description: 'Choose one: ECON 1110 or ECON 3030 or PAM 2000', source: 'https://business.cornell.edu/programs/undergraduate/minors/business/', checker: includesWithSingleRequirement('ECON 1110', 'ECON 3030', 'PAM 2000'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Introduction to Management', description: 'Choose one: AEM 1200, ILRID 1700, NCC 5540', source: 'https://business.cornell.edu/programs/undergraduate/minors/business/', checker: includesWithSingleRequirement('AEM 1200', 'ILRID 1700', 'NCC 5540'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Introduction to Marketing', description: 'Choose one: AEM 2400, NCC 5530, HADM 2410', source: 'https://business.cornell.edu/programs/undergraduate/minors/business/', checker: includesWithSingleRequirement('AEM 2400', 'NCC 5530', 'HADM 2410'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Financial Accounting', description: 'Choose one: AEM 2210, HADM 2230, NCC 5500', source: 'https://business.cornell.edu/programs/undergraduate/minors/business/', checker: includesWithSingleRequirement('AEM 2210', 'HADM 2230', 'NCC 5500'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Finance', description: 'Choose one: AEM 2241/5241, HADM 2250, NCC 5560', source: 'https://business.cornell.edu/programs/undergraduate/minors/business/', checker: includesWithSingleRequirement('AEM 2241', 'AEM 5241', 'HADM 2250', 'NCC 5560'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, ]; diff --git a/src/requirements/data/minors/cogsci.ts b/src/requirements/data/minors/cogsci.ts index b3e0bcac9..72eb32245 100644 --- a/src/requirements/data/minors/cogsci.ts +++ b/src/requirements/data/minors/cogsci.ts @@ -7,18 +7,16 @@ const cogsciMinorRequirements: readonly CollegeOrMajorRequirement[] = [ description: 'Choose COGST 1101 or COGST 2200', source: 'https://cogsci.cornell.edu/undergraduate-minor', checker: includesWithSingleRequirement('COGST 1101', 'COGST 2200'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Lab Requirement', description: 'Choose COGST 4700 or COGST 4710', source: 'https://cogsci.cornell.edu/undergraduate-minor', checker: includesWithSingleRequirement('COGST 4700', 'COGST 4710'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Three Courses at the 3000 or 4000 Level', @@ -26,9 +24,8 @@ const cogsciMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'Three courses at the 3000- and 4000-level in at least two departments (or certain suitable 2000- level courses by petition)', source: 'https://cogsci.cornell.edu/undergraduate-minor', checker: includesWithSingleRequirement('COGST 3***', 'COGST 4***'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, ]; diff --git a/src/requirements/data/minors/cs.ts b/src/requirements/data/minors/cs.ts index ac5ba4c62..3d3dc2fa1 100644 --- a/src/requirements/data/minors/cs.ts +++ b/src/requirements/data/minors/cs.ts @@ -14,18 +14,16 @@ const csMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'ENGRD 2140', 'ECE 2400' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, { name: 'Requirement 2', description: 'CS 3110 or CS 3410 or CS 3420/ECE 3140', source: 'https://www.cs.cornell.edu/undergrad/csminor', checker: includesWithSingleRequirement('CS 3110', 'CS 3410', 'CS 3420', 'ECE 3140'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }, // TODO: Needs excludes for certain classes { @@ -33,9 +31,8 @@ const csMinorRequirements: readonly CollegeOrMajorRequirement[] = [ description: 'CS 4090, CS 4997, CS 4998, CS 4999 and seminars are excluded. CS 2800 is allowed', source: 'https://www.cs.cornell.edu/undergrad/csminor', checker: includesWithSingleRequirement('CS 2800', 'CS 3***', 'CS 4***', 'CS 5***', 'CS 6***'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 4, + perSlotMinCount: [4], }, ]; diff --git a/src/requirements/data/minors/dbme.ts b/src/requirements/data/minors/dbme.ts index e5cc7e783..e3eaef4a3 100644 --- a/src/requirements/data/minors/dbme.ts +++ b/src/requirements/data/minors/dbme.ts @@ -8,7 +8,7 @@ const dbmeMinorRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://business.cornell.edu/programs/undergraduate/minors/business-engineers/', checker: includesWithSingleRequirement('ECON 1100', 'ECON 3030', 'HADM 1410', 'PAM 2000'), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Introduction to basic business concepts', @@ -29,7 +29,7 @@ const dbmeMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'MAE 4610' ), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, // TODO: restrictions + additional class for ORIE majors { @@ -38,7 +38,7 @@ const dbmeMinorRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://business.cornell.edu/programs/undergraduate/minors/business-engineers/', checker: includesWithSingleRequirement('AEM 2210', 'HADM 2230', 'NCC 5500', 'ORIE 3150'), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Finance', @@ -46,7 +46,7 @@ const dbmeMinorRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://business.cornell.edu/programs/undergraduate/minors/business-engineers/', checker: includesWithSingleRequirement('AEM 2241', 'AEM 5241', 'HADM 2250', 'NCC 5560'), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Capstone course', @@ -54,7 +54,7 @@ const dbmeMinorRequirements: readonly CollegeOrMajorRequirement[] = [ source: 'https://business.cornell.edu/programs/undergraduate/minors/business-engineers/', checker: includesWithSingleRequirement('AEM 4660'), fulfilledBy: 'credits', - minCount: 1.5, + perSlotMinCount: [1.5], }, { name: 'Career goals', @@ -105,7 +105,7 @@ const dbmeMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'AEM 4550' ), fulfilledBy: 'credits', - minCount: 3, + perSlotMinCount: [3], }, ]; diff --git a/src/requirements/data/minors/isst.ts b/src/requirements/data/minors/isst.ts index afff43c18..08f25bb53 100644 --- a/src/requirements/data/minors/isst.ts +++ b/src/requirements/data/minors/isst.ts @@ -7,9 +7,8 @@ const isstMinorRequirements: readonly CollegeOrMajorRequirement[] = [ description: 'ENGRD 2700, ORIE 3120, ORIE 4800', source: 'https://www.orie.cornell.edu/orie/programs/undergraduate-programs/ore-minors', checker: includesWithSingleRequirement('ENGRD 2700', 'ORIE 3120', 'ORIE 4800'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, { name: '3 Courses from the following', @@ -27,9 +26,8 @@ const isstMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'ORIE 5120', 'ORIE 5770' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, ]; diff --git a/src/requirements/data/minors/math.ts b/src/requirements/data/minors/math.ts index 1c11c07b1..273652423 100644 --- a/src/requirements/data/minors/math.ts +++ b/src/requirements/data/minors/math.ts @@ -7,9 +7,8 @@ const mathMinorRequirements: readonly CollegeOrMajorRequirement[] = [ description: 'MATH 2930 and 2940', source: 'https://www.mae.cornell.edu/mae/programs/undergraduate-programs/minors', checker: includesWithSubRequirements(['MATH 2930'], ['MATH 2940']), - subRequirementProgress: 'every-course-needed', fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [1, 1], }, // FIX: don't currently have a way to show the groups { diff --git a/src/requirements/data/minors/orms.ts b/src/requirements/data/minors/orms.ts index 10752a16b..34568328c 100644 --- a/src/requirements/data/minors/orms.ts +++ b/src/requirements/data/minors/orms.ts @@ -14,18 +14,16 @@ const ormsMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'ORIE 3510', 'ORIE 4580' ), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, { name: 'Three 3000 level or higher ORIE courses', description: 'Any ORIE courses at the 3000 level or higher.', source: 'https://www.orie.cornell.edu/orie/programs/undergraduate-programs/ore-minors', checker: includesWithSingleRequirement('ORIE 3***', 'ORIE 4***', 'ORIE 5***'), - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 3, + perSlotMinCount: [3], }, ]; diff --git a/src/requirements/data/minors/psych.ts b/src/requirements/data/minors/psych.ts index 1bec5fa91..7bfbe14a8 100644 --- a/src/requirements/data/minors/psych.ts +++ b/src/requirements/data/minors/psych.ts @@ -17,7 +17,7 @@ const psychMinorRequirements: readonly CollegeOrMajorRequirement[] = [ 'PSYCH 6***' ), fulfilledBy: 'credits', - minCount: 18, + perSlotMinCount: [18], }, ]; diff --git a/src/requirements/data/requirement-data-consistency.test.ts b/src/requirements/data/requirement-data-consistency.test.ts new file mode 100644 index 000000000..8d40a5204 --- /dev/null +++ b/src/requirements/data/requirement-data-consistency.test.ts @@ -0,0 +1,49 @@ +import requirementJson from '.'; + +const allRequirementsWithIDs = [ + ...requirementJson.university.UNI.requirements.map(it => ({ + id: `College-UNI-${it.name}`, + requirement: it, + })), + ...Object.entries(requirementJson.college) + .map(([college, collegeReqs]) => + collegeReqs.requirements.map(it => ({ id: `College-${college}-${it.name}`, requirement: it })) + ) + .flat(), + ...Object.entries(requirementJson.major) + .map(([major, majorRequirement]) => + majorRequirement.requirements.map(it => ({ + id: `Major-${major}-${it.name}`, + requirement: it, + })) + ) + .flat(), + ...Object.entries(requirementJson.minor) + .map(([minor, minorRequirement]) => + minorRequirement.requirements.map(it => ({ + id: `Minor-${minor}-${it.name}`, + requirement: it, + })) + ) + .flat(), +].sort((a, b) => a.id.localeCompare(b.id)); + +allRequirementsWithIDs.forEach(({ id, requirement }) => { + it(`${id}'s checker length and perSlotMinCount length are in sync.`, () => { + switch (requirement.fulfilledBy) { + case 'self-check': + return; + case 'courses': + case 'credits': + expect(requirement.checker.length).toBe(requirement.perSlotMinCount.length); + return; + case 'toggleable': + Object.values(requirement.fulfillmentOptions).forEach(option => { + expect(option.checker.length).toBe(option.perSlotMinCount.length); + }); + return; + default: + throw new Error(); + } + }); +}); diff --git a/src/requirements/data/university/index.ts b/src/requirements/data/university/index.ts index e22550075..257d698b7 100644 --- a/src/requirements/data/university/index.ts +++ b/src/requirements/data/university/index.ts @@ -8,10 +8,9 @@ const universityRequirements: readonly CollegeOrMajorRequirement[] = [ 'one credit each semester of the first year on campus.', source: 'http://courses.cornell.edu/content.php?catoid=41&navoid=11637', allowCourseDoubleCounting: true, - checker: (course: Course): boolean => 'PE'.includes(course.subject), - subRequirementProgress: 'any-can-count', + checker: [(course: Course): boolean => 'PE'.includes(course.subject)], fulfilledBy: 'courses', - minCount: 2, + perSlotMinCount: [2], }, ]; diff --git a/src/requirements/decorated-requirements.json b/src/requirements/decorated-requirements.json index acdefa033..e450a9b97 100644 --- a/src/requirements/decorated-requirements.json +++ b/src/requirements/decorated-requirements.json @@ -8,9 +8,10 @@ "description": "All incoming freshmen are required to take two credits (two courses) of Physical Education, one credit each semester of the first year on campus.", "source": "http://courses.cornell.edu/content.php?catoid=41&navoid=11637", "allowCourseDoubleCounting": true, - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 350002, @@ -245,7 +246,9 @@ "description": "55 CALS credits are required for graduation. CALS credits include all courses from departments within CALS and courses offered in Applied Economics and Management, Biological Sciences, Biology & Society, Earth and Atmospheric Sciences, Information Science, Nutritional Science, and The Department of Statistics and Data Science.", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements", "fulfilledBy": "credits", - "minCount": 55, + "perSlotMinCount": [ + 55 + ], "courses": [ [ 350010, @@ -2113,7 +2116,9 @@ "description": "Students must complete at least six academic credits from the list of courses that fulfill distribution requirements.", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements", "fulfilledBy": "credits", - "minCount": 6, + "perSlotMinCount": [ + 6 + ], "courses": [ [ 352133, @@ -2166,7 +2171,9 @@ "description": "Complete a minimum of three academic credits of chemistry or physics. Includes all Cornell courses with the CHEM or PHYS prefix at Cornell (excluding courses that are supplemental, independent study, research, TA, internship, and First-Year Writing Seminar).", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350174, @@ -2413,9 +2420,10 @@ "name": "Quantitative Literacy", "description": "Faculty legislation requires minimum competency in quantitative literacy. This requirement can be satisfied by earning a score of 4 or 5 on the AP Calculus exam or a score of 5 on the AP Statistics exam, or transfer an approved calculus or statistics course with a minimum letter grade of “C” or better; or take an approved calculus or statistics course at Cornell.", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350154, @@ -2605,9 +2613,17 @@ "name": "Social Sciences and Humanities", "description": "Students must complete four courses of 3 or more credits each from the following seven categories of courses in the humanities and social sciences. At least one course category MUST be completed in three different categories. No more than two courses in the same department will be counted toward the distribution requirement. To view a searchable list of courses, please search for courses that fulfill distribution requirements.", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "minNumberOfSlots": 4, "courses": [ [ 350234, @@ -4769,9 +4785,10 @@ "name": "Human Diversity (D)", "description": "At least one course category MUST be completed in three different categories. Human Diversity (D) is a required category and MUST be completed.", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350010, @@ -4835,7 +4852,9 @@ "description": "9 credits total, of which at least six must be in written expression. Oral expression is not required by the college, but may be required for some majors. If not required, all nine credits may be in written expression. Writing in the Majors courses do not count towards the writing requirement.", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements", "fulfilledBy": "credits", - "minCount": 9, + "perSlotMinCount": [ + 9 + ], "courses": [ [ 350160, @@ -5028,7 +5047,10 @@ "description": "At least six credits must be in written expression.", "source": "https://cals.cornell.edu/undergraduate-students/student-services/degree-requirements/graduation-requirements/distribution-requirements", "fulfilledBy": "credits", - "minCount": 6, + "perSlotMinCount": [ + 6 + ], + "allowCourseDoubleCounting": true, "courses": [ [ 350160, @@ -5229,7 +5251,9 @@ "description": "100 credits in Arts & Sciences are required. Students can take more than 20 credits outside of the College as long as they take 100 credits within; they can also take all their credits in Arts & Sciences and accumulate more than 120. Note: AP, IB, and A-Level credits count toward the 120 total credits but not toward the 100 A&S credits.", "source": "https://as.cornell.edu/education/old-degree-requirements", "fulfilledBy": "credits", - "minCount": 100, + "perSlotMinCount": [ + 100 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -9466,7 +9490,9 @@ "description": "A 5 on either the AP English Composition or Literature exam, or a 7 on the IB HL English Literature or Language exam will count towards one of these seminars. First-year students should plan to take an FWS during their first semester at Cornell.", "source": "https://as.cornell.edu/education/old-degree-requirements", "fulfilledBy": "credits", - "minCount": 6, + "perSlotMinCount": [ + 6 + ], "courses": [ [ 11, @@ -9710,8 +9736,9 @@ "Option 1": { "description": "Complete one intermediate course of 3 or more credits at Cornell at the 2000 level or above.", "counting": "courses", - "subRequirementProgress": "any-can-count", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351028, @@ -9840,7 +9867,9 @@ "Option 2": { "description": "Complete at least 11 credits of study (2 or 3 semesters) in a single foreign language taken in the appropriate sequence at Cornell.", "counting": "credits", - "minCount": 11, + "perSlotMinCount": [ + 11 + ], "courses": [ [ 351015, @@ -10502,12 +10531,15 @@ } }, { - "name": "Physical & Biological Sceiences (PBS-AS/PBSS-AS)", - "description": "Students must take 2 courses in Physical & Biological Sciences (PBS/PBSS-AS).", + "name": "PBS and MQR courses", + "description": "Students must take 2 courses in Physical & Biological Sciences (PBS/PBSS-AS). Students must take 1 course in Mathematics & Quantitative Reasoning (MQR-AS). Students must take 1 course that is either in PBS-AS or MQR-AS.", "source": "https://as.cornell.edu/education/old-degree-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2, + 1, + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -10768,18 +10800,7 @@ 371143, 371360, 371370 - ] - ] - }, - { - "name": "Mathematics & Quantitative Reasoning (MQR-AS)", - "description": "Students must take 1 course in Mathematics & Quantitative Reasoning (MQR-AS).", - "source": "https://as.cornell.edu/education/old-degree-requirements", - "subRequirementProgress": "any-can-count", - "fulfilledBy": "courses", - "minCount": 1, - "allowCourseDoubleCounting": true, - "courses": [ + ], [ 350154, 350163, @@ -10882,17 +10903,7 @@ 370800, 371315, 371479 - ] - ] - }, - { - "name": "PBS-AS or MQR-AS", - "description": "Students must take 1 course that is either in PBS-AS or MQR-AS", - "source": "https://as.cornell.edu/education/old-degree-requirements", - "subRequirementProgress": "any-can-count", - "fulfilledBy": "courses", - "minCount": 1, - "courses": [ + ], [ 350154, 350163, @@ -11259,9 +11270,14 @@ "name": "Distribution Requirement", "description": "Five Arts & Sciences courses of 3 or more credits from at least 4 of the following social sciences, humanities, and arts categories: CA-AS, HA-AS, KCM-AS, LA-AS, SBA-AS", "source": "https://as.cornell.edu/education/old-degree-requirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -12801,9 +12817,10 @@ "name": "Geographic Breadth Requirement (GB)", "description": "One course that focuses on an area or a people other than those of the United States, Canada, or Europe. Courses fulfilling this requirement are marked with a GB/GHB in the Class Roster.", "source": "https://as.cornell.edu/education/old-degree-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -13332,9 +13349,10 @@ "name": "Historic Breadth Requirement (HB)", "description": "One course that focuses on an historic period before the 20th century. Courses fulfilling this requirement are marked with an HB/GHB in the Class Roster.", "source": "https://as.cornell.edu/education/old-degree-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -13776,9 +13794,12 @@ "name": "Mathematics", "description": "MATH 1910, 1920, 2930 or 2940, and a mathematics course chosen by the Major.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 352255 @@ -13796,9 +13817,11 @@ "name": "Physics", "description": "PHYS 1112 and 2213, and, depending on the Major, either PHYS 2214 or a designated mathematics or science course.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 355146 @@ -13812,9 +13835,10 @@ "name": "Chemistry", "description": "CHEM 2090. Majors in Chemical Engineering or those planning on a health-related career should take CHEM 2090 and then 2080. Students in Environmental Engineering should take CHEM 2090 and CHEM 1570/3570. Earth and Atmospheric Sciences majors should take CHEM 2090 and then 2080/1570.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 359187 @@ -13825,9 +13849,10 @@ "name": "First-Year Writing Seminars", "description": "All students are required to take two first-year writing seminars.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 11, @@ -14066,9 +14091,10 @@ "name": "Computing", "description": "CS 1110, 1112, 1114, or 1115.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 358525, @@ -14081,7 +14107,9 @@ "description": "One introduction to engineering (ENGRI) course.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 354919, @@ -14111,9 +14139,10 @@ "name": "Engineering Distribution", "description": "Two different category distribution courses (ENGRD), one of which may be required by the Major.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 352313, @@ -14145,9 +14174,10 @@ "name": "Liberal Studies Distribution: 6 courses", "description": "Liberal arts commonly include courses in the humanities. A minimum of six courses must be taken. At least two courses must be at the 2000 level or higher.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/advising/liberal-studies", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 6, + "perSlotMinCount": [ + 6 + ], "courses": [ [ 350010, @@ -15985,10 +16015,24 @@ "name": "Liberal Studies Distribution: 3 categories", "description": "In addition to six courses, the liberal studies courses must be from 3 categories.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/advising/liberal-studies", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "minNumberOfSlots": 3, "allowCourseDoubleCounting": true, - "minCount": 3, "courses": [ [ 350636, @@ -18946,8 +18990,10 @@ "description": "In addition to six courses, the liberal studies distribution must total a minimum of 18 credits.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/advising/liberal-studies", "fulfilledBy": "credits", + "perSlotMinCount": [ + 18 + ], "allowCourseDoubleCounting": true, - "minCount": 18, "courses": [ [ 350010, @@ -20792,80 +20838,35 @@ "name": "Engineering Communications", "description": "An engineering communications course must be taken as an engineering distribution, liberal studies, Advisor-approved Elective, or Major course. Students can fulfill the upper-level engineering communications requirement in one of the six ways.", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/engineering-communications-program/technical", - "allowCourseDoubleCounting": true, - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], + "allowCourseDoubleCounting": true, "courses": [ [ - 355623 - ], - [ - 360971 - ], - [ - 355624 - ], - [ - 355625 - ], - [ - 358553 - ], - [ - 358553 - ], - [ - 350255 - ], - [ - 354942 - ], - [ - 352156 - ], - [ - 352183 - ], - [ - 355233 - ], - [ - 371145 - ], - [], - [ - 366630 - ], - [], - [ - 354831 - ], - [ - 361548 - ], - [ - 367481 - ], - [ - 367848 - ], - [], - [ - 367847 - ], - [ - 367922 - ], - [ - 367485 - ], - [ - 353896 - ], - [ + 350255, + 352156, + 352183, + 353896, 353898, - 353899 + 353899, + 354831, + 354942, + 355233, + 355623, + 355624, + 355625, + 358553, + 360971, + 361548, + 366630, + 367481, + 367485, + 367847, + 367848, + 367922, + 371145 ] ] } @@ -20879,7 +20880,9 @@ "description": "Students must complete a minimum of 43 Human Ecology credits from College Distribution, Major Requirements and electives.", "source": "https://www.human.cornell.edu/academics/policies/requirements", "fulfilledBy": "credits", - "minCount": 43, + "perSlotMinCount": [ + 43 + ], "courses": [ [ 350003, @@ -21465,9 +21468,18 @@ "name": "Core Requirements", "description": "Students are required to fulfill the following core requirements for a letter grade:", "source": "https://www.ilr.cornell.edu/student-experience/curriculum-requirements/undergraduate-requirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 9, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 358955 @@ -21503,7 +21515,9 @@ "description": "Students are required to fulfill the following writing requirements for a letter grade:", "source": "https://www.ilr.cornell.edu/student-experience/curriculum-requirements/undergraduate-requirements", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 11, @@ -21742,9 +21756,10 @@ "name": "ILR Advance Writing", "description": "Courses must be taken for a letter grade in order to count toward the ILR Requirements", "source": "https://www.ilr.cornell.edu/student-experience/curriculum-requirements/undergraduate-requirements/ilr-advanced-writing-courses", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 352758, @@ -21785,7 +21800,9 @@ "description": "55 CALS credits are required for graduation. CALS credits include all courses from departments within CALS and courses offered in Applied Economics and Management, Biological Sciences, Biology & Society, Earth and Atmospheric Sciences, Information Science, Nutritional Science, and The Department of Statistics and Data Science.", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/distribution/", "fulfilledBy": "credits", - "minCount": 55, + "perSlotMinCount": [ + 55 + ], "courses": [ [ 350010, @@ -23658,9 +23675,16 @@ "name": "Management Requirements", "description": "AEM 3200 and AEM 3230 are optional for the following three concentrations: applied economics; environmental, energy, and resource economics; and international trade and development.", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 7, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 364642 @@ -23689,9 +23713,12 @@ "name": "Economics Requirements", "description": "ECON 1110, ECON 1120, AND AEM 2600. For students concentrating in environmental, energy, and resource economics, ECON 3030 is required instead of AEM 2600.", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 350025 @@ -23709,9 +23736,12 @@ "name": "Quantitative Methods Requirements", "description": "AEM 2100, MATH 1110 OR MATH 1120, AND AEM 2010", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 350500 @@ -23730,7 +23760,9 @@ "description": "At least 3 elective credits from the following.", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350163, @@ -23761,9 +23793,10 @@ "name": "Grand Challenges Reqiurement Part 1: Written expression course", "description": "Sophomore year: 3 credits. Focus: Critical thinking. These course options are centered around contemporary global issues and will help you learn communication, business analysis, and critical thinking skills as you develop cultural awareness. Available courses may vary per semester. You’ll choose one of the following:", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350489, @@ -23778,9 +23811,10 @@ "name": "Grand Challenges Reqiurement Part 2: Pre-Project Weekend Immersion", "description": "Junior year: 1.5 credits. Focus: Working as part of a team", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 370844 @@ -23791,9 +23825,10 @@ "name": "Grand Challenges Reqiurement Part 3: Project Course", "description": "Senior year, 3 credits. Focus: Local and global community involvement", "source": "https://dyson.cornell.edu/programs/undergraduate/degree-requirements/core/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 370852 @@ -23813,9 +23848,13 @@ "name": "Introductory Biology Cluster", "description": "Take 2 of the following 3: BIOMG 1350, BIOG 1440 OR BIOG 1445, BIOEE 1610 OR BIOSM 1610", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1, + 1 + ], + "minNumberOfSlots": 2, "courses": [ [ 363586 @@ -23834,9 +23873,10 @@ "name": "Investigative Laboratory", "description": "BIOG 1500 OR BIOSM 1500", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 363759, @@ -23848,9 +23888,10 @@ "name": "Evolutionary Biology and Diversity", "description": "BIOEE 1780 OR BIOEE 1781 OR BIOSM 1780", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 354153, @@ -23868,8 +23909,10 @@ "Option 1": { "description": "CHEM 2070 AND CHEM 2080", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 351265 @@ -23882,8 +23925,9 @@ "Option 2": { "description": "CHEM 2150", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351273 @@ -23896,9 +23940,11 @@ "name": "College Mathematics", "description": "Two courses. One semester of calculus (MATH 1106 OR MATH 1110) Another course selected from: (MATH 1120 OR MATH 1910) OR MATH 1105 OR one course in statistics (STSCI 2150 OR BTRY 3010 are preferred)", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 352111, @@ -23922,9 +23968,14 @@ "name": "Organic Chemistry", "description": "CHEM 1570 OR CHEM 3570 & 3580 OR CHEM 3590 & 3600 OR CHEM 3530", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 2, + 2, + 1 + ], + "minNumberOfSlots": 1, "courses": [ [ 359185 @@ -23946,9 +23997,13 @@ "name": "Physics", "description": "PHYS 1101 & 1102 OR PHYS 2207 & 2208 OR PHY 1112 & 2213", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2, + 2, + 2 + ], + "minNumberOfSlots": 1, "courses": [ [ 355142, @@ -23968,9 +24023,11 @@ "name": "Genetics and Genomics", "description": "Lecture must be taken either concurrently or before the laboratory", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 353121 @@ -23984,9 +24041,10 @@ "name": "Biochemistry and Molecular Biology Part 1", "description": "BIOMG 3300 OR BIOMG 3350 OR BIOMG 3310", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 353357, @@ -23999,9 +24057,10 @@ "name": "Biochemistry and Molecular Biology Part 2", "description": "BIOMG 3300 OR BIOMG 3350 OR BIOMG 3320", "source": "http://courses.cornell.edu/preview_program.php?catoid=36&poid=17535", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 353357, @@ -24028,9 +24087,10 @@ "name": "Engineering Distriubtions", "description": "ENGRD 2202. ENGRD 2020 is recommended and satisfies the Common Curriculum distribution requirement and also fulfills a required Major course. It is best taken during semester 3 and must be completed before semester 5", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19808", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -24042,9 +24102,15 @@ "name": "Core Courses Part 1", "description": "BIOMG 1350, BME 2010, BME 2110, BME 2210, BME 2310, ENGRD 2020, and BTRY 3010. CEE 3040 or ENGRD 2700 can be taken instead of BTRY 3010.", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19808", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 6, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 363586 @@ -24072,9 +24138,16 @@ "name": "Core Courses Part 2", "description": "BME 3010, BME 3020, BME 3030, BME 4010, BME 4020, BME 4080, BME 4090", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19808", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 7, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 361173 @@ -24108,8 +24181,12 @@ "Molecular, Cellular, and Systems Engineering (MCSE)": { "description": "Must take CHEM 1570, BME 3110, BME 4190, and take 6 elective courses from the following courses.", "counting": "courses", - "subRequirementProgress": "any-can-count", - "minCount": 13, + "perSlotMinCount": [ + 1, + 1, + 1, + 6 + ], "courses": [ [ 359185 @@ -24134,8 +24211,12 @@ "Biomedical Materials and Drug Delivery (BMDD)": { "description": "Must take BME 3210, BME 4190 or BME 4490, CHEM 1570, and take 6 elective courses from the following courses.", "counting": "courses", - "subRequirementProgress": "any-can-count", - "minCount": 13, + "perSlotMinCount": [ + 1, + 1, + 1, + 6 + ], "courses": [ [ 367708 @@ -24164,8 +24245,12 @@ "Biomedical Imaging and Instrumentation (BMII)": { "description": "Must take BME 3310, BME 4390, PHYS 2214, and take 6 elective courses from the following courses.", "counting": "courses", - "subRequirementProgress": "any-can-count", - "minCount": 13, + "perSlotMinCount": [ + 1, + 1, + 1, + 6 + ], "courses": [ [ 368737 @@ -24191,8 +24276,12 @@ "Biomedical Mechanics and Mechanobiology (BMMB)": { "description": "Must take BME 3410, BME 4490, PHYS 2214, and take 6 elective courses from the following courses.", "counting": "courses", - "subRequirementProgress": "any-can-count", - "minCount": 13, + "perSlotMinCount": [ + 1, + 1, + 1, + 6 + ], "courses": [ [ 368742 @@ -24229,9 +24318,11 @@ "name": "Engineering Distriubtions", "description": "ENGRD 2020 and ENGRD 2600 or ENGRD 2510", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 358608 @@ -24246,9 +24337,10 @@ "name": "Intro Bio", "description": "Choose 2 of the following 4: BIOMG 1350, BIOG 1440, BIOG 1445, and BIOEE/BIOSM 1610", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 363586, @@ -24261,9 +24353,15 @@ "name": "Required Major Courses", "description": "Major requirements for BE: BIOG/BIOSM 1500, BEE 3500, BEE 3310, BEE 3400, BEE 3600, and BEE 4500", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 6, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [], [ @@ -24287,9 +24385,11 @@ "name": "Biochemistry", "description": "BIOMG 3300, BIOMG 3330, BIOMG 3350, or BIOMG 3310 and BIOMG 3320", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 353357, @@ -24312,9 +24412,11 @@ "name": "Engineering Statistics", "description": "BEE 2220 or ENGRD 2210 or CHEME 3130 or MSE 3030 and engineering statistics preferably before semester 6. CEE 3040 is the preferred version of statistics.", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 350193, @@ -24332,9 +24434,10 @@ "name": "BE Focus Area Elective", "description": "BE Focus Area Electives must include a BEE capstone design course. See beadvised.bee.cornell.edu for a current list of approved courses. In place of one focus area course, students may use up to 4 credits of research, project team, teaching, or independent study taken in an engineering department towards the engineering credits in category 8.", "source": "https://beadvised.bee.cornell.edu/full-list-of-focus-area-courses/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 4 + ], "courses": [ [ 350174, @@ -24386,9 +24489,11 @@ "name": "Engineering Distribution", "description": "ENGRD 2020 is required. For the second engineering distribution course, one of the following is recommended: ENGRD 2610, ENGRD 2210, ENGRD 2110, ENGRD 2510", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19826", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -24406,9 +24511,18 @@ "name": "Core Courses", "description": "MAE 2030 or CEE 4780, ENGRD 3200, CEE 3040, CEE 3230, CEE 3310, CEE 3410, BEE 2510, CEE 3610, and CEE 3710.ENGRD 2610, ENGRD 2210, ENGRD 2110, ENGRD 2510", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19826", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 9, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 358610, @@ -24444,9 +24558,10 @@ "name": "Capstone Design Elective", "description": "Take CEE 4400, CEE 4640, CEE 4730, CEE 4350, CEE 4410, CEE 4590, CEE 4650, CEE 4660, or CEE 4740.", "source": "https://www.cee.cornell.edu/cee/programs/undergraduate-programs/civil-engineering-major/design-courses-and-major-approved", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350788, @@ -24464,9 +24579,10 @@ "name": "Two Design Electives", "description": "Take 2 of the following electives: CEE 4210, CEE 4565, BEE 4730, CEE 4110, CEE 4520, BEE 4760, CEE 4750, CEE 6370, MSE 5150", "source": "https://www.cee.cornell.edu/cee/programs/undergraduate-programs/civil-engineering-major/design-courses-and-major-approved", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 352156, @@ -24485,9 +24601,10 @@ "name": "Two Major-Approved Electives", "description": "Take 2 of the following electives", "source": "https://www.cee.cornell.edu/cee/programs/undergraduate-programs/civil-engineering-major/design-courses-and-major-approved", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 350753, @@ -24539,8 +24656,10 @@ "Option 1": { "description": "CHEM 2090 AND CHEM 2080", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 359187 @@ -24553,8 +24672,9 @@ "Option 2": { "description": "CHEM 2150 with AP credit", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351273 @@ -24568,9 +24688,13 @@ "name": "Semester 3", "description": "MATH 2930, PHYS 2213, CHEM 3890, and ENGRD 2190", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19817", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 1, + 1, + 1, + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -24591,9 +24715,13 @@ "name": "Semester 4", "description": "MATH 2940 or CEE 3040 or ENGRD 2700, CHEME 3230, CHEM 3090, and CHEM 2900.", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19817", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 1, + 1, + 1, + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -24619,8 +24747,11 @@ "AP/IB Credit": { "description": "A score of 5 on the CEEB AP Biology exam or a score of 7 on the IB Higher Level exam", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [], [], @@ -24632,8 +24763,9 @@ "CHEME 2880": { "description": "CHEME 2880", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 358533 @@ -24643,25 +24775,36 @@ "CHEME 5430": { "description": "CHEME 5430", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350174 ] ] }, - "8 credits of pre-med biology sequence": { - "description": "Take BIOG 1500, BIOMG 1350, and BIOG 1440. Or take BIOG 1107, BIOG 1108, and BIOG 1500", + "8 credits of pre-med biology sequence: option 1": { + "description": "Take BIOG 1500, BIOMG 1350, and BIOG 1440", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 363586, 363758, 363759 - ], + ] + ] + }, + "8 credits of pre-med biology sequence: option 2": { + "description": "Take BIOG 1107, BIOG 1108, and BIOG 1500", + "counting": "courses", + "perSlotMinCount": [ + 3 + ], + "courses": [ [ 363759 ] @@ -24670,8 +24813,9 @@ "BIOMI 2900": { "description": "BIOMI 2900", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 353707 @@ -24681,8 +24825,9 @@ "BIOMG 3300 or BIOMG 3350": { "description": "BIOMG 3300 or BIOMG 3350", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 353357, @@ -24693,8 +24838,10 @@ "BIOMG 3310 and BIOMG 3320": { "description": "BIOMG 3310 and BIOMG 3320", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 354876 @@ -24710,9 +24857,14 @@ "name": "Semester 5", "description": "CS 1112, CHEM 3570 or CHEM 3530 or CHEM 3590, CHEM 2510, CHEME 3130, and CHEME 3240.", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19817", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "allowCourseDoubleCounting": true, "courses": [ [ @@ -24738,9 +24890,14 @@ "name": "Semester 6", "description": "Three credits of advanced CHEME electives, CHEME 3010, CHEME 3320, CHEME 3720, CHEME 3900", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19817", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 350174, @@ -24779,9 +24936,11 @@ "name": "Semester 7", "description": "CHEME 4320 and three credits of advanced CHEME electives", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19817", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 350255 @@ -24813,9 +24972,14 @@ "name": "Semester 8", "description": "CHEME 4620 or CHEME 4930", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19817", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 358525 @@ -24856,8 +25020,13 @@ "description": "COMM 1101, COMM 1300, COMM 2010, COMM 2310, COMM 2820", "source": "https://communication.cals.cornell.edu/undergraduate-program/major-requirements/", "fulfilledBy": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 360988 @@ -24881,8 +25050,9 @@ "description": "6 credits/2 courses in COMM 2200, COMM 2450, COMM 2760, or COMM 2850", "source": "https://communication.cals.cornell.edu/undergraduate-program/major-requirements/", "fulfilledBy": "courses", - "subRequirementProgress": "any-can-count", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 352879, @@ -24897,7 +25067,9 @@ "description": "Students must take six credits (two courses) of coursework within their declared Focus Area at the 3100+ level.", "source": "https://communication.cals.cornell.edu/undergraduate-program/major-requirements/", "fulfilledBy": "credits", - "minCount": 6, + "perSlotMinCount": [ + 6 + ], "courses": [ [ 352898, @@ -24971,7 +25143,9 @@ "description": "Students must complete 9 additional credit hours at the 3100+ level.* Electives can come from any of the focus area lists. A student may elect to fulfill 3 of these credit hours by taking a third focus area introductory course. A maximum of 3 credits in either 4970 or 4990 (combined) can be counted toward the upper level major requirements. Refer to the Course and Time Roster for the most up-to-date offerings. ", "source": "https://communication.cals.cornell.edu/undergraduate-program/major-requirements/", "fulfilledBy": "credits", - "minCount": 15, + "perSlotMinCount": [ + 15 + ], "courses": [ [ 352898, @@ -25019,7 +25193,9 @@ "description": "Three credits in the COMM 30XX range courses", "source": "https://communication.cals.cornell.edu/undergraduate-program/major-requirements/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 352940, @@ -25036,9 +25212,10 @@ "name": "Introductory Statistics Class", "description": "Students must take an introductory statistics class, such as PAM 2100, AEM 2100, ILRST 2100, etc. or a score of 5 in AP statistics", "source": "https://communication.cals.cornell.edu/undergraduate-program/major-requirements/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350154, @@ -25064,127 +25241,19 @@ ], "requirements": [ { - "name": "Distribution Requirements: MQR", - "description": "At least one class must be classified as mathematics and quantitative reasoning (MQR)", - "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "any-can-count", - "fulfilledBy": "courses", - "minCount": 1, - "courses": [ - [ - 350154, - 350163, - 350173, - 350359, - 350429, - 350486, - 350842, - 350862, - 351674, - 352104, - 352107, - 352111, - 352116, - 352120, - 352240, - 352245, - 352255, - 352257, - 352259, - 352260, - 352263, - 352270, - 352274, - 352284, - 352288, - 352295, - 352307, - 352308, - 352319, - 352337, - 352338, - 352340, - 352359, - 352361, - 352363, - 352367, - 352371, - 352378, - 352385, - 352387, - 352393, - 352396, - 352403, - 352408, - 352413, - 352417, - 352428, - 352433, - 352440, - 352443, - 352450, - 352453, - 352495, - 353732, - 353862, - 354066, - 354067, - 354665, - 355025, - 355653, - 357513, - 357514, - 357900, - 358525, - 358526, - 358546, - 358552, - 358556, - 358808, - 358881, - 358896, - 359058, - 359061, - 359062, - 359438, - 359541, - 360952, - 362277, - 364154, - 364513, - 364531, - 365098, - 365141, - 365785, - 365790, - 365817, - 367041, - 367628, - 368194, - 368472, - 368700, - 369395, - 369675, - 369746, - 370151, - 370307, - 370464, - 370579, - 370800, - 371315, - 371479 - ] - ] - }, - { - "name": "Distribution Requirements: PBS", - "description": "At least two classes must be classified as PBS", - "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "any-can-count", + "name": "PBS and MQR courses", + "description": "Students must take 2 courses in Physical & Biological Sciences (PBS/PBSS-AS). Students must take 1 course in Mathematics & Quantitative Reasoning (MQR-AS). Students must take 1 course that is either in PBS-AS or MQR-AS.", + "source": "https://as.cornell.edu/education/old-degree-requirements", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2, + 1, + 1 + ], + "allowCourseDoubleCounting": true, "courses": [ [ + 350215, 350710, 350718, 350726, @@ -25197,6 +25266,7 @@ 351133, 351138, 351139, + 351246, 351265, 351269, 351273, @@ -25212,12 +25282,16 @@ 351357, 351360, 351363, + 351490, 351591, + 351619, + 351649, 351661, 351716, 351750, 351757, 351766, + 351914, 352133, 352525, 352526, @@ -25335,7 +25409,9 @@ 357656, 357658, 357679, + 357754, 357827, + 358165, 358839, 358840, 358841, @@ -25352,6 +25428,7 @@ 360929, 360930, 360933, + 360955, 360974, 361023, 361059, @@ -25361,6 +25438,7 @@ 361108, 361175, 361187, + 361224, 361466, 361625, 361722, @@ -25370,10 +25448,13 @@ 363210, 363471, 363472, + 363551, 363586, 363618, 363667, + 363722, 363758, + 363836, 363899, 364016, 364290, @@ -25411,10 +25492,13 @@ 367841, 367845, 367858, + 367910, 368418, + 368631, 368688, 368751, 368762, + 368892, 369090, 369181, 369496, @@ -25424,18 +25508,112 @@ 370286, 370415, 371143, + 371360, 371370 - ] - ] - }, - { - "name": "Distribution Requirements: MQR OR PBS", - "description": "At least one class must be classified as MQR or PBS", - "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "any-can-count", - "fulfilledBy": "courses", - "minCount": 1, - "courses": [ + ], + [ + 350154, + 350163, + 350173, + 350359, + 350429, + 350486, + 350842, + 350862, + 351674, + 352104, + 352107, + 352111, + 352116, + 352120, + 352240, + 352245, + 352255, + 352257, + 352259, + 352260, + 352263, + 352270, + 352274, + 352284, + 352288, + 352295, + 352307, + 352308, + 352319, + 352337, + 352338, + 352340, + 352359, + 352361, + 352363, + 352367, + 352371, + 352378, + 352385, + 352387, + 352393, + 352396, + 352403, + 352408, + 352413, + 352417, + 352428, + 352433, + 352440, + 352443, + 352450, + 352453, + 352495, + 353732, + 353862, + 354066, + 354067, + 354665, + 355025, + 355653, + 357513, + 357514, + 357900, + 358525, + 358526, + 358546, + 358552, + 358556, + 358808, + 358881, + 358896, + 359058, + 359061, + 359062, + 359438, + 359541, + 360952, + 362277, + 364154, + 364513, + 364531, + 365098, + 365141, + 365785, + 365790, + 365817, + 367041, + 367628, + 368194, + 368472, + 368700, + 369395, + 369675, + 369746, + 370151, + 370307, + 370464, + 370579, + 370800, + 371315, + 371479 + ], [ 350154, 350163, @@ -25802,9 +25980,10 @@ "name": "Distribution Requirements: 5 Courses", "description": "Must be selected from at least four of these five categories (i.e., CA, HA, KCM, LA, and SBA).No more than three of these five courses can be taken in any one department.", "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 5 + ], "courses": [ [ 350010, @@ -27139,9 +27318,14 @@ "name": "Core Classes", "description": "CRP 1100, CRP 1101, CRP 2000, CRP 2010, CRP 3210", "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 350054 @@ -27164,9 +27348,10 @@ "name": "Microeconomics", "description": "Choose one course: AEM 2500 OR CRP 4040 OR ECON 1110 OR ECON 3030 OR PAM 2000", "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350025, @@ -27181,9 +27366,10 @@ "name": "Statistics", "description": "Choose one course: AEM 2100, AEM 3100, AEM 4100, ECON 3130, ECON 3140, ILRST 2100, MATH 1710MATH 4710, PAM 2100, PAM 2101, STSCI 2100, STSCI 3080", "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350154, @@ -27204,9 +27390,10 @@ "name": "Five CRP Classes", "description": "Take five additional CRP classes at the 3000-level or higher, for a minimum of 3 credits each", "source": "http://courses.cornell.edu/preview_program.php?catoid=31&poid=15145", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 5 + ], "courses": [ [ 350119, @@ -27345,9 +27532,11 @@ "description": "CS 111x (CS 1110, 1112, 1114, or 1115) and CS 2110 (or CS 2112) or equivalent.", "source": "https://www.cs.cornell.edu/undergrad/csmajor", "allowCourseDoubleCounting": true, - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 358525, @@ -27363,9 +27552,14 @@ "name": "Computer Science Core", "description": "CS 2800 or CS 2802, CS 3110, CS 3410 or CS 3420, CS 4410, and CS 4820", "source": "https://www.cs.cornell.edu/undergrad/csmajor", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 358552, @@ -27390,9 +27584,10 @@ "name": "CS Electives", "description": "Three 4000+ CS electives each at 3 credits. CS 4090, CS 4998, and CS 4998 are NOT allowed.", "source": "http://www.cs.cornell.edu/undergrad/rulesandproceduresengineering/choosingyourelectives", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 352385, @@ -27442,9 +27637,10 @@ "name": "CS Practicum or Project", "description": "CS practicums (CS 4xx1) or CS 3152, CS 4152, CS 4154, CS 4740, CS 4752, CS 5150, CS 5152, CS 5412, CS 5414, CS 5431, CS 5625, or CS 5643.", "source": "http://www.cs.cornell.edu/undergrad/rulesandproceduresengineering/choosingyourelectives", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 358571, @@ -27471,8 +27667,9 @@ "source": "https://www.cs.cornell.edu/undergrad/csmajor/technicalelectives", "checkerWarning": "We do not check that the courses are considered technical.", "fulfilledBy": "courses", - "subRequirementProgress": "any-can-count", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350014, @@ -28811,9 +29008,10 @@ "description": "Must take BTRY 3080, CS 4850, ECE 3100, ECON 3130, ENGRD 2700, or MATH 4710.", "source": "https://www.cs.cornell.edu/undergrad/csmajor", "allowCourseDoubleCounting": true, - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350359, @@ -28837,9 +29035,20 @@ "name": "Core Courses", "description": "Take all of the following: DEA 1050, DEA 1101, DEA 1110, DEA 1150, DEA 1500, DEA 2030, DEA 2510, DEA 2730, DEA 3590, DEA 4040, DEA 5304", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 11, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 366899 @@ -28880,9 +29089,10 @@ "name": "DEA Thematic Courses", "description": "Three out of the 9 must be studio thematic courses. Students must take at least one 2000-level studio. Students may not take more than 2 studios in one semester, this includes both DEA and non-DEA studios. Enrollment in 2 studios simultaneously requires approval from both studio instructors. DEA 4990 can fall under any of the three DEA Thematics.", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 9, + "perSlotMinCount": [ + 9 + ], "courses": [ [ 351518, @@ -28920,9 +29130,10 @@ "name": "Research Methods Course", "description": "Choose one of the following courses: DEA 3550, ILROB 4710, PAM 3120", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351497, @@ -28935,9 +29146,10 @@ "name": "Human Development or Psychology", "description": "Choose one of the following courses: HD 1150, HC 1170, PSYCH 1101", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351438, @@ -28949,9 +29161,10 @@ "name": "Introductory Microeconomics", "description": "ECON 1110", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350025 @@ -28962,9 +29175,10 @@ "name": "Humanities", "description": "Choose any course with the Course Distribution HA, LA or CA.", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350010, @@ -30276,9 +30490,10 @@ "name": "Statistics", "description": "Must be taken at Cornell, AP Statistics is not accepted. Choose one of the following: PAM 2100, AEM 2100, ILRST/STSCI 2100, or PSYCH 2500", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350154, @@ -30297,8 +30512,9 @@ "Biology": { "description": "Take 1: BIOG 1140, BIOG 1440, BIOMG 1350, BIOEE 1610, BIOG 1445, or 5 on AP Biology", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 354148, @@ -30312,8 +30528,9 @@ "Chemistry": { "description": "Take 1: CHEM 1560, CHEM 2070, CHEM 2080, or 5 on AP Chemistry", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351265, @@ -30325,8 +30542,9 @@ "Physics": { "description": "Take 1: PHYS 1101, PHYS 2207, PHYS 1102, PHYS 2208, or 5 on AP Physics", "counting": "courses", - "subRequirementProgress": "every-course-needed", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 355142, @@ -30343,7 +30561,9 @@ "description": "Choose any 3 credit course with a PBS, BIOLS-AG, or BIONLS-AG Course Distribution.", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350215, @@ -30640,7 +30860,9 @@ "description": "Any course with the Course Distribution PBS, BIOLS-AG, BIONLS-AG, SBA, KCM, MQR, LA, CA, or HA. Language courses may count here.", "source": "http://courses.cornell.edu/preview_program.php?catoid=41&poid=19856#deamajorrequirements", "fulfilledBy": "credits", - "minCount": 6, + "perSlotMinCount": [ + 6 + ], "courses": [ [ 350010, @@ -32835,9 +33057,12 @@ "name": "Admission to the Major", "description": "Before applying for admission to the Economics Major, students must complete ECON 1110, ECON 1120, and MATH 1110 (or equivalents).", "source": "https://economics.cornell.edu/major", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 350025 @@ -32854,9 +33079,13 @@ "name": "Core Economics", "description": "All students must take four core economics courses: ECON 3030, ECON 3040, ECON 3110 or ECON 3130, and ECON 3120 or ECON 3140.", "source": "https://economics.cornell.edu/major", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 1, + 1, + 1, + 1 + ], "courses": [ [ 350335 @@ -32878,9 +33107,10 @@ "name": "4000-level Courses", "description": "All students must take at least three courses at the 4000-level or higher.", "source": "https://economics.cornell.edu/major", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350486, @@ -32920,9 +33150,10 @@ "name": "Basic Requirements", "description": "Twelve courses listed by the Department of Economics, or approved by the student’s major advisor", "source": "https://economics.cornell.edu/major", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 12, + "perSlotMinCount": [ + 12 + ], "courses": [ [ 350025, @@ -33013,7 +33244,9 @@ "description": "To graduate with a major in English, a student must complete with a grade of C or better 40 credit hours approved for the English major. All 2000-level ENGL courses (with the exception of 2800-2810 and 2880-2890) count for the major, as do all 3000-and 4000-level courses.", "source": "https://english.cornell.edu/majoring-and-minoring-english-cornell#requirements-for-the-major", "fulfilledBy": "credits", - "minCount": 40, + "perSlotMinCount": [ + 40 + ], "courses": [ [ 350636, @@ -33320,7 +33553,9 @@ "description": "12 credits (normally 3 courses) must be from courses in which 50% or more of the material consists of literature originally written in English before 1800 (such courses are indicated in the English course listings)", "source": "https://english.cornell.edu/majoring-and-minoring-english-cornell#requirements-for-the-major", "fulfilledBy": "credits", - "minCount": 12, + "perSlotMinCount": [ + 12 + ], "courses": [ [ 352694, @@ -33360,7 +33595,9 @@ "description": "8 credits (2 courses) must be at the 4000 level or above", "source": "https://www.engineering.cornell.edu/students/undergraduate-students/curriculum/undergraduate-requirements", "fulfilledBy": "credits", - "minCount": 8, + "perSlotMinCount": [ + 8 + ], "courses": [ [ 352935, @@ -33464,9 +33701,10 @@ "name": "Introductory Government Courses", "description": "Pass two of the introductory government courses in the subfields of American Government (AM), Comparative Politics (CP), Political Theory (PT), and International Relations (IR)", "source": "https://government.cornell.edu/sites/govt/files/Majorchecklist%202017_2018%20rv%20untrckd.pdf", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 2 + ], "courses": [ [ 351395, @@ -33482,7 +33720,9 @@ "description": "Accumulate an additional 28 credits of government course work at the 2000-level or above.", "source": "https://government.cornell.edu/sites/govt/files/Majorchecklist%202017_2018%20rv%20untrckd.pdf", "fulfilledBy": "credits", - "minCount": 28, + "perSlotMinCount": [ + 28 + ], "courses": [ [ 353989, @@ -33514,7 +33754,9 @@ "description": "The tenth GOVT course: must be worth a minimum of three credits, can be taken at any level. First-Year Writing Seminars cannot be used.", "source": "https://government.cornell.edu/sites/govt/files/Majorchecklist%202017_2018%20rv%20untrckd.pdf", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 351195, @@ -33766,9 +34008,13 @@ "name": "Accounting; Real Estate Development", "description": "HADM 1210, HADM 2210, HADM 2220, HADM 3210", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 1, + 1, + 1, + 1 + ], "courses": [ [ 351502 @@ -33788,9 +34034,12 @@ "name": "Employment Relations; HR; Law", "description": "HADM 1150, HADM 2810, HADM 3870", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 351489 @@ -33807,9 +34056,11 @@ "name": "Food and Beverage Management", "description": "HADM 2360, HADM 3350", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 351542 @@ -33823,9 +34074,10 @@ "name": "Information Systems", "description": "HADM 1740", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351483 @@ -33836,9 +34088,11 @@ "name": "Management Communication", "description": "HADM 1650, HADM 3650", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 351477 @@ -33852,9 +34106,13 @@ "name": "Operations", "description": "HADM 1350, HADM 1360, HADM 2010, HADM 3010", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 1, + 1, + 1, + 1 + ], "courses": [ [ 351465 @@ -33874,9 +34132,11 @@ "name": "Properties Development and Management", "description": "HADM 2550, HADM 3550", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 351562 @@ -33890,9 +34150,11 @@ "name": "Services Marketing", "description": "HADM 1410, HADM 2430", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 351468 @@ -33906,9 +34168,10 @@ "name": "Strategy", "description": "HADM 4410", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351829 @@ -33920,7 +34183,9 @@ "description": "A minimum of 14 credits, 3000-level or higher, in SHA.", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", "fulfilledBy": "credits", - "minCount": 14, + "perSlotMinCount": [ + 14 + ], "courses": [ [ 351552, @@ -33964,7 +34229,9 @@ "description": "A minimum of 18 credits, to be taken outside SHA. 3 of these 18 credits must be FWS.", "source": "https://sha.cornell.edu/current-students/handbook/2015-2016-handbook/curriculum-requirements/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 11, @@ -34225,9 +34492,10 @@ "name": "Pre 1800 Classes", "description": "3 of the nine courses must be in history before 1800 (Courses that fulfill the Arts & Sciences historical breadth requirement do not necessarily fulfill the History pre-1800 requirement.)", "source": "https://history.cornell.edu/undergraduate", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 352559, @@ -34305,9 +34573,14 @@ "name": "Core Courses", "description": "Students are required to complete five core courses: INFO 1200, INFO 1300, INFO 2040, INFO 2450, and INFO 2950.", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/ba-information-science-college-arts-sciences/degree-requirements/core", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 5, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 366630 @@ -34330,9 +34603,12 @@ "name": "Programming and Math Requirements", "description": "All Information Science majors are required to take CS 1110, Introduction to Computing Using Python, Calculus I, and a Statistics course. The list of approved Calculus I and Statistics is provided below. All classes used to complete major requirements must be taken for a letter grade. Advanced Placement credits may not be used to fulfill the Statistics requirement for students matriculating as of or after Fall 2015, however, they may be used to fulfill the Calculus requirement. Students that have taken CS 1112 should take CS 1133, Transition to Python, to be prepared for INFO 2950, Introduction to Data Science.", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-cals/degree-requirements/programming-and-math", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 358526 @@ -34369,9 +34645,10 @@ "name": "Electives", "description": "All students are required to complete three electives that are chosen from the following options: INFO 2300, CS 2110, CS 3110, CS 3410 or any INFO 3000+ or higher course including INFO 4900 (except INFO 4998). These courses must be taken for a letter grade, each must earn three or more credit hours, and all must be completed with a grade of C- or higher.Students may only fulfill one of their electives with INFO 4900 (3 credits or more).", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/ba-information-science-college-arts-sciences/degree-requirements-2", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350641, @@ -34493,9 +34770,11 @@ "name": "Probability, Statistics, and Optimization", "description": "ORIE 3300: Optimization I, ORIE 3500: Engineering Probability and Statistics II", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/core", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 351723 @@ -34509,9 +34788,12 @@ "name": "Information Systems", "description": "INFO 2300: Intermediate Design and Programming for the Web, ORIE 3800: Information Systems and Analysis or ORIE 3120: Practical Tools for Operations Research, Machine Learning and Data Science, one of -- INFO 3300: Data-Driven Web Applications, INFO 4300: Language and Information", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/core", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 358551 @@ -34529,9 +34811,11 @@ "name": "Economic, Organization, and Social Context", "description": "INFO 2040: Networks, one of -- INFO 2450: Communication and Technology, ENGRC 3350: Communications for Engineering Managers", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/core", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 359378 @@ -34546,9 +34830,13 @@ "name": "Engineering Mathematics", "description": "For majors in ISST, the sequence of required mathematics courses is MATH 1910, MATH 1920, MATH 2940, and finally, one of MATH 2930 or MATH 3040 or CS 2800.", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/math", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 1, + 1, + 1, + 1 + ], "courses": [ [ 352255 @@ -34570,9 +34858,11 @@ "name": "Engineering Distributions", "description": "The major requires ENGRD 2700 as an Engineering Distribution course. ENGRD 2110 is also required by the major and it is recommended that this course be taken as an Engineering Distribution course.", "source": "https://infosci.cornell.edu/undergraduate/info-sci-majors/bs-information-science-systems-and-technology/degree-requirements/math", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 358546 @@ -34594,9 +34884,10 @@ "name": "Engineering Distriubtions", "description": "ENGRD 2020", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 358608 @@ -34607,9 +34898,19 @@ "name": "Required Major Courses", "description": "MAE 2210, MAE 2030, MAE 2250, MAE 3230, MAE 3240, MAE 3260, MAE 3270, (MAE 3780, ENGRD 2100, or PHYS 3360), MAE 4272, and MAE 4300", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 10, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 358617 @@ -34662,7 +34963,9 @@ "description": "Must be an upper-level mathematics course, which includes statistics, taken after Math 2940. A list of approved math electives is available online at www.mae.cornell.edu", "source": "http://cornellengineeringhandbook.freeflowdp.com/cornellengineeringhandbook/5215877281438417/MobilePagedReplica.action?pm=2&folio=12#pg14", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350659, @@ -34698,9 +35001,16 @@ "name": "Major Required Classes", "description": "The following courses may be substituted for ORIE 3150, if not used to meet other require- ments: MATH 3110 (Introduction to Analysis), MATH 4130 (Honors Real Analysis), MATH 4310 (Linear Algebra), MATH 4330 (Honors Linear Algebra), any 600 level ORIE course.", "source": "https://www.orie.cornell.edu/orie/programs/undergraduate-programs/degree-requirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 7, + "perSlotMinCount": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], "courses": [ [ 358529 @@ -34730,7 +35040,9 @@ "description": "At least 9 credits of ORIE electives at the 4000 level or above", "source": "https://www.orie.cornell.edu/orie/programs/undergraduate-programs/degree-requirements", "fulfilledBy": "credits", - "minCount": 9, + "perSlotMinCount": [ + 9 + ], "courses": [ [ 352140, @@ -34834,9 +35146,12 @@ "name": "Engineering Distribution Courses", "description": "ENGRI 1xxx, ENGRD 2700, and ENGRD 2xxx. ENGRD 2110 is recommended", "source": "https://www.orie.cornell.edu/orie/programs/undergraduate-programs/degree-requirements", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 1, + 1, + 1 + ], "courses": [ [ 358622 @@ -34915,9 +35230,10 @@ "name": "Statistics Prerequisite", "description": "Choose one: AEM 1200, BTRY 3010, BTRY 3080, CEE 3040, ECON 3110, ECON 3120, ECON 3130, ENGRD 2700ILRST 2100, ILRST 3080, ILRST 3110, MATH 1710, MATH 4710, MATH 4720, PAM 2100, PAM 2101, PSYCH 2500STSCI 2100, STSCI 2150, STSCI 2200, STSCI 3080, STSCI 3110, SOC 3010", "source": "https://business.cornell.edu/programs/undergraduate/minors/business/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350154, @@ -34944,9 +35260,10 @@ "name": "Microeconomics Prerequisite", "description": "Choose one: ECON 1110 or ECON 3030 or PAM 2000", "source": "https://business.cornell.edu/programs/undergraduate/minors/business/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350025, @@ -34959,9 +35276,10 @@ "name": "Introduction to Management", "description": "Choose one: AEM 1200, ILRID 1700, NCC 5540", "source": "https://business.cornell.edu/programs/undergraduate/minors/business/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350811, @@ -34974,9 +35292,10 @@ "name": "Introduction to Marketing", "description": "Choose one: AEM 2400, NCC 5530, HADM 2410", "source": "https://business.cornell.edu/programs/undergraduate/minors/business/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350542, @@ -34989,9 +35308,10 @@ "name": "Financial Accounting", "description": "Choose one: AEM 2210, HADM 2230, NCC 5500", "source": "https://business.cornell.edu/programs/undergraduate/minors/business/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350518, @@ -35004,9 +35324,10 @@ "name": "Finance", "description": "Choose one: AEM 2241/5241, HADM 2250, NCC 5560", "source": "https://business.cornell.edu/programs/undergraduate/minors/business/", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 350814, @@ -35028,9 +35349,10 @@ "name": "Introductory Requirement", "description": "Choose COGST 1101 or COGST 2200", "source": "https://cogsci.cornell.edu/undergraduate-minor", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 351444, @@ -35042,9 +35364,10 @@ "name": "Lab Requirement", "description": "Choose COGST 4700 or COGST 4710", "source": "https://cogsci.cornell.edu/undergraduate-minor", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 353573, @@ -35056,9 +35379,10 @@ "name": "Three Courses at the 3000 or 4000 Level", "description": "Three courses at the 3000- and 4000-level in at least two departments (or certain suitable 2000- level courses by petition)", "source": "https://cogsci.cornell.edu/undergraduate-minor", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350841, @@ -35104,9 +35428,10 @@ "name": "Requirement 1", "description": "CS/ENGRD 2110 or 2112 or ENGRD 2140 or ECE 2400", "source": "https://www.cs.cornell.edu/undergrad/csminor", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 358546, @@ -35119,9 +35444,10 @@ "name": "Requirement 2", "description": "CS 3110 or CS 3410 or CS 3420/ECE 3140", "source": "https://www.cs.cornell.edu/undergrad/csminor", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 1, + "perSlotMinCount": [ + 1 + ], "courses": [ [ 358556, @@ -35134,9 +35460,10 @@ "name": "4 CS courses numbered 3000 or higher", "description": "CS 4090, CS 4997, CS 4998, CS 4999 and seminars are excluded. CS 2800 is allowed", "source": "https://www.cs.cornell.edu/undergrad/csminor", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 4, + "perSlotMinCount": [ + 4 + ], "courses": [ [ 352385, @@ -35313,7 +35640,9 @@ "description": "ECON 1100 or ECON 3030 or HADM 1410 or PAM 2000", "source": "https://business.cornell.edu/programs/undergraduate/minors/business-engineers/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350335, @@ -35327,7 +35656,9 @@ "description": "Choose one: AEM 1200, AEM 2400, HADM 2410, ENGRI 1270, ILRD 1700, NCC 5530, NCC 5580ORIE 4152, ENGRG 4610, MAE 4610", "source": "https://business.cornell.edu/programs/undergraduate/minors/business-engineers/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350542, @@ -35345,7 +35676,9 @@ "description": "AEM 2210 or HADM 2230 or NCC 5500 or ORIE 3150", "source": "https://business.cornell.edu/programs/undergraduate/minors/business-engineers/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350518, @@ -35360,7 +35693,9 @@ "description": "AEM 2241/5241 OR HADM 2250 OR NCC 5560", "source": "https://business.cornell.edu/programs/undergraduate/minors/business-engineers/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350814, @@ -35375,7 +35710,9 @@ "description": "AEM 4660", "source": "https://business.cornell.edu/programs/undergraduate/minors/business-engineers/", "fulfilledBy": "credits", - "minCount": 1.5, + "perSlotMinCount": [ + 1.5 + ], "courses": [ [ 364250 @@ -35387,7 +35724,9 @@ "description": "Choose a course that will expand your business management skills in a field of your choice from the following.", "source": "https://business.cornell.edu/programs/undergraduate/minors/business-engineers/", "fulfilledBy": "credits", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 350563, @@ -35443,9 +35782,10 @@ "name": "Required Courses", "description": "ENGRD 2700, ORIE 3120, ORIE 4800", "source": "https://www.orie.cornell.edu/orie/programs/undergraduate-programs/ore-minors", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 358529, @@ -35457,9 +35797,10 @@ "name": "3 Courses from the following", "description": "ORIE 3150, ORIE 3300, ORIE 4150, ORIE 4580, ORIE 4810, ORIE 4850, ORIE 5100, ORIE 5120, ORIE 5770", "source": "https://www.orie.cornell.edu/orie/programs/undergraduate-programs/ore-minors", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 351710, @@ -35482,9 +35823,11 @@ "name": "MATH 2930 and MATH 2940", "description": "MATH 2930 and 2940", "source": "https://www.mae.cornell.edu/mae/programs/undergraduate-programs/minors", - "subRequirementProgress": "every-course-needed", "fulfilledBy": "courses", - "minCount": 2, + "perSlotMinCount": [ + 1, + 1 + ], "courses": [ [ 352295 @@ -35512,9 +35855,10 @@ "name": "3 courses from the following", "description": "ENGRD 2700, ORIE 3300, ORIE 3310, ORIE 3500, ORIE 3510, ORIE 4580", "source": "https://www.orie.cornell.edu/orie/programs/undergraduate-programs/ore-minors", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 351723, @@ -35530,9 +35874,10 @@ "name": "Three 3000 level or higher ORIE courses", "description": "Any ORIE courses at the 3000 level or higher.", "source": "https://www.orie.cornell.edu/orie/programs/undergraduate-programs/ore-minors", - "subRequirementProgress": "any-can-count", "fulfilledBy": "courses", - "minCount": 3, + "perSlotMinCount": [ + 3 + ], "courses": [ [ 351710, @@ -35629,7 +35974,9 @@ "description": "A total of 18 credits in psychology. First-year seminars or AP courses cannot be counted towards the credit requirementsIt is strongly recommended that students take at least one course from each of the following three areas of psychology: PCD, BEN, S&P.", "source": "https://psychology.cornell.edu/minor", "fulfilledBy": "credits", - "minCount": 18, + "perSlotMinCount": [ + 18 + ], "courses": [ [ 351438, diff --git a/src/requirements/requirement-frontend-computation.ts b/src/requirements/requirement-frontend-computation.ts index 1984e0272..e97ff169d 100644 --- a/src/requirements/requirement-frontend-computation.ts +++ b/src/requirements/requirement-frontend-computation.ts @@ -2,7 +2,7 @@ import { CREDITS_COURSE_ID, FWS_COURSE_ID, SWIM_TEST_COURSE_ID } from './data/co import getCourseEquivalentsFromUserExams from './data/exams/ExamCredit'; import { convertFirestoreSemesterCourseToCourseTaken, - getMatchedRequirementFulfillmentSpecification, + computeFulfillmentCoursesAndStatistics, } from './requirement-frontend-utils'; import RequirementFulfillmentGraph from './requirement-graph'; import buildRequirementFulfillmentGraphFromUserData from './requirement-graph-builder-from-user-data'; @@ -42,7 +42,7 @@ const getTotalCreditsFulfillmentStatistics = ( name: 'Total Academic Credits', courses: [], fulfilledBy: 'credits', - minCount: 120, + perSlotMinCount: [120], } as const; let requirement: RequirementWithIDSourceType; switch (college) { @@ -153,9 +153,8 @@ const getSwimTestFulfillmentStatistics = ( 'and water safety competency requirement for all entering first-year undergraduate students.', source: 'http://courses.cornell.edu/content.php?catoid=41&navoid=11637', courses: [[SWIM_TEST_COURSE_ID]], - subRequirementProgress: 'any-can-count', fulfilledBy: 'courses', - minCount: 1, + perSlotMinCount: [1], }; const swimClasses = courses.filter(it => it.courseId === SWIM_TEST_COURSE_ID); if (tookSwimTest) { @@ -175,87 +174,6 @@ const getSwimTestFulfillmentStatistics = ( }; }; -function computeFulfillmentStatisticsFromCourses( - coursesThatFulfilledRequirement: readonly (readonly CourseTaken[])[], - counting: 'courses' | 'credits', - subRequirementProgress: 'every-course-needed' | 'any-can-count', - minCountRequired: number -): RequirementFulfillmentStatistics & { readonly courses: readonly (readonly CourseTaken[])[] } { - let minCountFulfilled = 0; - coursesThatFulfilledRequirement.forEach(coursesThatFulfilledSubRequirement => { - if (coursesThatFulfilledSubRequirement.length === 0) { - return; - } - - switch (counting) { - case 'courses': - minCountFulfilled += - subRequirementProgress === 'any-can-count' - ? coursesThatFulfilledSubRequirement.length - : 1; - break; - case 'credits': - minCountFulfilled += coursesThatFulfilledSubRequirement - .map(course => course.credits) - .reduce((a, b) => a + b, 0); - break; - default: - throw new Error('Fulfillment type unknown.'); - } - }); - - return { - fulfilledBy: counting, - minCountFulfilled, - minCountRequired, - courses: coursesThatFulfilledRequirement, - }; -} - -/** - * @param coursesTaken a list of all taken courses. - * @param requirementCourses a list of eligible courses from requirement data. - * @returns a naively computed list of courses that fulfill the requirement, partitioned into sub-requirement filfillment. - */ -function filterAndPartitionCoursesThatFulfillRequirement( - coursesTaken: readonly CourseTaken[], - requirementCourses: readonly (readonly number[])[] -): CourseTaken[][] { - const coursesThatFulfilledRequirement: CourseTaken[][] = requirementCourses.map(() => []); - coursesTaken.forEach(courseTaken => { - const { courseId } = courseTaken; - requirementCourses.forEach((subRequirementCourses, subRequirementIndex) => { - if (subRequirementCourses.includes(courseId)) { - // add the course to the list of courses used to fulfill that one sub-requirement - coursesThatFulfilledRequirement[subRequirementIndex].push(courseTaken); - } - }); - }); - return coursesThatFulfilledRequirement; -} - -function computeFulfillmentCoursesAndStatistics( - requirement: RequirementWithIDSourceType, - coursesTaken: readonly CourseTaken[], - toggleableRequirementChoices: AppToggleableRequirementChoices -): RequirementFulfillmentStatistics & { readonly courses: readonly (readonly CourseTaken[])[] } { - const spec = getMatchedRequirementFulfillmentSpecification( - requirement, - toggleableRequirementChoices - ); - if (spec == null) { - // Give self-check 1 required course and 0 fulfilled to prevent it from being fulfilled. - return { fulfilledBy: 'self-check', minCountFulfilled: 0, minCountRequired: 1, courses: [] }; - } - const { fulfilledBy, eligibleCourses, subRequirementProgress, minCount } = spec; - return computeFulfillmentStatisticsFromCourses( - filterAndPartitionCoursesThatFulfillRequirement(coursesTaken, eligibleCourses), - fulfilledBy, - subRequirementProgress, - minCount - ); -} - function getCourseCodesArray( semesters: readonly FirestoreSemester[], onboardingData: AppOnboardingData diff --git a/src/requirements/requirement-frontend-utils.ts b/src/requirements/requirement-frontend-utils.ts index f32620b57..ad87ad054 100644 --- a/src/requirements/requirement-frontend-utils.ts +++ b/src/requirements/requirement-frontend-utils.ts @@ -111,25 +111,19 @@ export function getMatchedRequirementFulfillmentSpecification( ): { readonly fulfilledBy: 'courses' | 'credits'; readonly eligibleCourses: readonly (readonly number[])[]; - readonly subRequirementProgress: 'every-course-needed' | 'any-can-count'; - readonly minCount: number; + readonly perSlotMinCount: readonly number[]; + readonly minNumberOfSlots?: number; } | null { switch (requirement.fulfilledBy) { case 'self-check': return null; case 'courses': - return { - fulfilledBy: requirement.fulfilledBy, - eligibleCourses: requirement.courses, - subRequirementProgress: requirement.subRequirementProgress, - minCount: requirement.minCount, - }; case 'credits': return { fulfilledBy: requirement.fulfilledBy, eligibleCourses: requirement.courses, - subRequirementProgress: 'any-can-count', - minCount: requirement.minCount, + perSlotMinCount: requirement.perSlotMinCount, + minNumberOfSlots: requirement.minNumberOfSlots, }; case 'toggleable': { const option = @@ -140,9 +134,8 @@ export function getMatchedRequirementFulfillmentSpecification( return { fulfilledBy: option.counting, eligibleCourses: option.courses, - subRequirementProgress: - option.counting === 'courses' ? option.subRequirementProgress : 'any-can-count', - minCount: option.minCount, + perSlotMinCount: option.perSlotMinCount, + minNumberOfSlots: option.minNumberOfSlots, }; } default: @@ -150,6 +143,72 @@ export function getMatchedRequirementFulfillmentSpecification( } } +/** + * @param requirement the requirement which we want sub-requirement progress report. + * @param coursesTaken a list of courses that are associated with the requirement in the graph. + * @param toggleableRequirementChoices user's choices on toggleable requirements. + * @returns requirement fulfillment stat, and partitioned courses into sub-requirement slots. + */ +export function computeFulfillmentCoursesAndStatistics( + requirement: RequirementWithIDSourceType, + coursesTaken: readonly CourseTaken[], + toggleableRequirementChoices: AppToggleableRequirementChoices +): RequirementFulfillmentStatistics & { readonly courses: readonly (readonly CourseTaken[])[] } { + const spec = getMatchedRequirementFulfillmentSpecification( + requirement, + toggleableRequirementChoices + ); + if (spec == null) { + // Give self-check 1 required course and 0 fulfilled to prevent it from being fulfilled. + return { fulfilledBy: 'self-check', minCountFulfilled: 0, minCountRequired: 1, courses: [] }; + } + const { fulfilledBy, eligibleCourses, perSlotMinCount, minNumberOfSlots } = spec; + + const coursesThatFulfilledSubRequirements: CourseTaken[][] = eligibleCourses.map(() => []); + const subRequirementProgress: number[] = eligibleCourses.map(() => 0); + coursesTaken.forEach(courseTaken => { + const { courseId } = courseTaken; + for ( + let subRequirementIndex = 0; + subRequirementIndex < eligibleCourses.length; + subRequirementIndex += 1 + ) { + if ( + eligibleCourses[subRequirementIndex].includes(courseId) && + subRequirementProgress[subRequirementIndex] < perSlotMinCount[subRequirementIndex] + ) { + // add the course to the list of courses used to fulfill that one sub-requirement + coursesThatFulfilledSubRequirements[subRequirementIndex].push(courseTaken); + subRequirementProgress[subRequirementIndex] += + fulfilledBy === 'courses' ? 1 : courseTaken.credits; + break; + } + } + }); + + if (minNumberOfSlots != null) { + const minCountFulfilled = subRequirementProgress.reduce( + (acc, progress, index) => acc + (progress > perSlotMinCount[index] ? 1 : 0), + 0 + ); + return { + fulfilledBy, + minCountFulfilled, + minCountRequired: minNumberOfSlots, + courses: coursesThatFulfilledSubRequirements, + }; + } + + const minCountFulfilled = subRequirementProgress.reduce((acc, progress) => acc + progress, 0); + const minCountRequired = perSlotMinCount.reduce((acc, progress) => acc + progress, 0); + return { + fulfilledBy, + minCountFulfilled, + minCountRequired, + courses: coursesThatFulfilledSubRequirements, + }; +} + export function getRelatedUnfulfilledRequirements( courseID: number, groupedRequirements: readonly GroupedRequirementFulfillmentReport[], diff --git a/src/requirements/requirement-json-generator.ts b/src/requirements/requirement-json-generator.ts index 5f19b4952..461a5f5a2 100644 --- a/src/requirements/requirement-json-generator.ts +++ b/src/requirements/requirement-json-generator.ts @@ -57,9 +57,7 @@ const decorateRequirementWithCourses = ( const { checker, ...rest } = requirement; return { ...rest, - courses: getEligibleCoursesFromRequirementCheckers( - typeof checker === 'function' ? [checker] : checker - ), + courses: getEligibleCoursesFromRequirementCheckers(checker), }; } case 'toggleable': { @@ -69,9 +67,7 @@ const decorateRequirementWithCourses = ( fulfillmentOptions: Object.fromEntries( Object.entries(fulfillmentOptions).map(([optionName, option]) => { const { checker, ...rest } = option; - const courses = getEligibleCoursesFromRequirementCheckers( - typeof checker === 'function' ? [checker] : checker - ); + const courses = getEligibleCoursesFromRequirementCheckers(checker); return [optionName, { ...rest, courses }]; }) ), diff --git a/src/requirements/types.ts b/src/requirements/types.ts index 934ed1784..5fd5e8ea6 100644 --- a/src/requirements/types.ts +++ b/src/requirements/types.ts @@ -22,7 +22,7 @@ export type BaseRequirement = RequirementCommon & RequirementFulfillmentInformat export type RequirementChecker = (course: Course) => boolean; export type CollegeOrMajorRequirement = RequirementCommon & RequirementFulfillmentInformation<{ - readonly checker: RequirementChecker | readonly RequirementChecker[]; + readonly checker: readonly RequirementChecker[]; }>; export type CollegeRequirements = {