Skip to content

Commit

Permalink
Merge pull request #94 from vkoves/generate-historic-data
Browse files Browse the repository at this point in the history
Generate Historic Data, Showing In Simple Table
  • Loading branch information
vkoves authored May 8, 2024
2 parents cc4aebd + ee31e35 commit 9b53c30
Show file tree
Hide file tree
Showing 10 changed files with 19,461 additions and 1,318 deletions.
32 changes: 29 additions & 3 deletions gridsome.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const parse = require('csv-parse/sync').parse;
const DataDirectory = './src/data/dist/';

const BuildingEmissionsDataFile = 'building-benchmarks.csv';
const HistoricBenchmarkingDataFile = 'benchmarking-all-years.csv';

// This is an array equivalent of Object.keys(BuildingOwners) but this file can't use Typescript and
// import that file
Expand All @@ -34,6 +35,7 @@ module.exports = function(api) {
// Use the Data Store API here: https://gridsome.org/docs/data-store-api/
api.loadSource(async (actions) => {
loadBuildingBenchmarkData(actions);
loadHistoricBenchmarkDat(actions);
});

// Use the Pages API here: https://gridsome.org/docs/pages-api/
Expand All @@ -56,19 +58,19 @@ module.exports = function(api) {
* @param {unknown} actions The actions class?
*/
function loadBuildingBenchmarkData(actions) {
const input = readFileSync(`${DataDirectory}${BuildingEmissionsDataFile}`, 'utf8');
const latestBenchmarksRaw = readFileSync(`${DataDirectory}${BuildingEmissionsDataFile}`, 'utf8');

/**
* Load in building benchmarks and expose as Buildings collection
*/
const BuildingsData = parse(input, {
const LatestBenchmarksData = parse(latestBenchmarksRaw, {
columns: true,
skip_empty_lines: true,
});

const collection = actions.addCollection({typeName: 'Building'});

for (const building of BuildingsData) {
for (const building of LatestBenchmarksData) {
// Make a slugSource that is the property name or the address as a fallback (skip one letter
// names, e.g. '-)
building.slugSource = building.PropertyName.length > 1 ? building.PropertyName : building.Address;
Expand All @@ -80,3 +82,27 @@ function loadBuildingBenchmarkData(actions) {
collection.addNode(building);
}
}


/**
* Load in the historic benchmark data
*
* @param {unknown} actions The actions class?
*/
function loadHistoricBenchmarkDat(actions) {
const historicBenchmarksRaw = readFileSync(`${DataDirectory}${HistoricBenchmarkingDataFile}`, 'utf8');

/**
* Load in building benchmarks and expose as Buildings collection
*/
const HistoricBenchmarksData = parse(historicBenchmarksRaw, {
columns: true,
skip_empty_lines: true,
});

const collection = actions.addCollection({ typeName: 'Benchmark' });

for (const benchmark of HistoricBenchmarksData) {
collection.addNode(benchmark);
}
}
13 changes: 13 additions & 0 deletions src/common-functions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ export interface IBuilding {
/** How GraphQL passes back a building */
export interface IBuildingNode { node: IBuilding }
export interface IHistoricData {
ID: string;
DataYear: string;
GrossFloorArea: string;
ChicagoEnergyRating: string;
ENERGYSTARScore: string;
SourceEUI: string;
ElectricityUse: string;
GHGIntensity: string;
NaturalGasUse: string;
DistrictSteamUse: string;
}
/**
* A constant for what we use as min and max values for flagged ranks
*/
Expand Down
4 changes: 2 additions & 2 deletions src/components/BuildingsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default class BuildingsTable extends Vue {
</script>

<template>
<div class="table-cont">
<div class="buildings-table-cont">
<table :class="{ '-wide': showSquareFootage || showGasUse || showElectricityUse }">
<thead>
<tr>
Expand Down Expand Up @@ -196,7 +196,7 @@ export default class BuildingsTable extends Vue {
<style lang="scss">
// Make the whole table scroll in a constrained container so we can have a sticky header - CSS makes
// that impossible otherwise
.table-cont {
.buildings-table-cont {
width: 100%;
max-height: 80vh;
overflow: auto;
Expand Down
169 changes: 169 additions & 0 deletions src/components/HistoricalBuildingDataTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<template>
<div class="historical-table-cont">
<table class="historical-data">
<thead>
<tr>
<th scope="col">
Year
</th>
<th
v-if="renderedColumns.includes('GrossFloorArea')"
scope="col"
>
Floor Area <span class="unit">sqft</span>
</th>
<th
v-if="renderedColumns.includes('ChicagoEnergyRating')"
scope="col"
>
Chicago Energy<br> Rating
</th>
<th
v-if="renderedColumns.includes('ENERGYSTARScore')"
scope="col"
>
Energy Star<br> Score
</th>
<th scope="col">
GHG Intensity <span class="unit">kg CO<sub>2</sub>e / sqft</span>
</th>
<th scope="col">
Source EUI <span class="unit">kBtu / sqft</span>
</th>

<th scope="col">
Electricity Use <span class="unit">kBtu</span>
</th>
<th scope="col">
Natural Gas Use <span class="unit">kBtu</span>
</th>
<th
v-if="renderedColumns.includes('DistrictSteamUse')"
scope="col"
>
District Steam Use <span class="unit">kBtu</span>
</th>
</tr>
</thead>
<tbody>
<tr
v-for="benchmark in historicBenchmarks"
:key="benchmark.DataYear"
>
<td>{{ benchmark.DataYear }}</td>
<td v-if="renderedColumns.includes('GrossFloorArea')">
{{ benchmark.GrossFloorArea | optionalInt }}
</td>
<td v-if="renderedColumns.includes('ChicagoEnergyRating')">
{{ benchmark.ChicagoEnergyRating || '-' }}
</td>
<td v-if="renderedColumns.includes('ENERGYSTARScore')">
{{ benchmark.ENERGYSTARScore || '-' }}
</td>
<td>{{ benchmark.GHGIntensity }}</td>
<td>{{ benchmark.SourceEUI }}</td>

<!-- Round big numbers -->
<td>{{ benchmark.ElectricityUse | optionalInt }}</td>
<td>{{ benchmark.NaturalGasUse | optionalInt }}</td>
<td v-if="renderedColumns.includes('DistrictSteamUse')">
{{ benchmark.DistrictSteamUse | optionalInt }}
</td>
</tr>
</tbody>
</table>
</div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import {IHistoricData} from '../common-functions.vue';
/**
* A component that given an array of a building's benchmarking renders
* a table showing columns of data with values (skipping any columns that
* never had a value, like if a building never had an Energy star score)
*/
@Component({
filters: {
/**
* Round and process an optional float to a locale string
*
* Ex: null -> '-', '12345.67' -> '12,345'
*/
optionalInt(value: string) {
if (!value) {
return '-';
}
return parseInt(value).toLocaleString();
},
},
})
export default class BuildingImage extends Vue {
@Prop({required: true}) historicBenchmarks!: Array<IHistoricData>;
renderedColumns: Array<string> = [];
getRenderedColumns(): Array<string> {
if (this.historicBenchmarks.length === 0) {
return [];
}
const allColKeys: Array<string> = Object.keys(this.historicBenchmarks[0]);
const emptyColKeys = allColKeys.filter((colKey: string) => {
// A column is empty if it's all empty string or '0', so skip it if so. Some columns switch
// between both, like Natural Gas Use on Merch Mart, which we also want to ignore
return !this.historicBenchmarks.every((datum) => {
return (datum as any)[colKey] === '' || (datum as any)[colKey] === '0.0';
});
});
return emptyColKeys;
}
created(): void {
this.renderedColumns = this.getRenderedColumns();
}
}
</script>

<style lang="scss">
.historical-table-cont {
max-width: 100%;
overflow-x: auto;
margin-top: 0.5rem;
margin-bottom: 1rem;
}
table.historical-data {
border: solid 0.125rem $grey;
border-radius: $brd-rad-small;
border-collapse: collapse;
width: 100%;
min-width: 62.5rem; // 1000px
.unit {
display: block;
font-size: 0.75rem;
font-weight: normal;
}
th, td {
padding: 0.5rem 0.75rem;
text-align: left;
}
thead {
tr { background-color: $grey; }
th {
line-height: 1.25;
font-size: 0.825rem;
}
}
tbody tr:nth-of-type(even) { background-color: $grey-light; }
}
</style>
2 changes: 0 additions & 2 deletions src/components/StatTile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,6 @@ export default class StatTile extends Vue {
const statStdDeviation = this.stats[this.statKey]?.std;
const statMean = this.stats[this.statKey]?.mean;
console.log({ key: this.statKey, statStdDeviation, statMean });
if (this.building[this.statKey] === null || !statStdDeviation) {
return false;
}
Expand Down
Loading

0 comments on commit 9b53c30

Please sign in to comment.