# core/analyzers/learning.analyzer.ts

> 46 lines of code and 13 definitions.

Tree: Bane's Lab Build Scripts
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/build-scripts#file-build-scripts-core-analyzers-learning-analyzer-ts
Source text: https://banes-lab.com/source/build-scripts/core/analyzers/learning.analyzer.ts.txt

Listed in [core/analyzers](https://banes-lab.com/api/source/build-scripts/core/analyzers.md), after [core/analyzers/graph.analyzer.ts](https://banes-lab.com/source/build-scripts/core/analyzers/graph.analyzer.ts.md).

## Definitions

- `tabParts` (lexical_declaration, line 16)
- `entriesIn` (lexical_declaration, line 11)
- `routeSections` (lexical_declaration, line 33, exported)
- `sections` (lexical_declaration, line 12)
- `titled` (lexical_declaration, line 21)
- `untitled` (lexical_declaration, line 22)
- `held` (lexical_declaration, line 29)
- `byPage` (lexical_declaration, line 34, exported)
- `parts` (lexical_declaration, line 35, exported)
- `whole` (lexical_declaration, line 36, exported)
- `graph` (lexical_declaration, line 38, exported)
- `tabs` (lexical_declaration, line 39, exported)
- `routed` (lexical_declaration, line 40, exported)

## Contained in

- [core/analyzers](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-analyzers.md)

## Uses

- [core/converters/learning.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/learning.converter.ts.md)

## Linked from

- [core/analyzers](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-analyzers.md)
- [core/converters](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-converters.md)

## Source

```typescript
import {
    ROUTE_SECTIONS_POPULATION,
    ROUTE_SECTION_PARTS,
    SITE_PAGES,
} from "#configuration/constants/learning.constants";
import type { TabRecord, TabsFor } from "#types/learning.types";
import { heldIn, sectionsIn, textOf, unitsOf } from "#core/converters/learning.converter";
import type { ContentGraph } from "@banes-lab/web/types/methodology.types.js";
import type { Population } from "#types/catalog.types";

const entriesIn = function entriesIn(tab: TabRecord): number {
    const sections: unknown = tab.sections;
    return Array.isArray(sections) ? sections.length : 0;
};

const tabParts = function tabParts(
    tab: TabRecord,
    graph: ContentGraph | undefined,
    routed: ReadonlySet<string>,
): readonly (readonly [string, number])[] {
    const titled = sectionsIn(tab);
    const untitled: readonly [string, number] = [ROUTE_SECTION_PARTS.untitled, entriesIn(tab) - titled.length];
    if (graph === undefined) {
        return [untitled, [ROUTE_SECTION_PARTS.graphless, titled.length]];
    }
    if (!routed.has(textOf(tab.id))) {
        return [untitled, [ROUTE_SECTION_PARTS.silent, titled.length]];
    }
    const held = heldIn(graph, titled).length;
    return [untitled, [ROUTE_SECTION_PARTS.routed, held], [ROUTE_SECTION_PARTS.unheld, titled.length - held]];
};

export const routeSections = function routeSections(graphs: readonly ContentGraph[], tabsFor: TabsFor): Population {
    const byPage = new Map(graphs.map((graph) => [graph.page, graph]));
    const parts = new Map<string, number>(Object.values(ROUTE_SECTION_PARTS).map((part) => [part, 0]));
    let whole = 0;
    for (const page of SITE_PAGES) {
        const graph = byPage.get(page);
        const tabs = tabsFor(page);
        const routed = new Set(graph === undefined ? [] : unitsOf(page, graph, tabs).map((unit) => unit.tab));
        for (const tab of tabs) {
            whole += entriesIn(tab);
            for (const [part, count] of tabParts(tab, graph, routed)) {
                parts.set(part, (parts.get(part) ?? 0) + count);
            }
        }
    }
    return { name: ROUTE_SECTIONS_POPULATION, parts: Object.fromEntries(parts), whole };
};
```
