Skip to content

Commit

Permalink
fix the hours saved modelling with simplish model, enable reading que…
Browse files Browse the repository at this point in the history
…ry params
  • Loading branch information
Darragh Curran committed May 11, 2024
1 parent 020cd94 commit c5814b1
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 14 deletions.
2 changes: 1 addition & 1 deletion roi/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ <h2>Estimated Savings</h2>
Fin will resolve approximately <span class="resolvedConversationsMonthlyOutput"></span> conversations per month.<br/>

We estimate that will save you <span class="monthlyHoursSavedEstimateOutput"></span> hours<br/>
which avoids spending <span class="monthlyLaborCostAvoidanceOutput"></span> on staffing costs,<br/>
which avoids spending <span class="monthlyLaborCostAvoidanceOutput"></span> (<span class="percentageSavings"></span>%) on staffing costs,<br/>
assuming it takes on average <span class="handlingTimeMultipleForHumanHandledOutput"></span> longer for a human to handle a conversation Fin couldn't handle vs one it does.
</p>
</div>
Expand Down
7 changes: 4 additions & 3 deletions roi/magic.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
<label for="resolutionRateInput">resolution rate of </label><span class="compositeSliderValue">40</span>%
</span></p>
<input type="hidden" id="involvementRateInput" value="100"/>
<p id="roi-output">You could save <span class="monthlyLaborCostAvoidanceOutput"></span> on staffing costs per month,
by spending <span class="monthlyFinCostsOutput"></span> on Fin</p>
<p id="roi-output">You could save <span class="monthlyLaborCostAvoidanceOutput"></span> (<span class="percentageSavings"></span>%) on staffing costs per month,
by spending <span class="monthlyFinCostsOutput"></span> on Fin. In additon to saving money your customers will be happier with near instant answers.</p>

<p id="roi-explanation" style="font-size: 50%; color: grey;">
Not all conversations require the same human effort, in practice we observe humans take <span class="handlingTimeMultipleForHumanHandledOutput"></span>x longer on the conversations Fin cannot resolve, vs those it can.
Not all conversations require the same human effort, in practice we observe humans take <span class="handlingTimeMultipleForHumanHandledOutput"></span>x longer on the conversations Fin cannot resolve, vs those it can. This is modelled into the calculations.
</p>
</div>
<a href="index.html">Form version</a>
Expand Down
10 changes: 9 additions & 1 deletion roi/roi.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@ body {

.inlineSlider input {
position: absolute;
top: -1.5em;
top: -1.3em;
left: 50%;
transform: translateX(-50%);
}

.inlineSlider input {
opacity: 0.3;
}

.inlineSlider input:hover {
opacity: 1;
}
50 changes: 41 additions & 9 deletions roi/roi.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ function calculate() {
const resolutionRate = parseFloat(document.getElementById('resolutionRateInput').value);
const involvementRate = parseFloat(document.getElementById('involvementRateInput').value);
const costPerEmployeeMonth = parseFloat(document.getElementById('averageMonthlyCostPerEmployeeInput').value);
const ratioOfFinConversationTimeVsHuman = 0.33; //todo - derive that from team size vs volume...
const ratioOfFinConversationTimeVsHuman = 0.33;
const costPerResolution = 0.99;

const resolvedConversations = conversations * (resolutionRate/100.0) * (involvementRate/100.0);
const monthlyPerAgent = conversations / teamSize
const hoursPerConversation = (40 * 4) / monthlyPerAgent ;
const timeSavings = resolvedConversations * (hoursPerConversation * ratioOfFinConversationTimeVsHuman); // assuming 0.5 hours saved per resolution

const totalEmployeeHours = teamSize * (40 * 4);
const humanWeightedResolutions = (conversations - resolvedConversations) / ratioOfFinConversationTimeVsHuman;
const timeSavings = totalEmployeeHours * (resolvedConversations/(resolvedConversations+humanWeightedResolutions));
// rough modelling - https://docs.google.com/spreadsheets/d/1QprxDyqQCCnXLw3kqP-3HiRnj9SFaXUtuvyzpHbnc8E/edit#gid=0
// really dumb model - just assumes fin handled would take a human ratioOfFinConversationTimeVsHuman amount of time vs the ones find doesn't handle

const percentageTeamSavings = 100 * (timeSavings / totalEmployeeHours);

const personMonthsSaved = timeSavings / (40 * 4);
const costSavings = costPerEmployeeMonth * personMonthsSaved;
const finCosts = resolvedConversations * costPerResolution;
const roiDollars = costSavings - finCosts;

setOutput('.teamSizeOutput', `${teamSize}`)
setOutput('.resolutionRateOutput', `${resolutionRate}%`)
Expand All @@ -27,6 +32,7 @@ function calculate() {
setOutput('.monthlyLaborCostAvoidanceOutput', `$${costSavings.toFixed(2)}`)
setOutput('.monthlyFinCostsOutput', `$${finCosts.toFixed(2)}`)
setOutput('.handlingTimeMultipleForHumanHandledOutput', `${(1.0 / ratioOfFinConversationTimeVsHuman).toFixed(0)}`)
setOutput('.percentageSavings', `${percentageTeamSavings.toFixed(1)}`)
}

function setOutput(selector, text) {
Expand All @@ -44,10 +50,6 @@ function setSliderValue(target, value) {
calculate();
}

document.querySelectorAll('input').forEach(input => {
input.addEventListener('change', calculate);
});

document.querySelectorAll('input.slider').forEach(input => {
input.addEventListener('input', function() {
var compositeSlider = this.closest('.compositeSlider');
Expand All @@ -56,5 +58,35 @@ document.querySelectorAll('input.slider').forEach(input => {
calculate();
});
});
document.querySelectorAll('input').forEach(input => {
input.addEventListener('change', calculate);
});



function getQueryParam(param) {
const params = new URLSearchParams(window.location.search);
const value = params.get(param);
// Check if the parameter is a positive integer
return (value !== null && /^\d+$/.test(value)) ? parseInt(value, 10) : null;
}

function readQueryParam(param) {
const value = getQueryParam(param);
if (value == null) return;
let input = document.getElementById(param + 'Input');
input.value = value;
const event = new Event('input', {bubbles: true, cancelable: true});
input.dispatchEvent(event);
}

function readQueryParams () {
readQueryParam('resolutionRate');
readQueryParam('conversationVolume');
readQueryParam('supportTeamSize');
readQueryParam('involvementRate');
readQueryParam('averageMonthlyCostPerEmployee');
}

readQueryParams();
calculate();

0 comments on commit c5814b1

Please sign in to comment.