Last active
September 8, 2018 22:52
-
-
Save Kritner/fadc18ea0eff5e0e70f2ee75098e01f9 to your computer and use it in GitHub Desktop.
Medium blog post - solar projection, adding form - Form typescript model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class SolarProjectionFormModel { | |
constructor( | |
public yearsToProject: number, | |
public utilitySolarArrayKwhYear: number, | |
public solarCostPerMonth: number, | |
public solarFinanceYears: number, | |
public utilityCostFullYear: number, | |
public utilityPercentIncreasePerYear: number | |
) { } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h1>Solar Projection</h1> | |
<div class="container"> | |
<!-- form inputs solar projection--> | |
<div> | |
<form *ngIf="!isExpandedForm" (ngSubmit)="onSubmit()" #projectionForm="ngForm"> | |
<div class="form-group"> | |
<label for="yearsToProject">Years to project</label> | |
<input type="number" class="form-control" id="yearsToProject" name="yearsToProject" required [(ngModel)]="model.yearsToProject" | |
/> | |
</div> | |
<div class="form-group"> | |
<label for="utilitySolarArrayKwhYear">Utility/Solar Array kw/year</label> | |
<input type="number" class="form-control" id="utilitySolarArrayKwhYear" name="utilitySolarArrayKwhYear" required [(ngModel)]="model.utilitySolarArrayKwhYear" | |
/> | |
</div> | |
<div class="form-group"> | |
<label for="solarCostPerMonth">Solar Array cost/month</label> | |
<input type="number" class="form-control" id="solarCostPerMonth" name="solarCostPerMonth" required [(ngModel)]="model.solarCostPerMonth" | |
/> | |
</div> | |
<div class="form-group"> | |
<label for="solarFinanceYears">Solar Finance Years</label> | |
<input type="number" class="form-control" id="solarFinanceYears" name="solarFinanceYears" required [(ngModel)]="model.solarFinanceYears" | |
/> | |
</div> | |
<div class="form-group"> | |
<label for="utilityCostFullYear">Utility Cost Full Year</label> | |
<input type="number" class="form-control" id="utilityCostFullYear" name="utilityCostFullYear" required [(ngModel)]="model.utilityCostFullYear" | |
/> | |
</div> | |
<div class="form-group"> | |
<label for="utilityPercentIncreasePerYear">Utility Cost % Increase/year</label> | |
<input type="number" class="form-control" id="utilityPercentIncreasePerYear" name="utilityPercentIncreasePerYear" required | |
[(ngModel)]="model.utilityPercentIncreasePerYear" /> | |
</div> | |
<button type="submit" class="btn btn-success" [disabled]="!projectionForm.form.valid"> | |
Submit | |
</button> | |
</form> | |
<button type="button" class="btn" (click)="toggleFormInput()"> | |
Projection Criteria | |
<span class="glyphicon" [ngClass]="{ | |
'glyphicon-chevron-down': isExpandedForm, | |
'glyphicon-chevron-up': !isExpandedForm | |
}"></span> | |
</button> | |
</div> | |
<!-- Solar projection--> | |
<div> | |
<p *ngIf="!solarProjection"><em>Loading...</em></p> | |
<div *ngIf="solarProjection"> | |
<h4>Solar Estimate (Guaranteed for 90% of total Kw/year Production)</h4> | |
<ul> | |
<li>Solar Cost/year: {{ solarProjection.solarEstimate.totalCost | currency }}</li> | |
<li>Solar Cost/month: {{ solarProjection.solarEstimate.averageCostPerMonth | currency }}</li> | |
<li>Total Kw/h/year: {{ solarProjection.solarEstimate.totalKiloWattHours | number }}</li> | |
<li>Solar Cost kw/h {{ solarProjection.solarEstimate.averageCostKiloWattHour | currency }}</li> | |
<li>Total Years Financed: {{ solarProjection.financeYears }} </li> | |
</ul> | |
<table class='table'> | |
<thead> | |
<tr> | |
<th>Year</th> | |
<th>Total Cost Utility</th> | |
<th>Avg. Cost/month (Utility)</th> | |
<th>Cost/year 100% gen.</th> | |
<th>Savings/year 100% gen.</th> | |
<th>Cost/year 90% gen.</th> | |
<th>Savings/year 90% gen.</th> | |
<th>Cost/year 80% gen.</th> | |
<th>Savings/year 80% gen.</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr *ngFor="let projection of solarProjection.futureProjection"> | |
<td>{{ projection.purchaseYear | indexOffset }}</td> | |
<td>{{ projection.totalCost | currency }}</td> | |
<td>{{ projection.averageCostPerMonth | currency }}</td> | |
<td>{{ projection.costSolar100Percent | currency }}</td> | |
<td [ngClass]="{ | |
positive: inTheGreen(projection.totalSavings100Percent), | |
negative: !inTheGreen(projection.totalSavings100Percent) | |
}">{{ projection.totalSavings100Percent | currency }}</td> | |
<td>{{ projection.costSolar90Percent | currency }}</td> | |
<td [ngClass]="{ | |
positive: inTheGreen(projection.totalSavings90Percent), | |
negative: !inTheGreen(projection.totalSavings90Percent) | |
}">{{ projection.totalSavings90Percent | currency }}</td> | |
<td>{{ projection.costSolar80Percent | currency }}</td> | |
<td [ngClass]="{ | |
positive: inTheGreen(projection.totalSavings80Percent), | |
negative: !inTheGreen(projection.totalSavings80Percent) | |
}">{{ projection.totalSavings80Percent | currency }}</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, OnInit, Inject } from '@angular/core'; | |
import { HttpHeaders, HttpParams } from '@angular/common/http'; | |
import { HttpClient } from '@angular/common/http'; | |
import { SolarProjectionFormModel } from './solar-projection-form-model'; | |
@Component({ | |
selector: 'app-solar-projection', | |
templateUrl: './solar-projection.component.html', | |
styleUrls: ['./solar-projection.component.css'] | |
}) | |
export class SolarProjectionComponent implements OnInit { | |
private http: HttpClient; | |
private baseUrl: string; | |
isExpandedForm: boolean = true; | |
solarProjection: SolarProjection; | |
model: SolarProjectionFormModel = | |
new SolarProjectionFormModel( | |
25, | |
17000, | |
180, | |
20, | |
2240, | |
.03 | |
); | |
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) { | |
this.http = http; | |
this.baseUrl = baseUrl; | |
} | |
ngOnInit() { | |
this.getProjection(); | |
} | |
getProjection() { | |
let headers = new HttpHeaders({ | |
'Accept': 'application/json', | |
'Content-Type': 'application/json' | |
}); | |
let params = new HttpParams() | |
.set("param", JSON.stringify(this.model)); | |
this.http.get<SolarProjection>( | |
this.baseUrl + 'api/SolarProjection', | |
{ | |
headers: headers, | |
params: params | |
} | |
) | |
.subscribe( | |
result => { | |
this.solarProjection = result; | |
}, | |
error => { | |
console.error(error) | |
} | |
); | |
} | |
inTheGreen(value: number): boolean { | |
if (value >= 0) { | |
return true; | |
} | |
return false; | |
} | |
toggleFormInput() { | |
this.isExpandedForm = !this.isExpandedForm; | |
} | |
onSubmit() { | |
this.toggleFormInput(); | |
this.getProjection(); | |
} | |
} | |
interface SolarProjection { | |
solarEstimate: YearlyElectricityUsage; | |
futureProjection: FutureProjection[]; | |
financeYears: number; | |
} | |
interface YearlyElectricityUsage { | |
averageCostKiloWattHour: number; | |
averageCostPerMonth: number; | |
totalCost: number; | |
totalKiloWattHours: number; | |
} | |
interface FutureProjection { | |
solarEstimate: YearlyElectricityUsage; | |
purchaseYear: number; | |
averageCostKiloWattHour: number; | |
averageCostPerMonth: number; | |
totalCost: number; | |
totalKiloWattHours: number; | |
costSolar100Percent: number; | |
totalSavings100Percent: number; | |
costSolar90Percent: number; | |
totalSavings90Percent: number; | |
costSolar80Percent: number; | |
totalSavings80Percent: number; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Route("api/[controller]")] | |
[ApiController] | |
public class SolarProjectionController : ControllerBase | |
{ | |
private readonly IProjectFutureEnergyCostService _service; | |
public SolarProjectionController(IProjectFutureEnergyCostService service) | |
{ | |
_service = service; | |
} | |
[HttpGet("[action]")] | |
public SolarVsUtilityProjection GetProjection() | |
{ | |
return _service.CalculateFutureProjection( | |
ElectricityDataHelper.GetUsageWithPanelsMortgageAnnual(), | |
new ProjectionParameters( | |
ElectricityDataHelper.GetUsageUtility2017FromAnnual(), | |
25, | |
20, | |
.03 | |
) | |
); | |
} | |
/// <summary> | |
/// Get solar projection with a json | |
/// string representing <see cref="SolarProjectionParameters"/>. | |
/// | |
/// TODO there's gotta be a better way to do this signature, | |
/// both from a param and return perspective. I feel like | |
/// parameter should convey the proper type, and the result | |
/// should be able to convey a status perhaps? | |
/// </summary> | |
/// <param name="param">Json representation of <see cref="SolarProjectionParameters"/></param> | |
/// <returns><see cref="SolarVsUtilityProjection"/></returns> | |
[HttpGet] | |
public SolarVsUtilityProjection Get(string param) | |
{ | |
// Convert json string to type | |
var solarProjectionParameters = JsonConvert | |
.DeserializeObject<SolarProjectionParameters>(param); | |
// Calculate future projection | |
return _service.CalculateFutureProjection( | |
solarEstimate: new YearlyKwhUsageFromAnnual( | |
totalCost: solarProjectionParameters.SolarCostPerMonth * 12, | |
totalKiloWattHours: solarProjectionParameters.UtilitySolarArrayKwhYear | |
), | |
projectionParameters: new ProjectionParameters( | |
utilityYear: new YearlyKwhUsageFromAnnual( | |
totalCost: solarProjectionParameters.UtilityCostFullYear, | |
totalKiloWattHours: solarProjectionParameters.UtilitySolarArrayKwhYear | |
), | |
yearsToProject: solarProjectionParameters.YearsToProject, | |
financeYears: solarProjectionParameters.SolarFinanceYears, | |
percentIncreasePerYear: solarProjectionParameters.UtilityPercentIncreasePerYear | |
) | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Parameters for creating a solar projection | |
/// </summary> | |
public class SolarProjectionParameters | |
{ | |
/// <summary> | |
/// The number of years to project | |
/// </summary> | |
public int YearsToProject { get; set; } | |
/// <summary> | |
/// The total kw/h year used (will make solar projection with the | |
/// assumption the array can theoretically cover 100% of energy needs) | |
/// </summary> | |
public int UtilitySolarArrayKwhYear { get; set; } | |
/// <summary> | |
/// The cost per month of the solar financing | |
/// </summary> | |
public double SolarCostPerMonth { get; set; } | |
/// <summary> | |
/// The number of years the solar panels are financed | |
/// </summary> | |
public int SolarFinanceYears { get; set; } | |
/// <summary> | |
/// The total cost of a utility year | |
/// </summary> | |
public double UtilityCostFullYear { get; set; } | |
/// <summary> | |
/// The percentage increase of utility costs per year | |
/// </summary> | |
public double UtilityPercentIncreasePerYear { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment