Whole-mouth periodontal summary over the active chart: total charted
sites, how many bled on probing, the derived %BOP, and the single worst
(deepest) CAL reading with the tooth it's on, plus the deepest raw pocket
depth recorded anywhere. %BOP = bleedingSites / chartedSites — a site
flagged bop without ever being charted can't exist (see setPerioSite()),
so this ratio can never exceed 100%. Returns zeros/nulls (never NaN)
when nothing has been charted anywhere.
maxFurcation (SP-perio P2b Task 2): the single highest Glickman grade
(1-4) recorded on ANY furcation entrance anywhere in the mouth, null
when nothing has been graded. Deliberately its own pass over ALL_TEETH
(not folded into the pd-site loop above) since a tooth can carry furcation
data independently of whether it has any charted perio site.
plaquePercent (SP-perio P2b Task 3): whole-mouth O'Leary Plaque Index —
(total plaque surfaces charted across present teeth) / (present-teeth * 4) * 100, one decimal (same rounding as bopPercent above), 0 when
there are no present teeth (NOT null — matches bopPercent's
zero-not-null convention, unlike avgPd/avgCal). "Present" here means a
REAL tooth in the mouth — toothSelection is neither "none" (missing)
nor "implant" — deliberately the SAME predicate isToothPresent() uses
(O'Leary is a tooth-focused index: a missing tooth has no surfaces to
chart, an implant has no natural tooth surface). This is intentionally
looser than perioRowHidden() (which additionally excludes under-gum/
extraction-socket teeth, since THOSE have no probeable periodontal
pocket) — an under-gum or extraction-socket "tooth" still occupies a slot
in the arch and can carry visible/recorded plaque on the socket/gum
surface, so it still counts toward the denominator here. Deliberately its
own pass over ALL_TEETH (not folded into the pd-site loop above) since a
tooth can carry plaque data independently of whether it has any charted
perio site, mirroring maxFurcation above. A tooth never touched at all
(no entry in the active chart map) is skipped entirely, same convention
maxFurcation's loop and getOdontogramSummary() use.
SP-perio PG-D Task 5 additions (own pass over ALL_TEETH, same "absence =
not charted" convention as maxFurcation/plaquePercent above):
piScore/giScore: mean of ALL charted PI/GI surface grades across
the whole mouth (sum of grades / number of CHARTED surfaces, one
decimal) — null when nothing is charted anywhere (mirrors
avgPd/avgCal's null-when-none, NOT bopPercent/plaquePercent's
zero-when-none, since a 0 mean would misleadingly read as "all
surfaces charted healthy").
kgDeficientTeeth: count of teeth with a charted kg narrower than
2mm (kg != null && kg < 2) — an uncharted tooth (kg === null) is
never counted.
gtDistribution/millerDistribution: per-value counts across the
whole mouth, excluding the "not charted" skip value (unknown/
none respectively) — mirrors how maxFurcation's loop only counts
graded entrances.
SP-perio PG-E Task 3 addition (own pass, same convention):
mpiScore/mbiScore: mean of ALL charted mPI/mBI surface grades
across implant teeth (sum of grades / number of CHARTED surfaces, one
decimal) — null when nothing is charted anywhere, mirrors
piScore/giScore exactly. mPI/mBI are implant-only axes (the setter
is a no-op on a non-implant tooth), so guarding the accumulator on
s.toothSelection === "implant" is belt-and-suspenders — a
non-implant tooth's mpi/mbi maps can never be non-empty — but
makes the implant-only intent explicit at the read site too.
Whole-mouth periodontal summary over the active chart: total charted sites, how many bled on probing, the derived %BOP, and the single worst (deepest) CAL reading with the tooth it's on, plus the deepest raw pocket depth recorded anywhere.
%BOP = bleedingSites / chartedSites— a site flaggedbopwithout ever being charted can't exist (see setPerioSite()), so this ratio can never exceed 100%. Returns zeros/nulls (neverNaN) when nothing has been charted anywhere.maxFurcation(SP-perio P2b Task 2): the single highest Glickman grade (1-4) recorded on ANY furcation entrance anywhere in the mouth,nullwhen nothing has been graded. Deliberately its own pass overALL_TEETH(not folded into the pd-site loop above) since a tooth can carry furcation data independently of whether it has any charted perio site.plaquePercent(SP-perio P2b Task 3): whole-mouth O'Leary Plaque Index —(total plaque surfaces charted across present teeth) / (present-teeth * 4) * 100, one decimal (same rounding asbopPercentabove),0when there are no present teeth (NOTnull— matchesbopPercent's zero-not-null convention, unlikeavgPd/avgCal). "Present" here means a REAL tooth in the mouth —toothSelectionis neither"none"(missing) nor"implant"— deliberately the SAME predicateisToothPresent()uses (O'Leary is a tooth-focused index: a missing tooth has no surfaces to chart, an implant has no natural tooth surface). This is intentionally looser thanperioRowHidden()(which additionally excludes under-gum/ extraction-socket teeth, since THOSE have no probeable periodontal pocket) — an under-gum or extraction-socket "tooth" still occupies a slot in the arch and can carry visible/recorded plaque on the socket/gum surface, so it still counts toward the denominator here. Deliberately its own pass overALL_TEETH(not folded into the pd-site loop above) since a tooth can carry plaque data independently of whether it has any charted perio site, mirroringmaxFurcationabove. A tooth never touched at all (no entry in the active chart map) is skipped entirely, same conventionmaxFurcation's loop andgetOdontogramSummary()use.SP-perio PG-D Task 5 additions (own pass over
ALL_TEETH, same "absence = not charted" convention asmaxFurcation/plaquePercentabove):piScore/giScore: mean of ALL charted PI/GI surface grades across the whole mouth (sum of grades / number of CHARTED surfaces, one decimal) —nullwhen nothing is charted anywhere (mirrorsavgPd/avgCal's null-when-none, NOTbopPercent/plaquePercent's zero-when-none, since a 0 mean would misleadingly read as "all surfaces charted healthy").kgDeficientTeeth: count of teeth with a chartedkgnarrower than 2mm (kg != null && kg < 2) — an uncharted tooth (kg === null) is never counted.gtDistribution/millerDistribution: per-value counts across the whole mouth, excluding the "not charted" skip value (unknown/nonerespectively) — mirrors howmaxFurcation's loop only counts graded entrances.SP-perio PG-E Task 3 addition (own pass, same convention):
mpiScore/mbiScore: mean of ALL charted mPI/mBI surface grades across implant teeth (sum of grades / number of CHARTED surfaces, one decimal) —nullwhen nothing is charted anywhere, mirrorspiScore/giScoreexactly. mPI/mBI are implant-only axes (the setter is a no-op on a non-implant tooth), so guarding the accumulator ons.toothSelection === "implant"is belt-and-suspenders — a non-implant tooth'smpi/mbimaps can never be non-empty — but makes the implant-only intent explicit at the read site too.