All files / utils convertedSectionsToPrimaryRows.jsx

100% Statements 37/37
100% Branches 30/30
100% Functions 6/6
100% Lines 37/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97            39x 5x   34x       39x       26x 15x                     26x 5x     21x 21x 39x 39x 26x   39x     21x 5x 5x 5x 2x   3x     21x   21x 26x 26x   26x 39x 39x   39x 18x 1x   18x                 21x 6x   15x                       26x 17x       21x    
/**
 * Turn a flat list of ConvertedSection documents (courseInfo + section) into the
 * same hierarchical shape as /api/public/primaries: each row has quarter, courseId,
 * title, primary (lecture section), and subRows (secondary sections).
 */
function isLectureSectionNumber(sectionNum) {
  if (typeof sectionNum !== "string") {
    return false;
  }
  return /^\d+00$/.test(sectionNum.trim());
}
 
function groupKey(cs) {
  return `${cs.courseInfo.quarter}|${cs.courseInfo.courseId}`;
}
 
function sortWithinGroup(convertedSections) {
  return [...convertedSections].sort((a, b) =>
    (a.section.section ?? "").localeCompare(
      b.section.section ?? "",
      undefined,
      {
        numeric: true,
      },
    ),
  );
}
 
export function convertedSectionsToPrimaryRows(flatConvertedSections) {
  if (!flatConvertedSections || flatConvertedSections.length === 0) {
    return [];
  }
 
  const groups = new Map();
  for (const cs of flatConvertedSections) {
    const key = groupKey(cs);
    if (!groups.has(key)) {
      groups.set(key, []);
    }
    groups.get(key).push(cs);
  }
 
  const sortedKeys = [...groups.keys()].sort((ka, kb) => {
    const [qa, ca] = ka.split("|");
    const [qb, cb] = kb.split("|");
    if (qa !== qb) {
      return qb.localeCompare(qa);
    }
    return ca.localeCompare(cb);
  });
 
  const result = [];
 
  for (const key of sortedKeys) {
    const items = sortWithinGroup(groups.get(key));
    let currentPrimary = null;
 
    for (const cs of items) {
      const sec = cs.section;
      const info = cs.courseInfo;
 
      if (isLectureSectionNumber(sec.section)) {
        if (currentPrimary) {
          result.push(currentPrimary);
        }
        currentPrimary = {
          quarter: info.quarter,
          courseId: info.courseId,
          title: info.title,
          description: info.description ?? "",
          primary: sec,
          subRows: [],
          generalEducation: info.generalEducation ?? [],
        };
      } else if (currentPrimary) {
        currentPrimary.subRows.push(sec);
      } else {
        result.push({
          quarter: info.quarter,
          courseId: info.courseId,
          title: info.title,
          description: info.description ?? "",
          primary: sec,
          subRows: [],
          generalEducation: info.generalEducation ?? [],
        });
      }
    }
 
    if (currentPrimary) {
      result.push(currentPrimary);
    }
  }
 
  return result;
}