From 2a23143bae85c19e38007b8b6f03bb373f661268 Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Wed, 4 Dec 2024 13:57:12 +0100 Subject: [PATCH] refactor: stats row count prop --- CHANGELOG.md | 1 + app/scripts/components/statistics.js | 11 +++----- app/scripts/components/trend-diagram.ts | 4 +-- .../controllers/statistics_controller.ts | 2 +- app/scripts/statistics.ts | 28 ++++++++----------- app/scripts/statistics_worker.ts | 17 ++++++----- app/scripts/util.ts | 6 ++-- 7 files changed, 32 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40f4fed4..a062a282 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - `countAttrValues()` for getting a deep structure with counts - Search history is stored as parameters only, not full urls #118 - Enabled the `noImplicitAny` TypeScript flag for added strictness, and fixed/refactored various parts as a consequence +- The `hitCountHtml` util function now takes the numbers as a tuple ### Fixed diff --git a/app/scripts/components/statistics.js b/app/scripts/components/statistics.js index ade49833..14e25538 100644 --- a/app/scripts/components/statistics.js +++ b/app/scripts/components/statistics.js @@ -340,10 +340,7 @@ angular.module("korpApp").component("statistics", { } // Find which corpora had any hits (uppercase ids) - // TODO Move [CORPUSID]_value to {count: {[corpusid]: ...}} or similar - const corpora = Object.keys(rowData) - .filter((key) => key.endsWith("_value") && key != "total_value" && rowData[key][0] > 0) - .map((key) => key.split("_")[0]) + const corpora = Object.keys(rowData.count).filter((id) => rowData.count[id][0] > 0) const opts = {} opts.ajaxParams = { @@ -462,7 +459,7 @@ angular.module("korpApp").component("statistics", { $scope.rowData = $ctrl.searchParams.corpora.map((corpus) => ({ title: locObj(settings.corpora[corpus.toLowerCase()]["title"]), - values: row[corpus + "_value"], // [absolute, relative] + values: row.count[corpus], // [absolute, relative] })) const modal = $uibModal.open({ @@ -559,9 +556,9 @@ angular.module("korpApp").component("statistics", { return row[reduceVal].join(",") } }) - outputRow.push(fmt(row.total_value[selVal])) + outputRow.push(fmt(row.total[selVal])) for (let corp of $ctrl.searchParams.corpora) { - val = row[corp + "_value"][selVal] + val = row.count[corp][selVal] if (val) { outputRow.push(fmt(val)) } else { diff --git a/app/scripts/components/trend-diagram.ts b/app/scripts/components/trend-diagram.ts index 6278571b..1723952a 100644 --- a/app/scripts/components/trend-diagram.ts +++ b/app/scripts/components/trend-diagram.ts @@ -439,9 +439,7 @@ angular.module("korpApp").component("trendDiagram", { name: timestamp, field: timestamp, formatter(row, cell, value, columnDef, dataContext) { - return typeof value[0] === "undefined" - ? "" - : hitCountHtml(value[0], value[1], $rootScope.lang) + return typeof value[0] === "undefined" ? "" : hitCountHtml(value, $rootScope.lang) }, } const i = _.sortedIndexOf(_.map(seriesRow.abs_data, "x"), item.x) diff --git a/app/scripts/controllers/statistics_controller.ts b/app/scripts/controllers/statistics_controller.ts index 3c4ab2f9..cf64edd6 100644 --- a/app/scripts/controllers/statistics_controller.ts +++ b/app/scripts/controllers/statistics_controller.ts @@ -176,7 +176,7 @@ angular.module("korpApp").directive("statsResultCtrl", () => ({ s.gridData = data - if (data[0].total_value[0] === 0) { + if (data[0].total[0] === 0) { s.no_hits = true return } diff --git a/app/scripts/statistics.ts b/app/scripts/statistics.ts index e769339d..26269554 100644 --- a/app/scripts/statistics.ts +++ b/app/scripts/statistics.ts @@ -23,11 +23,6 @@ const createStatisticsService = function () { reduceVals: string[], reduceValLabels: LangString[] ): SlickgridColumn[] { - const valueFormatter: SlickGridFormatter = function (row, cell, value, columnDef, dataContext) { - const [absolute, relative] = [...dataContext[`${columnDef.id}_value`]] - return hitCountHtml(absolute, relative) - } - // This sorting will not react to language change, but that's quite alright, we like columns staying in place. const lang = getLang() const getCorpusTitle = (id: string): string => locObj(settings.corpora[id.toLowerCase()].title, lang) @@ -76,22 +71,23 @@ const createStatisticsService = function () { columns.push({ id: "total", name: "stats_total", - field: "total_value", + field: "total", sortable: true, - formatter: valueFormatter, + formatter: (row, cell, value) => hitCountHtml(value, lang), minWidth, headerCssClass: "localized-header", }) - const corpusColumns = corpora.map((id) => ({ - id, - translation: settings.corpora[id.toLowerCase()].title, - field: id + "_value", - sortable: true, - formatter: valueFormatter, - minWidth, - })) - columns.push(...corpusColumns) + corpora.forEach((id) => + columns.push({ + id, + translation: settings.corpora[id.toLowerCase()].title, + field: "count", + sortable: true, + formatter: (row, cell, value, columnDef) => hitCountHtml(value[columnDef.id!], lang), + minWidth, + }) + ) return columns } diff --git a/app/scripts/statistics_worker.ts b/app/scripts/statistics_worker.ts index c4b1fc7c..6a041a20 100644 --- a/app/scripts/statistics_worker.ts +++ b/app/scripts/statistics_worker.ts @@ -53,7 +53,8 @@ onmessage = function (e) { const totalRow: TotalRow = { id: "row_total", - total_value: [combined[0].sums.absolute, combined[0].sums.relative], + count: {}, + total: [combined[0].sums.absolute, combined[0].sums.relative], rowId: 0, } @@ -61,7 +62,7 @@ onmessage = function (e) { const corporaFreqs: Record> = {} for (const id of corporaKeys) { const obj = data.corpora[id] - totalRow[`${id}_value`] = [obj[0].sums.absolute, obj[0].sums.relative] + totalRow.count[id] = [obj[0].sums.absolute, obj[0].sums.relative] corporaFreqs[id] = groupBy(obj[0].rows, (item) => simplifyHitString(item)) } @@ -106,7 +107,8 @@ onmessage = function (e) { const row: SingleRow = { rowId: i + 1, - total_value: [totalAbs, totalRel] as AbsRelSeq, + count: {}, + total: [totalAbs, totalRel] as AbsRelSeq, formattedValue: {}, statsValues, } @@ -114,14 +116,14 @@ onmessage = function (e) { map(corporaKeys, function (corpus) { const abs = sumBy(corporaFreqs[corpus][word], "absolute") const rel = sumBy(corporaFreqs[corpus][word], "relative") - row[`${corpus}_value`] = [abs, rel] + row.count[corpus] = [abs, rel] }) dataset[i + 1] = row } dataset.sort(function (a, b) { - return b.total_value[0] - a.total_value[0] + return b.total[0] - a.total[0] }) const ctx: Worker = self as any ctx.postMessage(dataset) @@ -141,8 +143,9 @@ export type SingleRow = RowBase & { export type RowBase = { rowId: number - total_value: AbsRelSeq - [name: `${string}_value`]: AbsRelSeq + /** Frequency counts keyed by uppercase corpus id */ + count: Record + total: AbsRelSeq } export type Dataset = Row[] diff --git a/app/scripts/util.ts b/app/scripts/util.ts index c785f913..11c5a8e4 100644 --- a/app/scripts/util.ts +++ b/app/scripts/util.ts @@ -192,13 +192,13 @@ export function formatRelativeHits(x: number | string, lang?: string) { /** * Format as ` ()` plus surrounding HTML. - * @param absolute Number of absolute hits - * @param relative Number of relative hits (hits per 1 million tokens) + * @param absrel Tuple with numbers of 0) absolute hits and 1) relative hits (hits per 1 million tokens) * @param lang The locale to use. * @returns A HTML snippet. */ -export function hitCountHtml(absolute: number, relative: number, lang?: string) { +export function hitCountHtml(absrel: [number, number], lang?: string) { lang = lang || getLang() + const [absolute, relative] = absrel const relativeHtml = `${formatRelativeHits(relative, lang)}` // TODO Remove outer span? // TODO Flexbox?