Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cfb 230 #244

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions heat-stack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ npm install
npm run buildpy # to build rules engine into `public/pyodide-env`
npm run dev
```
After you run the build for python. you'll just need to make sure the newest rules-engine wheel is in the JS context.
All we need to do is run `node ./other/utils/update-pyodide-lock.js`

After you run the build for python. you'll just need to make sure the newest rules-engine wheel is in the JS context.
All we need to do is run `node ./other/utils/update-pyodide-lock.js`

### Set up in a new GitHub CodingSpace:

Expand Down
54 changes: 8 additions & 46 deletions heat-stack/app/routes/_heat+/single.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import GeocodeUtil from '#app/utils/GeocodeUtil'
import WeatherUtil from '#app/utils/WeatherUtil'


import PyodideUtil from '#app/utils/pyodide.util'

Check warning on line 17 in heat-stack/app/routes/_heat+/single.tsx

View workflow job for this annotation

GitHub Actions / ⬣ Heat-Stack - ESLint

`#app/utils/pyodide.util` import should occur before import of `#app/utils/WeatherUtil`

// TODO NEXT WEEK
// - [x] Server side error checking/handling
Expand Down Expand Up @@ -112,17 +112,6 @@
console.error('submission failed', submission)
}
return submission.reply()
// submission.reply({
// // You can also pass additional error to the `reply` method
// formErrors: ['Submission failed'],
// fieldErrors: {
// address: ['Address is invalid'],
// },

// // or avoid sending the the field value back to client by specifying the field names
// hideFields: ['password'],
// }),
// {status: submission.status === "error" ? 400 : 200}
}

const {
Expand All @@ -147,27 +136,16 @@

console.log('loading geocodeUtil/weatherUtil')

const pyodideUtil: PyodideUtil = PyodideUtil.getInstance();
const geocodeUtil = new GeocodeUtil()
const weatherUtil = new WeatherUtil()
////////////////////////
const getPyodide = async () => {
return await pyodideModule.loadPyodide({
// This path is actually `public/pyodide-env`, but the browser knows where `public` is. Note that remix server needs `public/`
// TODO: figure out how to determine if we're in browser or remix server and use ternary.
indexURL: 'public/pyodide-env/',
})
}
const runPythonScript = async () => {
const pyodide: any = await getPyodide()
return pyodide
}
// consider running https://github.com/codeforboston/home-energy-analysis-tool/blob/main/rules-engine/tests/test_rules_engine/test_engine.py
const pyodide: any = await runPythonScript()
//////////////////////
const pyodide = await pyodideUtil.getPyodideModule();
const pyHelpers = await pyodideUtil.getHelpersModule();
// wirte comment that pyhelpers is not beign used yet. but will be.
// pyHelpers.get_design_temp();

let {coordinates, state_id, county_id} = await geocodeUtil.getLL(address)
let { coordinates, state_id, county_id } = await geocodeUtil.getLL(address)
let {x, y} = coordinates ?? {x: 0, y: 0};

console.log('geocoded', x, y)

// CSV entrypoint parse_gas_bill(data: str, company: NaturalGasCompany)
Expand All @@ -190,10 +168,6 @@

// console.log('parsedAndValidatedFormSchema', parsedAndValidatedFormSchema)

await pyodide.loadPackage(
'public/pyodide-env/pydantic_core-2.14.5-cp311-cp311-emscripten_3_1_32_wasm32.whl',
)

/* NOTES for pydantic, typing-extensions, annotated_types:
pyodide should match pyodide-core somewhat.
typing-extensions needs specific version per https://github.com/pyodide/pyodide/issues/4234#issuecomment-1771735148
Expand All @@ -202,19 +176,6 @@
- https://pypi.org/project/typing-extensions/
- https://pypi.org/project/annotated-types/#files
*/
await pyodide.loadPackage(
'public/pyodide-env/pydantic-2.5.2-py3-none-any.whl',
)
await pyodide.loadPackage(
'public/pyodide-env/typing_extensions-4.8.0-py3-none-any.whl',
)
await pyodide.loadPackage(
'public/pyodide-env/annotated_types-0.5.0-py3-none-any.whl',
)

await pyodide.loadPackage(
'public/pyodide-env/rules_engine-0.0.1-py3-none-any.whl',
)

// console.log("uploadedTextFile", uploadedTextFile)

Expand Down Expand Up @@ -322,6 +283,7 @@
# We will just pass in this data
naturalGasInputRecords = parser.parse_gas_bill(csvDataJs, parser.NaturalGasCompany.NATIONAL_GRID)

# can replace this with pyHelpers! boom!! what whaaat!!!
design_temp_looked_up = helpers.get_design_temp(state_id, county_id)
summaryInput = SummaryInput( **summaryInputFromJs, design_temperature=design_temp_looked_up)

Expand Down
130 changes: 63 additions & 67 deletions heat-stack/app/utils/GeocodeUtil.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const BASE_URL = 'https://geocoding.geo.census.gov'
const ADDRESS_ENDPOINT = '/geocoder/geographies/onelineaddress'
const LAYERS_COUNTY = 82;

// example: https://geocoding.geo.census.gov/geocoder/geographies/onelineaddress?address=1%20broadway%2C%20cambridge%2C%20ma%2002142&benchmark=4&vintage=4&format=json
interface CensusGeocoderResponse {
Expand All @@ -26,54 +27,53 @@ interface CensusGeocoderResponse {
}

interface AddressMatch {
tigerLine: {
side: string
tigerLineId: string
}
geographies: {
'State Legislative Districts - Upper': Geography[]
States: Geography[]
'Combined Statistical Areas': Geography[]
'2020 Urban Areas - Corrected': Geography[]
'County Subdivisions': Geography[]
'State Legislative Districts - Lower': Geography[]
'Incorporated Places': Geography[]
Counties: Geography[]
'116th Congressional Districts': Geography[]
'Census Tracts': Geography[]
'Census Blocks': Geography[]
}
coordinates: {
x: number
y: number
}
addressComponents: {
zip: string
streetName: string
preType: string
city: string
preDirection: string
suffixDirection: string
fromAddress: string
state: string
suffixType: string
toAddress: string
suffixQualifier: string
preQualifier: string
}
matchedAddress: string
tigerLine: {
side: string
tigerLineId: string
}
geographies: {
Counties: Geography[]
}
coordinates: {
x: number
y: number
}
addressComponents: {
zip: string
streetName: string
preType: string
city: string
preDirection: string
suffixDirection: string
fromAddress: string
state: string
suffixType: string
toAddress: string
suffixQualifier: string
preQualifier: string
}
matchedAddress: string
}

interface Geography {
GEOID: string
CENTLAT: string
AREAWATER: number
STATE: string
BASENAME: string
OID: string
LSADC: string
[key: string]: string | number /* a bit dubious catchall by the
LLM for all the semi-optional keys */
GEOID: string
CENTLAT: string
AREAWATER: number
STATE: string
BASENAME: string
OID: string
LSADC: string
FUNCSTAT: string;
INTPTLAT: string;
NAME: string;
OBJECTID: number;
CENTLON: string;
COUNTYCC: string;
COUNTYNS: string;
AREALAND: number;
INTPTLON: string;
MTFCC: string;
COUNTY: string;
}

class GeocodeUtil {
Expand All @@ -86,29 +86,25 @@ class GeocodeUtil {
async getLL(address: string) {
const params = new URLSearchParams()

params.append('address', address)
params.append('format', 'json')
params.append('benchmark', '2020')
params.append('vintage', 'Census2020_Census2020')
params.append('address', address)
params.append('format', 'json')
params.append('benchmark', '2020')
params.append('vintage', 'Census2020_Census2020')
params.append('layers',[LAYERS_COUNTY].toString()); // Right now we only care aboot the 'Counties' obj in the census return. Providing no layers param gives us a lotta data that we don't need.

/** TODO: note that for this Census API you can specify particular parts of this that
we want (x, y, state_id, and county_id for now), read the docs */
let url = new URL(BASE_URL + ADDRESS_ENDPOINT + '?' + params.toString())
let rezzy = await fetch(url)
let jrez = (await rezzy.json()) as CensusGeocoderResponse
// TODO: Return all addresses and let the user choose the right one
let coordz = jrez?.result?.addressMatches?.[0]?.coordinates
// console.log(JSON.stringify(jrez, null, 2));
return {
coordinates: coordz,
state_id:
jrez?.result?.addressMatches?.[0]?.geographies.Counties?.[0]?.['STATE'],
county_id:
jrez?.result?.addressMatches?.[0]?.geographies?.Counties?.[0]?.[
'COUNTY'
],
}
}
let url = new URL(BASE_URL + ADDRESS_ENDPOINT + '?' + params.toString())
let rezzy = await fetch(url)
let jrez = (await rezzy.json()) as CensusGeocoderResponse
// TODO: Return all addresses and let the user choose the right one
let coordz = jrez?.result?.addressMatches[0]?.coordinates
// console.log(JSON.stringify(jrez, null, 2));
return {
coordinates: coordz,
state_id: jrez.result?.addressMatches[0]?.geographies.Counties[0]?.STATE,
county_id:
jrez.result.addressMatches[0]?.geographies.Counties[0]?.COUNTY,
}
}
}

export default GeocodeUtil
Loading
Loading