Skip to content

Commit

Permalink
Merge pull request #49 from ScottLogic/exclude-downstream
Browse files Browse the repository at this point in the history
Add an option to exclude downstream impacts
  • Loading branch information
mgriffin-scottlogic authored Apr 30, 2024
2 parents 3ea0100 + b87386b commit fb6e806
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 71 deletions.
1 change: 1 addition & 0 deletions docs/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ classDiagram
Cloud --> "cloudLocation" WorldLocation
Cloud --> "monthlyCloudBill" CostRange
class Downstream {
noDownstream: boolean
customerLocation: WorldLocation
monthlyActiveUsers: number
mobilePercentage: number
Expand Down
152 changes: 84 additions & 68 deletions src/app/carbon-estimator-form/carbon-estimator-form.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<input
id="estimateServerCount"
type="checkbox"
class="rounded-sm"
class="rounded-sm cursor-pointer"
formControlName="estimateServerCount"
aria-describedby="on-prem-servers-question" />
<label for="estimateServerCount" class="cursor-pointer select-none">I don't know</label>
Expand Down Expand Up @@ -81,7 +81,11 @@

<div class="flex flex-col gap-4">
<div class="flex gap-2 items-center">
<input id="noCloudServices" type="checkbox" formControlName="noCloudServices" class="rounded-sm" />
<input
id="noCloudServices"
type="checkbox"
formControlName="noCloudServices"
class="rounded-sm cursor-pointer" />
<label for="noCloudServices" class="cursor-pointer select-none">We don't use cloud services</label>
</div>

Expand Down Expand Up @@ -134,78 +138,90 @@
<div formGroupName="downstream">
<ng-container *ngTemplateOutlet="sectionHeader; context: formContext.downstream"></ng-container>
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-2">
<div class="flex">
<label for="purposeOfSite" class="text-sm text-slate-600"
>What's the primary purpose of your digital services?</label
>
<helper-info class="ml-auto" inputLabel="What's the purpose of your website">
<p class="text-sm text-slate-600">
The purpose of your digital services is used to determine the typical amount of time a user might spend on
them and the amount of data that may be transferred.
</p>
<p class="text-sm text-slate-600">
This can affect the amount of energy used by end user devices and how much energy from network traffic is
attributable to your organisation
</p>
</helper-info>
</div>
<select
class="border border-slate-400 rounded"
formControlName="purposeOfSite"
name="purposeOfSite"
id="purposeOfSite">
<option value="average" selected>Unspecified (uses average)</option>
<option value="information">Information</option>
<option value="eCommerce">E-Commerce</option>
<option value="socialMedia">Social Media</option>
<option value="streaming">Streaming</option>
</select>
<div class="flex gap-2 items-center">
<input id="noDownstream" type="checkbox" formControlName="noDownstream" class="rounded-sm cursor-pointer" />
<label for="noDownstream" class="cursor-pointer select-none"
>We don't have any external users of our digital services</label
>
</div>
<ng-container *ngTemplateOutlet="locationInput; context: formContext.downstream"></ng-container>

<div class="flex flex-col gap-2">
<label for="monthlyActiveUsers" class="text-sm text-slate-600">
How many monthly active users do your digital services have?
</label>
<input
class="border border-slate-400 rounded"
formControlName="monthlyActiveUsers"
name="monthlyActiveUsers"
type="number"
id="monthlyActiveUsers"
min="0" />
</div>
@if (!noDownstream) {
<div class="flex flex-col gap-2">
<div class="flex">
<label for="purposeOfSite" class="text-sm text-slate-600"
>What's the primary purpose of your digital services?</label
>
<helper-info class="ml-auto" inputLabel="What's the purpose of your website">
<p class="text-sm text-slate-600">
The purpose of your digital services is used to determine the typical amount of time a user might spend
on them and the amount of data that may be transferred.
</p>
<p class="text-sm text-slate-600">
This can affect the amount of energy used by end user devices and how much energy from network traffic
is attributable to your organisation
</p>
</helper-info>
</div>
<select
class="border border-slate-400 rounded"
formControlName="purposeOfSite"
name="purposeOfSite"
id="purposeOfSite">
<option value="average" selected>Unspecified (uses average)</option>
<option value="information">Information</option>
<option value="eCommerce">E-Commerce</option>
<option value="socialMedia">Social Media</option>
<option value="streaming">Streaming</option>
</select>
</div>
<ng-container *ngTemplateOutlet="locationInput; context: formContext.downstream"></ng-container>

<div class="flex flex-col gap-2">
<div class="flex">
<label for="mobilePercentage" class="text-sm text-slate-600">
What percentage of your end-users are mobile or personal computer users?
<div class="flex flex-col gap-2">
<label for="monthlyActiveUsers" class="text-sm text-slate-600">
How many monthly active users do your digital services have?
</label>
<helper-info class="ml-auto" inputLabel="What percentage of your users are mobile or personal computer users">
<p class="text-sm text-slate-600">
The percentage of mobile users will affect the energy used by end user devices and network infrastructure.
</p>
<p class="text-sm text-slate-600">
While the power demand of mobile devices is often much lower, the use of mobile networks can increase the
power used when transferring data.
</p>
</helper-info>
<input
class="border border-slate-400 rounded"
formControlName="monthlyActiveUsers"
name="monthlyActiveUsers"
type="number"
id="monthlyActiveUsers"
min="1" />
</div>
<input
id="mobilePercentage"
formControlName="mobilePercentage"
name="mobilePercentage"
type="range"
min="0"
max="100"
step="5"
[attr.aria-valuetext]="'Mobile ' + mobilePercentage + '%, Computer' + computerPercentage + '%'" />
<div class="flex justify-between text-sm text-slate-600">
<span>Mobile {{ mobilePercentage }}%</span>
<span>Computer {{ computerPercentage }}%</span>

<div class="flex flex-col gap-2">
<div class="flex">
<label for="mobilePercentage" class="text-sm text-slate-600">
What percentage of your end-users are mobile or personal computer users?
</label>
<helper-info
class="ml-auto"
inputLabel="What percentage of your users are mobile or personal computer users">
<p class="text-sm text-slate-600">
The percentage of mobile users will affect the energy used by end user devices and network
infrastructure.
</p>
<p class="text-sm text-slate-600">
While the power demand of mobile devices is often much lower, the use of mobile networks can increase
the power used when transferring data.
</p>
</helper-info>
</div>
<input
id="mobilePercentage"
formControlName="mobilePercentage"
name="mobilePercentage"
type="range"
min="0"
max="100"
step="5"
[attr.aria-valuetext]="'Mobile ' + mobilePercentage + '%, Computer' + computerPercentage + '%'" />
<div class="flex justify-between text-sm text-slate-600">
<span>Mobile {{ mobilePercentage }}%</span>
<span>Computer {{ computerPercentage }}%</span>
</div>
</div>
</div>
}
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class CarbonEstimatorFormComponent implements OnInit {
public previewServerCount = 0;

public noCloudServices: boolean = defaultValues.cloud.noCloudServices;
public noDownstream: boolean = defaultValues.downstream.noDownstream;

public locationDescriptions = locationArray.map(location => ({
value: location,
Expand Down Expand Up @@ -90,6 +91,7 @@ export class CarbonEstimatorFormComponent implements OnInit {
monthlyCloudBill: [defaultValues.cloud.monthlyCloudBill],
}),
downstream: this.formBuilder.nonNullable.group({
noDownstream: [false],
customerLocation: [defaultValues.downstream.customerLocation],
monthlyActiveUsers: [defaultValues.downstream.monthlyActiveUsers],
mobilePercentage: [defaultValues.downstream.mobilePercentage],
Expand Down Expand Up @@ -123,6 +125,10 @@ export class CarbonEstimatorFormComponent implements OnInit {
this.changeDetector.detectChanges();
});

this.estimatorForm
.get('downstream.noDownstream')
?.valueChanges.subscribe(noDownstream => (this.noDownstream = noDownstream));

this.estimatorForm.get('cloud.cloudPercentage')?.valueChanges.subscribe(cloudPercentage => {
this.cloudPercentage = cloudPercentage;
this.onPremisePercentage = 100 - this.cloudPercentage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const defaultValues: Required<EstimatorValues> = {
monthlyCloudBill: costRanges[0],
},
downstream: {
noDownstream: false,
customerLocation: 'global',
monthlyActiveUsers: 100,
mobilePercentage: 50,
Expand Down
6 changes: 4 additions & 2 deletions src/app/estimation/estimate-downstream-emissions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { sumValues } from '../utils/number-object';
import { estimateDownstreamEmissions } from './estimate-downstream-emissions';

describe('estimateDownstreamEmissions', () => {
it('should return no emissions if monthly active users is zero', () => {
it('should return no emissions if no downstream is requested', () => {
const input: Downstream = {
monthlyActiveUsers: 0,
noDownstream: true,
monthlyActiveUsers: 100,
customerLocation: 'global',
mobilePercentage: 0,
purposeOfSite: 'average',
Expand All @@ -18,6 +19,7 @@ describe('estimateDownstreamEmissions', () => {

function createInput(purposeOfSite: PurposeOfSite): Downstream {
return {
noDownstream: false,
monthlyActiveUsers: 100,
customerLocation: 'global',
mobilePercentage: 0,
Expand Down
2 changes: 1 addition & 1 deletion src/app/estimation/estimate-downstream-emissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const siteTypeInfo: Record<PurposeOfSite, SiteInformation> = addAverage({
});

export function estimateDownstreamEmissions(downstream: Downstream): DownstreamEstimation {
if (downstream.monthlyActiveUsers === 0) {
if (downstream.noDownstream) {
return { endUser: 0, networkTransfer: 0 };
}

Expand Down
1 change: 1 addition & 0 deletions src/app/services/carbon-estimation.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const emptyEstimatorValues: EstimatorValues = {
monthlyCloudBill: { min: 0, max: 200 },
},
downstream: {
noDownstream: true,
customerLocation: 'global',
monthlyActiveUsers: 0,
mobilePercentage: 0,
Expand Down
2 changes: 2 additions & 0 deletions src/app/types/carbon-estimator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export type EstimatorFormValues = {
monthlyCloudBill: FormControl<CostRange>;
}>;
downstream: FormGroup<{
noDownstream: FormControl<boolean>;
customerLocation: FormControl<WorldLocation>;
monthlyActiveUsers: FormControl<number>;
mobilePercentage: FormControl<number>;
Expand All @@ -77,6 +78,7 @@ export type Cloud = {
monthlyCloudBill: CostRange;
};
export type Downstream = {
noDownstream: boolean;
customerLocation: WorldLocation;
monthlyActiveUsers: number;
mobilePercentage: number;
Expand Down

0 comments on commit fb6e806

Please sign in to comment.