refactor(frontend): normalize naming conventions
This commit is contained in:
@@ -24,7 +24,7 @@ npm run start
|
|||||||
|
|
||||||
## Coding Style & Naming Conventions
|
## Coding Style & Naming Conventions
|
||||||
|
|
||||||
Use TypeScript and React function components. Follow ESLint and Next.js conventions. Use `PascalCase` for components, `camelCase` for variables/functions, and descriptive feature-oriented filenames. Prefer MUI components and existing design tokens/patterns for UI. Keep operational screens dense, clear, and task-focused.
|
Use TypeScript and React function components. Follow ESLint and Next.js conventions. Use `PascalCase` for React component files and component names. Use `camelCase` for ordinary TypeScript modules, hooks, stores, providers, utilities, variables, and functions. Next.js route directories under `src/app` use `kebab-case`; route groups and dynamic segments keep the Next.js syntax such as `(main)` and `[...nextauth]`. Keep backend/Agent boundary fields and query parameters in the shape required by the API, typically `snake_case`, and do not translate third-party SDK fields. Prefer MUI components and existing design tokens/patterns for UI. Keep operational screens dense, clear, and task-focused.
|
||||||
|
|
||||||
## Testing Guidelines
|
## Testing Guidelines
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Frontend Naming Audit
|
||||||
|
|
||||||
|
DOC-004 audit for the internal `TJWaterFrontend_Refine` application.
|
||||||
|
|
||||||
|
## Local frontend naming
|
||||||
|
|
||||||
|
- Next.js route directories under `src/app` are already `kebab-case`: `audit-logs`, `health-risk-analysis`, `hydraulic-simulation`, `monitoring-place-optimization`, `network-simulation`, `scada-data-cleaning`, and `system-admin`.
|
||||||
|
- Route groups and dynamic segments keep Next.js syntax: `(main)` and `[...nextauth]`.
|
||||||
|
- Local ordinary module filenames now use `camelCase`, including `src/utils/breaksClassification.ts`, `src/components/chat/globalChatboxUtils.ts`, and `src/components/chat/globalChatboxVoice.ts`.
|
||||||
|
- React component files remain `PascalCase.tsx`, including `src/app/RefineContext.tsx`, `src/components/chat/GlobalChatboxParts.tsx`, and domain directories under `src/components/olmap`.
|
||||||
|
|
||||||
|
## API boundary naming
|
||||||
|
|
||||||
|
Frontend request and response boundary fields intentionally keep backend/Agent wire names. Examples include `project_id`, `user_id`, `scheme_name`, `scheme_type`, `start_time`, `end_time`, `session_id`, `request_id`, and `keep_message_count`.
|
||||||
|
|
||||||
|
Current direct API calls mostly use new `kebab-case` URL paths, including:
|
||||||
|
|
||||||
|
- `/api/v1/admin/projects`
|
||||||
|
- `/api/v1/audit/logs`
|
||||||
|
- `/api/v1/projects/open`
|
||||||
|
- `/api/v1/project-info`
|
||||||
|
- `/api/v1/schemes`
|
||||||
|
- `/api/v1/sensor-placement-schemes`
|
||||||
|
- `/api/v1/burst-analysis`
|
||||||
|
- `/api/v1/valve-isolation-analysis`
|
||||||
|
- `/api/v1/flushing-analysis`
|
||||||
|
- `/api/v1/contaminant-simulation`
|
||||||
|
- `/api/v1/simulations/run-by-date`
|
||||||
|
- `/api/v1/burst-detection/detect`
|
||||||
|
- `/api/v1/burst-location/locate`
|
||||||
|
- `/api/v1/scada/by-ids-field-time-range`
|
||||||
|
- `/api/v1/composite/clean-scada`
|
||||||
|
- `/api/v1/agent/chat/render-ref/{render_ref}`
|
||||||
|
|
||||||
|
## Legacy URL inventory
|
||||||
|
|
||||||
|
The frontend no longer calls these active legacy URLs directly. The backend still exposes them as deprecated compatibility aliases:
|
||||||
|
|
||||||
|
| Current frontend URL | Files | Suggested target |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `/api/v1/openproject/` | `src/contexts/ProjectContext.tsx` | `/api/v1/projects/open` or `/api/v1/project/open` |
|
||||||
|
| `/api/v1/project_info/` | `src/contexts/ProjectContext.tsx` | `/api/v1/project-info` |
|
||||||
|
| `/api/v1/getallschemes/` | burst, burst simulation, contaminant, flushing scheme query components | `/api/v1/schemes` |
|
||||||
|
| `/api/v1/getallsensorplacements/` | `src/components/olmap/MonitoringPlaceOptimization/SchemeQuery.tsx` | `/api/v1/sensor-placement-schemes` |
|
||||||
|
| `/api/v1/sensorplacementscheme/create` | `src/components/olmap/MonitoringPlaceOptimization/OptimizationParameters.tsx` | `/api/v1/sensor-placement-schemes` |
|
||||||
|
| `/api/v1/burst_analysis/` | `src/components/olmap/BurstSimulation/AnalysisParameters.tsx` | `/api/v1/burst-analysis` |
|
||||||
|
| `/api/v1/valve_isolation_analysis/` | `src/components/olmap/BurstSimulation/ValveIsolation.tsx` | `/api/v1/valve-isolation-analysis` |
|
||||||
|
| `/api/v1/flushing_analysis/` | `src/components/olmap/FlushingAnalysis/AnalysisParameters.tsx` | `/api/v1/flushing-analysis` |
|
||||||
|
| `/api/v1/contaminant_simulation/` | `src/components/olmap/ContaminantSimulation/AnalysisParameters.tsx` | `/api/v1/contaminant-simulation` |
|
||||||
|
| `/api/v1/runsimulationmanuallybydate/` | `src/components/olmap/core/Controls/Timeline.tsx` | `/api/v1/simulations/run-by-date` |
|
||||||
|
|
||||||
|
Already migrated frontend code leaves comments showing older pre-`/api/v1` URLs in `src/components/olmap/core/Controls/Toolbar.tsx`; those comments are historical only and are not active calls.
|
||||||
|
|
||||||
|
## Follow-up
|
||||||
|
|
||||||
|
Continue tracking broad passive legacy backend routes under the shared legacy API compatibility strategy.
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import React, { Suspense } from "react";
|
import React, { Suspense } from "react";
|
||||||
import { RefineContext } from "./_refine_context";
|
import { RefineContext } from "./RefineContext";
|
||||||
import { META_DATA } from "@config/config";
|
import { META_DATA } from "@config/config";
|
||||||
|
|
||||||
export const metadata: Metadata = META_DATA;
|
export const metadata: Metadata = META_DATA;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import {
|
|||||||
type ContentSegment,
|
type ContentSegment,
|
||||||
} from "./chatMessageSections";
|
} from "./chatMessageSections";
|
||||||
import type { Message, SpeechState } from "./GlobalChatbox.types";
|
import type { Message, SpeechState } from "./GlobalChatbox.types";
|
||||||
import { stripMarkdown } from "./GlobalChatbox.utils";
|
import { stripMarkdown } from "./globalChatboxUtils";
|
||||||
import { AgentProgressTimeline } from "./AgentProgressTimeline";
|
import { AgentProgressTimeline } from "./AgentProgressTimeline";
|
||||||
import { ChartGenerationSkeleton, ChatInlineChart } from "./ChatInlineChart";
|
import { ChartGenerationSkeleton, ChatInlineChart } from "./ChatInlineChart";
|
||||||
import { ChatToolCallBlock } from "./ChatToolCallBlock";
|
import { ChatToolCallBlock } from "./ChatToolCallBlock";
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import { AgentComposer, type AgentComposerHandle } from "./AgentComposer";
|
|||||||
import { AgentHeader } from "./AgentHeader";
|
import { AgentHeader } from "./AgentHeader";
|
||||||
import { AgentHistoryPanel } from "./AgentHistoryPanel";
|
import { AgentHistoryPanel } from "./AgentHistoryPanel";
|
||||||
import { AgentWorkspace } from "./AgentWorkspace";
|
import { AgentWorkspace } from "./AgentWorkspace";
|
||||||
import { Blob } from "./GlobalChatbox.parts";
|
import { Blob } from "./GlobalChatboxParts";
|
||||||
import type { Props } from "./GlobalChatbox.types";
|
import type { Props } from "./GlobalChatbox.types";
|
||||||
import { PRESET_PROMPTS } from "./GlobalChatbox.utils";
|
import { PRESET_PROMPTS } from "./globalChatboxUtils";
|
||||||
import { useSpeechRecognition, useSpeechSynthesis } from "./GlobalChatbox.voice";
|
import { useSpeechRecognition, useSpeechSynthesis } from "./globalChatboxVoice";
|
||||||
import { useAgentChatSession } from "./hooks/useAgentChatSession";
|
import { useAgentChatSession } from "./hooks/useAgentChatSession";
|
||||||
import { useAgentToolActions } from "./hooks/useAgentToolActions";
|
import { useAgentToolActions } from "./hooks/useAgentToolActions";
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type {
|
|||||||
LoadedChatState,
|
LoadedChatState,
|
||||||
Message,
|
Message,
|
||||||
} from "./GlobalChatbox.types";
|
} from "./GlobalChatbox.types";
|
||||||
import { cloneMessages } from "./GlobalChatbox.utils";
|
import { cloneMessages } from "./globalChatboxUtils";
|
||||||
|
|
||||||
type BackendSessionPayload = {
|
type BackendSessionPayload = {
|
||||||
id?: string;
|
id?: string;
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { cloneMessage } from "./GlobalChatbox.utils";
|
import { cloneMessage } from "./globalChatboxUtils";
|
||||||
import type { Message } from "./GlobalChatbox.types";
|
import type { Message } from "./GlobalChatbox.types";
|
||||||
|
|
||||||
describe("cloneMessage", () => {
|
describe("cloneMessage", () => {
|
||||||
@@ -9,7 +9,7 @@ import type {
|
|||||||
ChatProgress,
|
ChatProgress,
|
||||||
Message,
|
Message,
|
||||||
} from "../GlobalChatbox.types";
|
} from "../GlobalChatbox.types";
|
||||||
import { createId } from "../GlobalChatbox.utils";
|
import { createId } from "../globalChatboxUtils";
|
||||||
|
|
||||||
export const upsertProgress = (
|
export const upsertProgress = (
|
||||||
progress: ChatProgress[] | undefined,
|
progress: ChatProgress[] | undefined,
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
// Tests for useAgentChatSession are split by behavior boundary.
|
|
||||||
// See useAgentChatSession.lifecycle.test.tsx and useAgentChatSession.actions.test.tsx.
|
|
||||||
@@ -5,7 +5,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|||||||
import { abortAgentChat, forkAgentChat, rejectAgentQuestion, replyAgentPermission, replyAgentQuestion, resumeAgentChatStream, streamAgentChat } from "@/lib/chatStream";
|
import { abortAgentChat, forkAgentChat, rejectAgentQuestion, replyAgentPermission, replyAgentQuestion, resumeAgentChatStream, streamAgentChat } from "@/lib/chatStream";
|
||||||
import type { PermissionReply, StreamEvent } from "@/lib/chatStream";
|
import type { PermissionReply, StreamEvent } from "@/lib/chatStream";
|
||||||
import type { AgentArtifact, ChatSessionSummary, Message } from "../GlobalChatbox.types";
|
import type { AgentArtifact, ChatSessionSummary, Message } from "../GlobalChatbox.types";
|
||||||
import { cloneMessages } from "../GlobalChatbox.utils";
|
import { cloneMessages } from "../globalChatboxUtils";
|
||||||
import { createEmptyChatState, deleteChatSession, listChatSessions, loadChatSessionById, updateChatSessionTitle } from "../chatStorage";
|
import { createEmptyChatState, deleteChatSession, listChatSessions, loadChatSessionById, updateChatSessionTitle } from "../chatStorage";
|
||||||
import { applyQuestionResponse, cancelRunningTodos, completeRunningProgress, createAssistantMessage, createTodoUpdateFromEvent, createUserMessage, dedupeQuestionsAcrossMessages, finalizeAssistantMessageAfterAbort, normalizeSessionTodos, toPermissionStatus, upsertPermission, upsertProgress, upsertQuestionAcrossMessages } from "./agentChatSessionState";
|
import { applyQuestionResponse, cancelRunningTodos, completeRunningProgress, createAssistantMessage, createTodoUpdateFromEvent, createUserMessage, dedupeQuestionsAcrossMessages, finalizeAssistantMessageAfterAbort, normalizeSessionTodos, toPermissionStatus, upsertPermission, upsertProgress, upsertQuestionAcrossMessages } from "./agentChatSessionState";
|
||||||
import type { PromptRunOptions, UseAgentChatSessionOptions } from "./useAgentChatSession.types";
|
import type { PromptRunOptions, UseAgentChatSessionOptions } from "./useAgentChatSession.types";
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const AnalysisParameters: React.FC<Props> = ({ onResult }) => {
|
|||||||
|
|
||||||
setSchemeLoading(true);
|
setSchemeLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get(`${config.BACKEND_URL}/api/v1/getallschemes/`, {
|
const response = await api.get(`${config.BACKEND_URL}/api/v1/schemes`, {
|
||||||
params: { network: NETWORK_NAME },
|
params: { network: NETWORK_NAME },
|
||||||
});
|
});
|
||||||
const burstSchemes = (response.data as SchemeItem[]).filter(
|
const burstSchemes = (response.data as SchemeItem[]).filter(
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const AnalysisParameters: React.FC<Props> = ({ onResult }) => {
|
|||||||
|
|
||||||
setSchemeLoading(true);
|
setSchemeLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get(`${config.BACKEND_URL}/api/v1/getallschemes/`, {
|
const response = await api.get(`${config.BACKEND_URL}/api/v1/schemes`, {
|
||||||
params: { network: NETWORK_NAME },
|
params: { network: NETWORK_NAME },
|
||||||
});
|
});
|
||||||
const burstSchemes = (response.data as SchemeItem[]).filter(
|
const burstSchemes = (response.data as SchemeItem[]).filter(
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await api.get(`${config.BACKEND_URL}/api/v1/burst_analysis/`, {
|
await api.get(`${config.BACKEND_URL}/api/v1/burst-analysis`, {
|
||||||
params,
|
params,
|
||||||
paramsSerializer: {
|
paramsSerializer: {
|
||||||
indexes: null, // 移除数组索引,即由 burst_ID[] 变为 burst_ID
|
indexes: null, // 移除数组索引,即由 burst_ID[] 变为 burst_ID
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get(
|
const response = await api.get(
|
||||||
`${config.BACKEND_URL}/api/v1/getallschemes/?network=${network}`,
|
`${config.BACKEND_URL}/api/v1/schemes?network=${network}`,
|
||||||
);
|
);
|
||||||
let filteredResults = response.data;
|
let filteredResults = response.data;
|
||||||
|
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ const ValveIsolation: React.FC<ValveIsolationProps> = ({
|
|||||||
params.disabled_valves = disabled;
|
params.disabled_valves = disabled;
|
||||||
}
|
}
|
||||||
const response = await api.get(
|
const response = await api.get(
|
||||||
`${config.BACKEND_URL}/api/v1/valve_isolation_analysis/`,
|
`${config.BACKEND_URL}/api/v1/valve-isolation-analysis`,
|
||||||
{
|
{
|
||||||
params,
|
params,
|
||||||
paramsSerializer: {
|
paramsSerializer: {
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
scheme_name: schemeName,
|
scheme_name: schemeName,
|
||||||
};
|
};
|
||||||
|
|
||||||
await api.get(`${config.BACKEND_URL}/api/v1/contaminant_simulation/`, {
|
await api.get(`${config.BACKEND_URL}/api/v1/contaminant-simulation`, {
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get(
|
const response = await api.get(
|
||||||
`${config.BACKEND_URL}/api/v1/getallschemes/?network=${network}`,
|
`${config.BACKEND_URL}/api/v1/schemes?network=${network}`,
|
||||||
);
|
);
|
||||||
let filteredResults = response.data;
|
let filteredResults = response.data;
|
||||||
|
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ const AnalysisParameters: React.FC = () => {
|
|||||||
// but axios usually handles array as valves[]=1&valves[]=2
|
// but axios usually handles array as valves[]=1&valves[]=2
|
||||||
// FastAPI default expects repeated query params.
|
// FastAPI default expects repeated query params.
|
||||||
|
|
||||||
const response = await api.get(`${config.BACKEND_URL}/api/v1/flushing_analysis/`, {
|
const response = await api.get(`${config.BACKEND_URL}/api/v1/flushing-analysis`, {
|
||||||
params,
|
params,
|
||||||
// Ensure arrays are sent as repeated keys: valves=1&valves=2
|
// Ensure arrays are sent as repeated keys: valves=1&valves=2
|
||||||
paramsSerializer: {
|
paramsSerializer: {
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get(
|
const response = await api.get(
|
||||||
`${config.BACKEND_URL}/api/v1/getallschemes/?network=${network}`,
|
`${config.BACKEND_URL}/api/v1/schemes?network=${network}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
let filteredResults = response.data;
|
let filteredResults = response.data;
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ const OptimizationParameters: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
// 发送优化请求
|
// 发送优化请求
|
||||||
const response = await api.post(
|
const response = await api.post(
|
||||||
`${config.BACKEND_URL}/api/v1/sensorplacementscheme/create`,
|
`${config.BACKEND_URL}/api/v1/sensor-placement-schemes`,
|
||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await api.get(
|
const response = await api.get(
|
||||||
`${config.BACKEND_URL}/api/v1/getallsensorplacements/?network=${network}`,
|
`${config.BACKEND_URL}/api/v1/sensor-placement-schemes?network=${network}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
let filteredResults = response.data;
|
let filteredResults = response.data;
|
||||||
|
|||||||
@@ -643,7 +643,7 @@ const Timeline: React.FC<TimelineProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const response = await apiFetch(
|
const response = await apiFetch(
|
||||||
`${config.BACKEND_URL}/api/v1/runsimulationmanuallybydate/`,
|
`${config.BACKEND_URL}/api/v1/simulations/run-by-date`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FlatStyleLike } from "ol/style/flat";
|
import { FlatStyleLike } from "ol/style/flat";
|
||||||
|
|
||||||
import { calculateClassification } from "@utils/breaks_classification";
|
import { calculateClassification } from "@utils/breaksClassification";
|
||||||
import { parseColor } from "@utils/parseColor";
|
import { parseColor } from "@utils/parseColor";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import {
|
|||||||
StyleEditorStateProps,
|
StyleEditorStateProps,
|
||||||
} from "./styleEditorTypes";
|
} from "./styleEditorTypes";
|
||||||
import { LegendStyleConfig } from "./StyleLegend";
|
import { LegendStyleConfig } from "./StyleLegend";
|
||||||
import { calculateClassification } from "@utils/breaks_classification";
|
import { calculateClassification } from "@utils/breaksClassification";
|
||||||
|
|
||||||
const UNIT_HEADLOSS_RANGE: [number, number] = [0, 5];
|
const UNIT_HEADLOSS_RANGE: [number, number] = [0, 5];
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
try {
|
try {
|
||||||
// Open project backend (simulation model)
|
// Open project backend (simulation model)
|
||||||
const openResponse = await apiFetch(
|
const openResponse = await apiFetch(
|
||||||
`${config.BACKEND_URL}/api/v1/openproject/?network=${net}`,
|
`${config.BACKEND_URL}/api/v1/projects/open?network=${net}`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
@@ -64,7 +64,7 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
|
|
||||||
// Fetch project metadata
|
// Fetch project metadata
|
||||||
const infoResponse = await apiFetch(
|
const infoResponse = await apiFetch(
|
||||||
`${config.BACKEND_URL}/api/v1/project_info/?network=${net}`,
|
`${config.BACKEND_URL}/api/v1/project-info?network=${net}`,
|
||||||
);
|
);
|
||||||
if (!infoResponse.ok) {
|
if (!infoResponse.ok) {
|
||||||
console.warn(
|
console.warn(
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function variance(data: number[], start: number, end: number): number {
|
|||||||
return data.slice(start, end + 1).reduce((sum, val) => sum + (val - mean) ** 2, 0);
|
return data.slice(start, end + 1).reduce((sum, val) => sum + (val - mean) ** 2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function jenks_breaks_jenkspy(data: number[], nClasses: number): number[] {
|
function jenksBreaksJenkspy(data: number[], nClasses: number): number[] {
|
||||||
if (data.length === 0) return [];
|
if (data.length === 0) return [];
|
||||||
if (nClasses >= data.length) return data.slice().sort((a, b) => a - b);
|
if (nClasses >= data.length) return data.slice().sort((a, b) => a - b);
|
||||||
|
|
||||||
@@ -92,13 +92,13 @@ export function jenks_breaks_jenkspy(data: number[], nClasses: number): number[]
|
|||||||
return breaks;
|
return breaks;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function jenks_with_stratified_sampling(
|
function jenksWithStratifiedSampling(
|
||||||
data: number[],
|
data: number[],
|
||||||
nClasses: number,
|
nClasses: number,
|
||||||
sampleSize = 10000
|
sampleSize = 10000
|
||||||
): number[] {
|
): number[] {
|
||||||
if (data.length <= sampleSize) {
|
if (data.length <= sampleSize) {
|
||||||
return jenks_breaks_jenkspy(data, nClasses);
|
return jenksBreaksJenkspy(data, nClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortedData = data.slice().sort((a, b) => a - b);
|
const sortedData = data.slice().sort((a, b) => a - b);
|
||||||
@@ -112,7 +112,7 @@ export function jenks_with_stratified_sampling(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return jenks_breaks_jenkspy(sampledData, nClasses);
|
return jenksBreaksJenkspy(sampledData, nClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateClassification(
|
export function calculateClassification(
|
||||||
@@ -129,7 +129,7 @@ export function calculateClassification(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (classificationMethod === "jenks_optimized") {
|
if (classificationMethod === "jenks_optimized") {
|
||||||
return jenks_with_stratified_sampling(data, segments);
|
return jenksWithStratifiedSampling(data, segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
Reference in New Issue
Block a user