140 lines
3.8 KiB
TypeScript
140 lines
3.8 KiB
TypeScript
/**
|
|
* Static import of URT Taxonomy data
|
|
*/
|
|
|
|
import urtData from './urt-codes.json';
|
|
import type { URTTaxonomy } from './types';
|
|
|
|
export const taxonomy = urtData as URTTaxonomy;
|
|
|
|
/**
|
|
* Get subcode count for a category
|
|
*/
|
|
export function getSubcodeCount(categoryKey: string): number {
|
|
const domainKey = categoryKey[0];
|
|
const domain = taxonomy.domains[domainKey];
|
|
if (!domain) return 0;
|
|
|
|
const category = domain.categories[categoryKey];
|
|
if (!category) return 0;
|
|
|
|
return Object.keys(category.subcodes).length;
|
|
}
|
|
|
|
/**
|
|
* Get subcode count for a domain
|
|
*/
|
|
export function getDomainSubcodeCount(domainKey: string): number {
|
|
return taxonomy.indices.subcodes_by_domain[domainKey] || 0;
|
|
}
|
|
|
|
/**
|
|
* Get category count for a domain
|
|
*/
|
|
export function getDomainCategoryCount(domainKey: string): number {
|
|
const domain = taxonomy.domains[domainKey];
|
|
if (!domain) return 0;
|
|
return Object.keys(domain.categories).length;
|
|
}
|
|
|
|
/**
|
|
* Search taxonomy codes by text
|
|
*/
|
|
export function searchTaxonomy(query: string): {
|
|
domains: string[];
|
|
categories: string[];
|
|
subcodes: string[];
|
|
} {
|
|
const normalizedQuery = query.toLowerCase().trim();
|
|
if (!normalizedQuery) {
|
|
return { domains: [], categories: [], subcodes: [] };
|
|
}
|
|
|
|
const matchedDomains: string[] = [];
|
|
const matchedCategories: string[] = [];
|
|
const matchedSubcodes: string[] = [];
|
|
|
|
for (const [domainKey, domain] of Object.entries(taxonomy.domains)) {
|
|
const domainMatches =
|
|
domainKey.toLowerCase().includes(normalizedQuery) ||
|
|
domain.name.toLowerCase().includes(normalizedQuery) ||
|
|
domain.description.toLowerCase().includes(normalizedQuery);
|
|
|
|
if (domainMatches) {
|
|
matchedDomains.push(domainKey);
|
|
}
|
|
|
|
for (const [categoryKey, category] of Object.entries(domain.categories)) {
|
|
const categoryMatches =
|
|
categoryKey.toLowerCase().includes(normalizedQuery) ||
|
|
category.name.toLowerCase().includes(normalizedQuery) ||
|
|
category.definition.toLowerCase().includes(normalizedQuery);
|
|
|
|
if (categoryMatches) {
|
|
matchedCategories.push(categoryKey);
|
|
}
|
|
|
|
for (const [subcodeKey, subcode] of Object.entries(category.subcodes)) {
|
|
const subcodeMatches =
|
|
subcodeKey.toLowerCase().includes(normalizedQuery) ||
|
|
subcode.name.toLowerCase().includes(normalizedQuery) ||
|
|
subcode.definition.toLowerCase().includes(normalizedQuery) ||
|
|
subcode.positive_example.toLowerCase().includes(normalizedQuery) ||
|
|
subcode.negative_example.toLowerCase().includes(normalizedQuery);
|
|
|
|
if (subcodeMatches) {
|
|
matchedSubcodes.push(subcodeKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
domains: matchedDomains,
|
|
categories: matchedCategories,
|
|
subcodes: matchedSubcodes,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get parent domain and category for a subcode
|
|
*/
|
|
export function getSubcodeContext(subcodeKey: string): {
|
|
domainKey: string;
|
|
categoryKey: string;
|
|
} | null {
|
|
// Parse subcode key like "O1.01" -> domain "O", category "O1"
|
|
const match = subcodeKey.match(/^([OPJEAVR])(\d)/);
|
|
if (!match) return null;
|
|
|
|
const domainKey = match[1];
|
|
const categoryKey = `${match[1]}${match[2]}`;
|
|
|
|
return { domainKey, categoryKey };
|
|
}
|
|
|
|
/**
|
|
* Get parent domain for a category
|
|
*/
|
|
export function getCategoryDomain(categoryKey: string): string | null {
|
|
const match = categoryKey.match(/^([OPJEAVR])/);
|
|
return match ? match[1] : null;
|
|
}
|
|
|
|
/**
|
|
* Get subcode definition by subcode key (e.g., "J1.04" -> "Meeting scheduled times")
|
|
*/
|
|
export function getSubcodeDefinition(subcodeKey: string): string | null {
|
|
const context = getSubcodeContext(subcodeKey);
|
|
if (!context) return null;
|
|
|
|
const domain = taxonomy.domains[context.domainKey];
|
|
if (!domain) return null;
|
|
|
|
const category = domain.categories[context.categoryKey];
|
|
if (!category) return null;
|
|
|
|
const subcode = category.subcodes[subcodeKey];
|
|
return subcode?.definition || null;
|
|
}
|