From c4b0ba9c10d92749d75bd2a57ac28fa417f30936 Mon Sep 17 00:00:00 2001 From: lublagg Date: Thu, 5 Oct 2023 15:33:11 -0400 Subject: [PATCH 1/2] Add in support for Economic Class. --- src/components/app.tsx | 4 ++-- src/constants/codapMetadata.ts | 35 +++++++++++++++++++++++++++++++++- src/scripts/api.ts | 18 +++++++++++++---- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/components/app.tsx b/src/components/app.tsx index 49e322d..aab4d0c 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -57,10 +57,10 @@ function App() { setStatusGraphic(); const res = await createTableFromSelections(selectedOptions); if (res !== "success") { - setStatusMessage(strings.fetchSuccess); + setStatusMessage(strings.fetchError); setStatusGraphic(); } else { - setStatusMessage(strings.fetchError); + setStatusMessage(strings.fetchSuccess); setStatusGraphic(); } }; diff --git a/src/constants/codapMetadata.ts b/src/constants/codapMetadata.ts index 56370df..658b122 100644 --- a/src/constants/codapMetadata.ts +++ b/src/constants/codapMetadata.ts @@ -179,5 +179,38 @@ export const attrToCODAPColumnName: IAttrToCodapColumn = { "WHEAT - ACRES HARVESTED": { "attributeNameInCodapTable": "Wheat Area Harvested", "unitInCodapTable": "Acres Harvested" - } + }, + "ECONOMIC CLASS: (1,000 TO 9,999 $)": { + "attributeNameInCodapTable": "Small Farm ($1,000 - $9,999)", + "unitInCodapTable": "" + }, + "ECONOMIC CLASS: (10,000 TO 99,999 $)": { + "attributeNameInCodapTable": "Small Medium Farm ($10,000 - $99,000)", + "unitInCodapTable": "# of Farms" + }, + "ECONOMIC CLASS: (100,000 TO 249,999 $)": { + "attributeNameInCodapTable": "Medium Farm ($100,000 - $249,000)", + "unitInCodapTable": "# of Farms" + }, + "ECONOMIC CLASS: (250,000 TO 499,999 $)": { + "attributeNameInCodapTable": "Medium Large Farm ($250,000 - $499,999)", + "unitInCodapTable": "# of Farms" + }, + "ECONOMIC CLASS: (500,000 TO 999,999 $)": { + "attributeNameInCodapTable": "Large Farm ($500,000 - $999,999)", + "unitInCodapTable": "# of Farms" + }, + "ECONOMIC CLASS: (1,000,000 OR MORE $)": { + "attributeNameInCodapTable": "Very Large Farm ($1 million or more)", + "unitInCodapTable": "# of Farms" + }, }; + +export const economicClassAttirbutes = [ + "ECONOMIC CLASS: (1,000 TO 9,999 $)", + "ECONOMIC CLASS: (10,000 TO 99,999 $)", + "ECONOMIC CLASS: (100,000 TO 249,999 $)", + "ECONOMIC CLASS: (250,000 TO 499,999 $)", + "ECONOMIC CLASS: (500,000 TO 999,999 $)", + "ECONOMIC CLASS: (1,000,000 OR MORE $)" +]; diff --git a/src/scripts/api.ts b/src/scripts/api.ts index 8aaefeb..a2dbda1 100644 --- a/src/scripts/api.ts +++ b/src/scripts/api.ts @@ -5,7 +5,7 @@ import { connect } from "./connect"; import { cropOptions, fiftyStates } from "../constants/constants"; import { countyData } from "../constants/counties"; import { flatten, getQueryParams } from "./utils"; -import { attrToCODAPColumnName } from "../constants/codapMetadata"; +import { attrToCODAPColumnName, economicClassAttirbutes } from "../constants/codapMetadata"; const baseURL = `https://quickstats.nass.usda.gov/api/api_GET/?key=9ED0BFB8-8DDD-3609-9940-A2341ED6A9E3`; @@ -109,7 +109,12 @@ export const getAllAttrs = (selectedOptions: IStateOptions) => { throw new Error("Invalid attribute"); } const {short_desc} = queryParams; - if (Array.isArray(short_desc)) { + if (attribute === "Economic Class") { + for (const econAttr of economicClassAttirbutes) { + const codapColumnName = attrToCODAPColumnName[econAttr].attributeNameInCodapTable; + allAttrs.push(codapColumnName); + } + } else if (Array.isArray(short_desc)) { for (const desc of short_desc) { const codapColumnName = attrToCODAPColumnName[desc].attributeNameInCodapTable; allAttrs.push(codapColumnName); @@ -240,8 +245,13 @@ const getAttrData = async (params: IGetAttrDataParams) => { if (res) { const {data} = res; data.map((dataItem: any) => { - const codapColumnName = attrToCODAPColumnName[dataItem.short_desc].attributeNameInCodapTable; - return values[codapColumnName] = dataItem.Value; + let codapColumnName; + if (attribute === "Economic Class") { + codapColumnName = attrToCODAPColumnName[dataItem.domaincat_desc].attributeNameInCodapTable; + } else { + codapColumnName = attrToCODAPColumnName[dataItem.short_desc].attributeNameInCodapTable; + } + return values[codapColumnName] = dataItem.Value; }); } else { // eslint-disable-next-line no-console From a863f7bbdd884ff51e2472ef2eda22b390c0fc60 Mon Sep 17 00:00:00 2001 From: lublagg Date: Mon, 9 Oct 2023 12:47:34 -0400 Subject: [PATCH 2/2] Add support for Acres Operated. --- src/constants/codapMetadata.ts | 38 ++++++++++++++++++ src/constants/queryHeaders.ts | 4 +- src/scripts/api.ts | 71 +++++++++++++++++++++++++++++----- 3 files changed, 101 insertions(+), 12 deletions(-) diff --git a/src/constants/codapMetadata.ts b/src/constants/codapMetadata.ts index 658b122..4ed3f91 100644 --- a/src/constants/codapMetadata.ts +++ b/src/constants/codapMetadata.ts @@ -204,6 +204,34 @@ export const attrToCODAPColumnName: IAttrToCodapColumn = { "attributeNameInCodapTable": "Very Large Farm ($1 million or more)", "unitInCodapTable": "# of Farms" }, + "AREA OPERATED: (1.0 TO 9.9 ACRES)": { + "attributeNameInCodapTable": "Less than 10 Acres", + "unitInCodapTable": "# of Farms" + }, + "AREA OPERATED: (10.0 TO 49.9 ACRES)": { + "attributeNameInCodapTable": "10 - 50 Acres", + "unitInCodapTable": "# of Farms" + }, + "AREA OPERATED: (50.0 TO 100 ACRES)": { + "attributeNameInCodapTable": "50 - 100 Acres", + "unitInCodapTable": "# of Farms" + }, + "AREA OPERATED: (100 TO 500 ACRES)": { + "attributeNameInCodapTable": "100 - 500 Acres", + "unitInCodapTable": "# of Farms" + }, + "AREA OPERATED: (500 TO 999 ACRES)": { + "attributeNameInCodapTable": "500 - 1,000 Acres", + "unitInCodapTable": "# of Farms" + }, + "AREA OPERATED: (1,000 TO 5,000 ACRES)": { + "attributeNameInCodapTable": "1,000 - 5,000 Acres", + "unitInCodapTable": "# of Farms" + }, + "AREA OPERATED: (5,000 OR MORE ACRES)": { + "attributeNameInCodapTable": "5,000 Acres or More", + "unitInCodapTable": "# of Farms" + } }; export const economicClassAttirbutes = [ @@ -214,3 +242,13 @@ export const economicClassAttirbutes = [ "ECONOMIC CLASS: (500,000 TO 999,999 $)", "ECONOMIC CLASS: (1,000,000 OR MORE $)" ]; + +export const acresOperatedAttributes = [ + "AREA OPERATED: (1.0 TO 9.9 ACRES)", + "AREA OPERATED: (10.0 TO 49.9 ACRES)", + "AREA OPERATED: (50.0 TO 100 ACRES)", + "AREA OPERATED: (100 TO 500 ACRES)", + "AREA OPERATED: (500 TO 999 ACRES)", + "AREA OPERATED: (1,000 TO 5,000 ACRES)", + "AREA OPERATED: (5,000 OR MORE ACRES)" +]; diff --git a/src/constants/queryHeaders.ts b/src/constants/queryHeaders.ts index a33d426..93bfebb 100644 --- a/src/constants/queryHeaders.ts +++ b/src/constants/queryHeaders.ts @@ -145,8 +145,8 @@ export const queryData: Array = [ sect_desc: "Economics", group_desc: "Farms & Land & Assets", commodity_desc: "Farm Operations", - statisticcat_desc: "Area Operated", - short_desc: ["FARM OPERATIONS - ACRES OPERATED"], + statisticcat_desc: "Operations", + short_desc: ["FARM OPERATIONS - NUMBER OF OPERATIONS"], domain_desc: "Area Operated", geographicAreas: ["State", "County"], years: { diff --git a/src/scripts/api.ts b/src/scripts/api.ts index a2dbda1..d7fed2a 100644 --- a/src/scripts/api.ts +++ b/src/scripts/api.ts @@ -5,7 +5,7 @@ import { connect } from "./connect"; import { cropOptions, fiftyStates } from "../constants/constants"; import { countyData } from "../constants/counties"; import { flatten, getQueryParams } from "./utils"; -import { attrToCODAPColumnName, economicClassAttirbutes } from "../constants/codapMetadata"; +import { acresOperatedAttributes, attrToCODAPColumnName, economicClassAttirbutes } from "../constants/codapMetadata"; const baseURL = `https://quickstats.nass.usda.gov/api/api_GET/?key=9ED0BFB8-8DDD-3609-9940-A2341ED6A9E3`; @@ -18,6 +18,12 @@ interface IGetAttrDataParams { state?: string } +interface IAcreTotals { + [key: string]: { + [key: string]: number | null + } +} + export const fetchDataWithRetry = async (req: string, maxRetries = 3) => { let retries = 0; while (retries < maxRetries) { @@ -114,6 +120,11 @@ export const getAllAttrs = (selectedOptions: IStateOptions) => { const codapColumnName = attrToCODAPColumnName[econAttr].attributeNameInCodapTable; allAttrs.push(codapColumnName); } + } else if (attribute === "Acres Operated") { + for (const acresAttr of acresOperatedAttributes) { + const codapColumnName = attrToCODAPColumnName[acresAttr].attributeNameInCodapTable; + allAttrs.push(codapColumnName); + } } else if (Array.isArray(short_desc)) { for (const desc of short_desc) { const codapColumnName = attrToCODAPColumnName[desc].attributeNameInCodapTable; @@ -230,7 +241,6 @@ const getDataForSingleYearAndState = async (selectedOptions: IStateOptions, coun return item; }; - const getAttrData = async (params: IGetAttrDataParams) => { const {attribute, geographicLevel, location, year, cropUnits, state} = params; const reqParams: IGetAttrDataParams = {attribute, geographicLevel, location, year, state}; @@ -244,15 +254,56 @@ const getAttrData = async (params: IGetAttrDataParams) => { const values: any = {}; if (res) { const {data} = res; - data.map((dataItem: any) => { - let codapColumnName; - if (attribute === "Economic Class") { - codapColumnName = attrToCODAPColumnName[dataItem.domaincat_desc].attributeNameInCodapTable; - } else { - codapColumnName = attrToCODAPColumnName[dataItem.short_desc].attributeNameInCodapTable; + if (attribute === "Acres Operated") { + const acreTotals: IAcreTotals = { + "AREA OPERATED: (1.0 TO 9.9 ACRES)": { + "AREA OPERATED: (1.0 TO 9.9 ACRES)": 0 + }, + "AREA OPERATED: (10.0 TO 49.9 ACRES)": { + "AREA OPERATED: (10.0 TO 49.9 ACRES)": 0 + }, + "AREA OPERATED: (50.0 TO 100 ACRES)": { + "AREA OPERATED: (50.0 TO 69.9 ACRES)": 0, + "AREA OPERATED: (70.0 TO 99.9 ACRES)": 0 + }, + "AREA OPERATED: (100 TO 500 ACRES)": { + "AREA OPERATED: (100 TO 139 ACRES)": 0, + "AREA OPERATED: (140 TO 179 ACRES)": 0, + "AREA OPERATED: (180 TO 219 ACRES)": 0, + "AREA OPERATED: (220 TO 259 ACRES)": 0, + "AREA OPERATED: (260 TO 499 ACRES)": 0 + }, + "AREA OPERATED: (500 TO 999 ACRES)": { + "AREA OPERATED: (500 TO 999 ACRES)": 0 + }, + "AREA OPERATED: (1,000 TO 5,000 ACRES)": { + "AREA OPERATED: (1,000 TO 1,999 ACRES)": 0, + "AREA OPERATED: (2,000 TO 4,999 ACRES)": 0 + }, + "AREA OPERATED: (5,000 OR MORE ACRES)": { + "AREA OPERATED: (5,000 OR MORE ACRES)": 0 + } + }; + const totalKeys = Object.keys(acreTotals); + for (const total of totalKeys) { + const subTotalKeys = Object.keys(acreTotals[total]); + const dataItems = data.filter((dataItem: any) => subTotalKeys.includes(dataItem.domaincat_desc)); + dataItems.forEach((dataItem: any) => { + acreTotals[total][dataItem.domaincat_desc] = dataItem.Value.replace(/,/g, ""); + }); + const codapColumnName = attrToCODAPColumnName[total].attributeNameInCodapTable; + // sum up all the values of acreTotals[total] + const onlyNumbers = subTotalKeys.map((key) => Number(acreTotals[total][key])); + const sum = onlyNumbers.reduce((acc, cur) => acc + cur); + values[codapColumnName] = sum; } - return values[codapColumnName] = dataItem.Value; - }); + } else { + data.forEach((dataItem: any) => { + const dataItemDesc = attribute === "Economic Class" ? dataItem.domaincat_desc : dataItem.short_desc; + const codapColumnName = attrToCODAPColumnName[dataItemDesc].attributeNameInCodapTable; + values[codapColumnName] = dataItem.Value; + }); + } } else { // eslint-disable-next-line no-console console.log(`Error: did not receive response for this request:`, req);