Skip to content

Commit

Permalink
WIP: Move API calls and params/response types to client.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
arildm committed Oct 22, 2024
1 parent 1f600ac commit e0fa9b5
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 191 deletions.
39 changes: 10 additions & 29 deletions app/scripts/backend/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,9 @@ import { KorpResponse, WithinParameters } from "@/backend/types"
import { SavedSearch } from "@/local-storage"
import settings from "@/settings"
import { httpConfAddMethodFetch } from "@/util"
import { KorpStatsResponse, normalizeStatsData } from "@/backend/stats-proxy"
import { normalizeStatsData } from "@/backend/stats-proxy"
import { MapResult, parseMapData } from "@/map_services"
import { KorpQueryResponse } from "@/backend/kwic-proxy"

type KorpLoglikeResponse = {
/** Log-likelihood average. */
average: number
/** Log-likelihood values. */
loglike: Record<string, number>
/** Absolute frequency for the values in set 1. */
set1: Record<string, number>
/** Absolute frequency for the values in set 2. */
set2: Record<string, number>
}
import { count, loglike, QueryResponse } from "./client"

export type CompareResult = [CompareTables, number, SavedSearch, SavedSearch, string[]]

Expand Down Expand Up @@ -80,7 +69,7 @@ export async function requestCompare(
const rankedReduce = _.filter(reduce, (item) => cl.getCurrentAttributes(cl.getReduceLang())[item]?.ranked)
const top = rankedReduce.map((item) => item + ":1").join(",")

const params = {
const data = await loglike({
group_by: reduce.join(","),
set1_corpus: corpora1.join(",").toUpperCase(),
set1_cqp: cmpObj1.cqp,
Expand All @@ -89,9 +78,7 @@ export async function requestCompare(
max: "50",
split,
top,
}

const data = await korpRequest<KorpLoglikeResponse>("loglike", params)
})

if ("ERROR" in data) {
// TODO Create a KorpBackendError which could be displayed nicely
Expand Down Expand Up @@ -137,19 +124,16 @@ export async function requestMapData(
const cqpSubExprs = {}
_.map(_.keys(cqpExprs), (subCqp, idx) => (cqpSubExprs[`subcqp${idx}`] = subCqp))

const params = {
const data = await count({
group_by_struct: attribute.label,
cqp,
corpus: attribute.corpora.join(","),
incremental: true,
split: attribute.label,
relative_to_struct: relative ? attribute.label : undefined,
}
_.extend(params, settings.corpusListing.getWithinParameters())

_.extend(params, cqpSubExprs)

const data = await korpRequest<KorpStatsResponse>("count", params)
...settings.corpusListing.getWithinParameters(),
...cqpSubExprs,
})

if ("ERROR" in data) {
// TODO Create a KorpBackendError which could be displayed nicely
Expand All @@ -161,10 +145,7 @@ export async function requestMapData(
return { corpora: attribute.corpora, cqp, within, data: result, attribute }
}

export async function getDataForReadingMode(
inputCorpus: string,
textId: string
): Promise<KorpResponse<KorpQueryResponse>> {
export async function getDataForReadingMode(inputCorpus: string, textId: string): Promise<KorpResponse<QueryResponse>> {
const corpus = inputCorpus.toUpperCase()
const corpusSettings = settings.corpusListing.get(inputCorpus)

Expand All @@ -187,5 +168,5 @@ export async function getDataForReadingMode(
end: 0,
}

return korpRequest<KorpQueryResponse>("query", params)
return korpRequest<QueryResponse>("query", params)
}
3 changes: 1 addition & 2 deletions app/scripts/backend/graph-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import _ from "lodash"
import settings from "@/settings"
import BaseProxy from "@/backend/base-proxy"
import { AjaxSettings, Granularity, Histogram, KorpResponse, NumericString } from "@/backend/types"
import { AbsRelTuple } from "@/statistics.types"
import { AbsRelTuple, AjaxSettings, Granularity, Histogram, KorpResponse, NumericString } from "@/backend/types"
import { Factory, httpConfAddMethod } from "@/util"

export class GraphProxy extends BaseProxy<KorpCountTimeResponse> {
Expand Down
94 changes: 12 additions & 82 deletions app/scripts/backend/kwic-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import _ from "lodash"
import settings from "@/settings"
import BaseProxy from "@/backend/base-proxy"
import type { AjaxSettings, KorpResponse, ProgressReport, ProgressResponse } from "@/backend/types"
import type { AjaxSettings, KorpResponse, ProgressReport } from "@/backend/types"
import { locationSearchGet, httpConfAddMethod, Factory } from "@/util"
import { QueryParams, QueryResponse } from "./client"

export class KwicProxy extends BaseProxy<KorpQueryResponse> {
export class KwicProxy extends BaseProxy<QueryResponse> {
foundKwic: boolean
prevCQP?: string
prevParams: KorpQueryParams | null
prevParams: QueryParams | null
prevRequest: JQuery.AjaxSettings | null
prevUrl?: string
queryData?: string
Expand All @@ -24,9 +25,9 @@ export class KwicProxy extends BaseProxy<KorpQueryResponse> {
makeRequest(
options: KorpQueryRequestOptions,
page: number | undefined,
progressCallback: (data: ProgressReport<KorpQueryResponse>) => void,
kwicCallback: (data: KorpResponse<KorpQueryResponse>) => void
): JQuery.jqXHR<KorpResponse<KorpQueryResponse>> {
progressCallback: (data: ProgressReport<QueryResponse>) => void,
kwicCallback: (data: KorpResponse<QueryResponse>) => void
): JQuery.jqXHR<KorpResponse<QueryResponse>> {
const self = this
this.foundKwic = false
this.resetRequest()
Expand All @@ -49,7 +50,7 @@ export class KwicProxy extends BaseProxy<KorpQueryResponse> {

const command = options.ajaxParams.command || "query"

const data: KorpQueryParams = {
const data: QueryParams = {
default_context: settings.default_overview_context,
...getPageInterval(),
...options.ajaxParams,
Expand Down Expand Up @@ -103,7 +104,7 @@ export class KwicProxy extends BaseProxy<KorpQueryResponse> {
self.prevUrl = self.makeUrlWithParams(this.url, data)
},

success(data: KorpQueryResponse, status, jqxhr) {
success(data: QueryResponse, status, jqxhr) {
self.queryData = data.query_data
self.cleanup()
// TODO Should be `options.ajaxParams.incremental`?
Expand All @@ -119,12 +120,12 @@ export class KwicProxy extends BaseProxy<KorpQueryResponse> {
progressCallback(progressObj)
if ("kwic" in progressObj.struct) {
this.foundKwic = true
return kwicCallback(progressObj.struct as KorpQueryResponse)
return kwicCallback(progressObj.struct as QueryResponse)
}
},
}

const def = $.ajax(httpConfAddMethod(ajaxSettings)) as JQuery.jqXHR<KorpResponse<KorpQueryResponse>>
const def = $.ajax(httpConfAddMethod(ajaxSettings)) as JQuery.jqXHR<KorpResponse<QueryResponse>>
this.pendingRequests.push(def)
return def
}
Expand All @@ -133,84 +134,13 @@ export class KwicProxy extends BaseProxy<KorpQueryResponse> {
const kwicProxyFactory = new Factory(KwicProxy)
export default kwicProxyFactory

/** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Concordance/paths/~1query/get */
export type KorpQueryParams = {
corpus: string
cqp: string
start?: number
end?: number
default_context?: string
context?: string
show?: string
show_struct?: string
default_within?: string
within?: string
in_order?: boolean
sort?: string
random_seed?: number
cut?: number
[cqpn: `cqp${number}`]: string
expand_prequeries?: boolean
incremental?: boolean
query_data?: string
}

export type KorpQueryRequestOptions = {
// TODO Should start,end really exist here as well as under ajaxParams?
start?: number
end?: number
ajaxParams: KorpQueryParams & {
ajaxParams: QueryParams & {
command?: string
}
}

type Interval = { start: number; end: number }

/** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Concordance/paths/~1query/get */
export type KorpQueryResponse = {
/** Search hits */
kwic: ApiKwic[]
/** Total number of hits */
hits: number
/** Number of hits for each corpus */
corpus_hits: Record<string, number>
/** Order of corpora in result */
corpus_order: string[]
/** Execution time in seconds */
time: number
/** A hash of this query */
query_data: string
}

/** Search hits */
export type ApiKwic = {
/** An object for each token in the context, with attribute values for that token */
tokens: Token[]
/** Attribute values for the context (e.g. sentence) */
structs: Record<string, any>
/** Specifies the position of the match in the context. If `in_order` is false, `match` will consist of a list of match objects, one per highlighted word */
match: KwicMatch | KwicMatch[]
/** Hits from aligned corpora if available, otherwise omitted */
aligned: {
[linkedCorpusId: `${string}-${string}`]: Record<string, any>[]
}
}

/** Specifies the position of a match in a context */
type KwicMatch = {
/** Start position of the match within the context */
start: number
/** End position of the match within the context */
end: number
/** Global corpus position of the match */
position: number
}

export type Token = {
word: string
structs?: {
open?: Record<string, Record<string, string>>[]
close?: string[]
}
[attr: string]: any
}
60 changes: 11 additions & 49 deletions app/scripts/backend/stats-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
import _ from "lodash"
import settings from "@/settings"
import BaseProxy from "@/backend/base-proxy"
import type { AjaxSettings, KorpResponse, ProgressResponse, ProgressReport } from "@/backend/types"
import { StatsNormalized, StatsColumn, StatisticsWorkerResult } from "@/statistics.types"
import type { AjaxSettings, KorpResponse, ProgressResponse, ProgressReport, StatsColumn } from "@/backend/types"
import { StatsNormalized, StatisticsWorkerResult } from "@/statistics.types"
import { locationSearchGet, httpConfAddMethod, Factory } from "@/util"
import { statisticsService } from "@/statistics"
import { CountParams, CountResponse } from "./client"

/**
* Stats in the response can be split by subqueries if the `subcqp#` param is used, but otherwise not.
*
* This function adds a split (converts non-arrays to single-element arrays) if not, so higher code can assume the same shape regardless.
*/
export function normalizeStatsData(data: KorpStatsResponse): StatsNormalized {
export function normalizeStatsData(data: CountResponse): StatsNormalized {
const combined = !Array.isArray(data.combined) ? [data.combined] : data.combined

const corpora: Record<string, StatsColumn[]> = {}
Expand All @@ -25,8 +26,8 @@ export function normalizeStatsData(data: KorpStatsResponse): StatsNormalized {
return { ...data, combined, corpora }
}

export class StatsProxy extends BaseProxy<KorpStatsResponse> {
prevParams: KorpStatsParams | null
export class StatsProxy extends BaseProxy<CountResponse> {
prevParams: CountParams | null
prevRequest: AjaxSettings | null
prevUrl?: string

Expand All @@ -36,7 +37,7 @@ export class StatsProxy extends BaseProxy<KorpStatsResponse> {
this.prevParams = null
}

makeParameters(reduceVals: string[], cqp: string, ignoreCase: boolean): KorpStatsParams {
makeParameters(reduceVals: string[], cqp: string, ignoreCase: boolean): CountParams {
const structAttrs = settings.corpusListing.getStructAttrs(settings.corpusListing.getReduceLang())
const groupBy: string[] = []
const groupByStruct: string[] = []
Expand Down Expand Up @@ -66,7 +67,7 @@ export class StatsProxy extends BaseProxy<KorpStatsResponse> {

makeRequest(
cqp: string,
callback: (data: ProgressReport<KorpStatsResponse>) => void
callback: (data: ProgressReport<CountResponse>) => void
): JQuery.Promise<StatisticsWorkerResult> {
const self = this
this.resetRequest()
Expand Down Expand Up @@ -113,7 +114,7 @@ export class StatsProxy extends BaseProxy<KorpStatsResponse> {
const def: JQuery.Deferred<StatisticsWorkerResult> = $.Deferred()

const url = settings.korp_backend_url + "/count"
const ajaxSettings: AjaxSettings<KorpResponse<KorpStatsResponse>> = {
const ajaxSettings: AjaxSettings<KorpResponse<CountResponse>> = {
url,
data,
beforeSend(req, settings) {
Expand All @@ -137,7 +138,7 @@ export class StatsProxy extends BaseProxy<KorpStatsResponse> {
}
},

success: (data: KorpResponse<KorpStatsResponse>) => {
success: (data: KorpResponse<CountResponse>) => {
self.cleanup()
if ("ERROR" in data) {
console.log("gettings stats failed with error", data.ERROR)
Expand All @@ -156,50 +157,11 @@ export class StatsProxy extends BaseProxy<KorpStatsResponse> {
)
},
}
this.pendingRequests.push($.ajax(httpConfAddMethod(ajaxSettings)) as JQuery.jqXHR<KorpStatsResponse>)
this.pendingRequests.push($.ajax(httpConfAddMethod(ajaxSettings)) as JQuery.jqXHR<CountResponse>)

return def.promise()
}
}

const statsProxyFactory = new Factory(StatsProxy)
export default statsProxyFactory

/** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Statistics/paths/~1count/get */
type KorpStatsParams = {
/** Corpus names, separated by comma */
corpus: string
/** CQP query */
cqp: string
/** Positional attribute by which the hits should be grouped. Defaults to "word" if neither `group_by` nor `group_by_struct` is defined */
group_by?: string
/** Structural attribute by which the hits should be grouped. The value for the first token of the hit will be used */
group_by_struct?: string
/** Prevent search from crossing boundaries of the given structural attribute, e.g. 'sentence'. */
default_within?: string
/** Like default_within, but for specific corpora, overriding the default. Specified using the format 'corpus:attribute' */
within?: string
ignore_case?: string
relative_to_struct?: string
split?: string
top?: string
[cqpn: `cqp${number}`]: string
expand_prequeries?: boolean
[subcqpn: `subcqp${number}`]: string
start?: number
end?: number
/** Incrementally return progress updates when the calculation for each corpus is finished */
incremental?: boolean
}

/** @see https://ws.spraakbanken.gu.se/docs/korp#tag/Statistics/paths/~1count/get */
export type KorpStatsResponse = {
corpora: {
[name: string]: StatsColumn | StatsColumn[]
}
combined: StatsColumn | StatsColumn[]
/** Total number of different values */
count: number
/** Execution time in seconds */
time: number
}
Loading

0 comments on commit e0fa9b5

Please sign in to comment.