From 4b951c5802163b319c3cfa8b334b4c54bf598319 Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Thu, 16 May 2024 16:26:26 +0200 Subject: [PATCH] Extract TimeProxy as TS --- app/scripts/korp-api/base-proxy.ts | 13 +++ app/scripts/korp-api/kwic-proxy.ts | 6 +- app/scripts/korp-api/lemgram-proxy.ts | 6 +- app/scripts/korp-api/stats-proxy.ts | 6 +- app/scripts/korp-api/time-proxy.ts | 111 ++++++++++++++++++++++++++ app/scripts/model.js | 86 +------------------- 6 files changed, 137 insertions(+), 91 deletions(-) create mode 100644 app/scripts/korp-api/time-proxy.ts diff --git a/app/scripts/korp-api/base-proxy.ts b/app/scripts/korp-api/base-proxy.ts index 08b94685e..6fe8bd09e 100644 --- a/app/scripts/korp-api/base-proxy.ts +++ b/app/scripts/korp-api/base-proxy.ts @@ -152,6 +152,19 @@ export default abstract class BaseProxy { } } +/** A Korp response is either successful or has error info. */ +export type KorpResponse = (T | KorpErrorResponse) & { + /** Execution time in seconds */ + time?: number +} + +export type KorpErrorResponse = { + ERROR: { + type: string + value: string + } +} + type ProgressResponse = { progress?: string | { corpus: string } progress_corpora?: any diff --git a/app/scripts/korp-api/kwic-proxy.ts b/app/scripts/korp-api/kwic-proxy.ts index fd4d888f1..e7e11f3ce 100644 --- a/app/scripts/korp-api/kwic-proxy.ts +++ b/app/scripts/korp-api/kwic-proxy.ts @@ -1,7 +1,7 @@ /** @format */ import _ from "lodash" import settings from "@/settings" -import BaseProxy, { type AjaxSettings } from "@/korp-api/base-proxy" +import BaseProxy, { KorpResponse, type AjaxSettings } from "@/korp-api/base-proxy" import { angularLocationSearch, httpConfAddMethod } from "@/util" export default class KwicProxy extends BaseProxy { @@ -160,7 +160,7 @@ type MakeRequestOptions = { type Interval = { start: number; end: number } /** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Concordance/paths/~1query/get */ -type KorpQueryResponse = { +type KorpQueryResponse = KorpResponse<{ /** Search hits */ kwic: ApiKwic[] /** Total number of hits */ @@ -171,7 +171,7 @@ type KorpQueryResponse = { time: number /** A hash of this query */ query_data: string -} +}> /** Search hits */ type ApiKwic = { diff --git a/app/scripts/korp-api/lemgram-proxy.ts b/app/scripts/korp-api/lemgram-proxy.ts index 519b11337..1852997c3 100644 --- a/app/scripts/korp-api/lemgram-proxy.ts +++ b/app/scripts/korp-api/lemgram-proxy.ts @@ -1,6 +1,6 @@ /** @format */ import settings from "@/settings" -import BaseProxy, { AjaxSettings } from "@/korp-api/base-proxy" +import BaseProxy, { AjaxSettings, KorpResponse } from "@/korp-api/base-proxy" import { httpConfAddMethod } from "@/util" export default class LemgramProxy extends BaseProxy { @@ -61,11 +61,11 @@ type KorpRelationsParams = { incremental?: boolean } -type KorpRelationsResponse = { +type KorpRelationsResponse = KorpResponse<{ relations: ApiRelation[] /** Execution time in seconds */ time: number -} +}> type ApiRelation = { dep: string diff --git a/app/scripts/korp-api/stats-proxy.ts b/app/scripts/korp-api/stats-proxy.ts index 01d097a18..b951b5a6e 100644 --- a/app/scripts/korp-api/stats-proxy.ts +++ b/app/scripts/korp-api/stats-proxy.ts @@ -1,7 +1,7 @@ /** @format */ import _ from "lodash" import settings from "@/settings" -import BaseProxy, { AjaxSettings } from "@/korp-api/base-proxy" +import BaseProxy, { AjaxSettings, KorpResponse } from "@/korp-api/base-proxy" import { angularLocationSearch, httpConfAddMethod } from "@/util" import { statisticsService } from "@/statistics" @@ -170,7 +170,7 @@ type KorpStatsParams = { } /** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Statistics/paths/~1count/get */ -type KorpStatsResponse = { +type KorpStatsResponse = KorpResponse<{ corpora: { [name: string]: StatsColumn } @@ -179,7 +179,7 @@ type KorpStatsResponse = { count: number /** Execution time in seconds */ time: number -} +}> type StatsColumn = { sums: AbsRelTuple diff --git a/app/scripts/korp-api/time-proxy.ts b/app/scripts/korp-api/time-proxy.ts new file mode 100644 index 000000000..936480471 --- /dev/null +++ b/app/scripts/korp-api/time-proxy.ts @@ -0,0 +1,111 @@ +/** @format */ +import _ from "lodash" +import settings from "@/settings" +import BaseProxy, { AjaxSettings, KorpResponse } from "@/korp-api/base-proxy" +import { httpConfAddMethod } from "@/util" + +export default class TimeProxy extends BaseProxy { + makeRequest() { + const data: KorpTimespanParams = { + granularity: "y", + corpus: settings.corpusListing.stringifyAll(), + } + + const dfd = $.Deferred() + const ajaxSettings: AjaxSettings = { + url: settings["korp_backend_url"] + "/timespan", + data, + } + const xhr = $.ajax(httpConfAddMethod(ajaxSettings)) as JQuery.jqXHR + + xhr.done((data) => { + if ("ERROR" in data) { + console.error("timespan error", data.ERROR) + dfd.reject(data.ERROR) + return + } + + const rest = data.combined[""] + delete data.combined[""] + + this.expandTimeStruct(data.combined) + const combined = this.compilePlotArray(data.combined) + + if (_.keys(data).length < 2) { + dfd.reject() + return + } + + return dfd.resolve([data.corpora, combined, rest]) + }) + + xhr.fail(function () { + console.log("timeProxy.makeRequest failed", arguments) + return dfd.reject() + }) + + return dfd + } + + compilePlotArray(dataStruct: Histogram) { + let output = [] + $.each(dataStruct, function (key, val) { + if (!key || !val) { + return + } + return output.push([parseInt(key), val]) + }) + + output = output.sort((a, b) => a[0] - b[0]) + return output + } + + expandTimeStruct(struct: Histogram) { + const years = _.map(_.toPairs(_.omit(struct, "")), (item) => Number(item[0])) + if (!years.length) { + return + } + const minYear = _.min(years) + const maxYear = _.max(years) + + if (_.isNaN(maxYear) || _.isNaN(minYear)) { + console.log("expandTimestruct broken, years:", years) + return + } + + let prevVal = null + for (let y of _.range(minYear, maxYear + 1)) { + let thisVal = struct[y] + if (typeof thisVal == "undefined") { + struct[y] = prevVal + } else { + prevVal = thisVal + } + } + } +} + +/** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Statistics/paths/~1timespan/get */ +type KorpTimespanParams = { + corpus: string + granularity?: "y" | "m" | "d" | "h" | "n" | "s" + from?: `${number}` + to?: `${number}` + strategy?: 1 | 2 | 3 + per_corpus?: boolean + combined?: boolean + incremental?: boolean +} + +/** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Statistics/paths/~1timespan/get */ +type KorpTimespanResponse = KorpResponse<{ + /** An object with corpus names as keys and time statistics objects as values */ + corpora: Record + /** Number of tokens per time period */ + combined: Histogram + /** Execution time in seconds */ + time: number +}> + +type NumericString = `${number}` +type Histogram = Record diff --git a/app/scripts/model.js b/app/scripts/model.js index 0885187c9..b113b12ff 100644 --- a/app/scripts/model.js +++ b/app/scripts/model.js @@ -5,8 +5,9 @@ import settings from "@/settings" import { httpConfAddMethod } from "@/util" import BaseProxy from "@/korp-api/base-proxy" import KwicProxy from "@/korp-api/kwic-proxy" -import LemgramProxy from "./korp-api/lemgram-proxy" -import StatsProxy from "./korp-api/stats-proxy" +import LemgramProxy from "@/korp-api/lemgram-proxy" +import StatsProxy from "@/korp-api/stats-proxy" +import TimeProxy from "@/korp-api/time-proxy" const model = {} export default model @@ -17,86 +18,7 @@ model.LemgramProxy = LemgramProxy model.StatsProxy = StatsProxy -model.TimeProxy = class TimeProxy extends BaseProxy { - makeRequest() { - const dfd = $.Deferred() - - const xhr = $.ajax( - httpConfAddMethod({ - url: settings["korp_backend_url"] + "/timespan", - data: { - granularity: "y", - corpus: settings.corpusListing.stringifyAll(), - }, - }) - ) - - xhr.done((data) => { - if (data.ERROR) { - c.error("timespan error", data.ERROR) - dfd.reject(data.ERROR) - return - } - - const rest = data.combined[""] - delete data.combined[""] - - this.expandTimeStruct(data.combined) - const combined = this.compilePlotArray(data.combined) - - if (_.keys(data).length < 2 || data.ERROR) { - dfd.reject() - return - } - - return dfd.resolve([data.corpora, combined, rest]) - }) - - xhr.fail(function () { - c.log("timeProxy.makeRequest failed", arguments) - return dfd.reject() - }) - - return dfd - } - - compilePlotArray(dataStruct) { - let output = [] - $.each(dataStruct, function (key, val) { - if (!key || !val) { - return - } - return output.push([parseInt(key), val]) - }) - - output = output.sort((a, b) => a[0] - b[0]) - return output - } - - expandTimeStruct(struct) { - const years = _.map(_.toPairs(_.omit(struct, "")), (item) => Number(item[0])) - if (!years.length) { - return - } - const minYear = _.min(years) - const maxYear = _.max(years) - - if (_.isNaN(maxYear) || _.isNaN(minYear)) { - c.log("expandTimestruct broken, years:", years) - return - } - - let prevVal = null - for (let y of _.range(minYear, maxYear + 1)) { - let thisVal = struct[y] - if (typeof thisVal == "undefined") { - struct[y] = prevVal - } else { - prevVal = thisVal - } - } - } -} +model.TimeProxy = TimeProxy model.GraphProxy = class GraphProxy extends BaseProxy { constructor() {