Connection
${typeof d.totalChannels === 'number' ? html`${d.totalChannels} channels` : nothing}
${this.renderChart(d)}
${renderHdFacts([
{ label: 'Channels', value: d.totalChannels?.toString() },
{
label: 'Combined definition',
value: d.combinedDefinition
? humanize(String(d.combinedDefinition))
: undefined,
},
{
label: 'Centers defined',
value:
centers.length > 0
? `${definedCenters} of ${centers.length}`
: undefined,
},
])}
${
this.hideReadings
? nothing
: html`
A connection chart reads the two charts as one bodygraph. Wherever the
two of them together hold both gates of a channel, that channel is
defined between them, and the centers it joins are defined in the
connection whether or not either person defines them alone.
`
}
${this.renderDynamics(d.summary)}
${this.renderCenters(centers)}
${this.renderChannels(channels, centers)}
`;
}
/**
* The four ways two charts can meet in a channel, in canonical order, each with what it means. The count is the aside, so the taxonomy and the tally read as one thing: a dynamic with no channels still shows, because its absence is as much a fact of the connection as its presence.
*/
private renderDynamics(s: Connection['summary'] | undefined) {
if (!s) return nothing;
const sections: InterpSection[] = [
{
label: 'Electromagnetic',
aside: channelCount(s.electromagnetic),
body: 'Each person holds one of the two gates, so the channel completes only when they are together. The classic point of attraction.',
},
{
label: 'Dominance',
aside: channelCount(s.dominance),
body: 'One person holds both gates and the other holds neither, so the conditioning runs one way, from the person who carries the channel to the person who does not.',
},
{
label: 'Compromise',
aside: channelCount(s.compromise),
body: 'One person holds both gates and the other holds a single hanging gate of the same channel, so the channel is complete for one of them and half open for the other.',
},
{
label: 'Companionship',
aside: channelCount(s.companionship),
body: 'Both people independently hold both gates, so neither needs the other to complete it. A shared and familiar frequency rather than an attraction.',
},
];
return this.renderInterpretation(
sections,
'hd-connection-dynamic',
'Dynamics',
);
}
/**
* The nine centers of the combined chart. `defined` is the combined state and `definedBy` is who carries it alone, so the two together say whether a center is brought to the connection or created by it.
*/
private renderCenters(centers: CombinedCenter[]) {
if (centers.length === 0) return nothing;
return html`
Centers
${
// The rows below are the state of each center and stay; this note is the
// explanation of how to read them.
this.hideReadings
? nothing
: html`
Defined is the state of the combined chart. Beside it is who already
defines that center in their own chart. A center defined only together is
what the connection itself creates: it is there when the two are together
and gone when they are apart. The combined definition counts how the
defined centers hang together, so Single is one connected piece and a
split is more than one.
`
}
${centers.map((c) => {
const by = c.definedBy ?? [];
const a = by.includes('A');
const b = by.includes('B');
// Only the connection defines it: defined in the combined chart, and in
// neither chart on its own.
const together = Boolean(c.defined) && !a && !b;
return html`
${c.name ?? humanize(String(c.id ?? ''))}
${c.defined ? (together ? 'Only together' : 'Defined') : 'Open'}
${centerWho(Boolean(c.defined), a, b)}
`;
})}
`;
}
/**
* Every connected channel. The centers a channel joins are named, not left as ids, because the row is what explains a defined center in the block above: this is the wiring that produced it.
*/
private renderChannels(
channels: ConnectionChannel[],
centers: CombinedCenter[],
) {
if (channels.length === 0) return nothing;
const names = new Map(
centers.map((c) => [String(c.id ?? ''), c.name ?? ''] as const),
);
const centerName = (id: string) => names.get(id) || humanize(id);
return html`