Init
This commit is contained in:
commit
8b72c9df74
124
index.html
Normal file
124
index.html
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name=""viewport" content=""width=device-width, initial-scale="1.0">
|
||||||
|
<title>Calculator</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Calculator</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
|
||||||
|
<form action="/action_page.php">
|
||||||
|
<div class="flex-container">
|
||||||
|
<div class="flex-1">
|
||||||
|
<h2>Policy Details</h2>
|
||||||
|
<label for="effectiveDate">Effective date:</label>
|
||||||
|
<input type="date" id="effectiveDate" name="effectiveDate" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
<label for="expiryDate">Expiry date:</label>
|
||||||
|
<input type="date" id="expiryDate" name="expiryDate" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Days in policy term: <span id="termDays">-</span>
|
||||||
|
<br><br>
|
||||||
|
<label for="cancelDate">Cancellation date</label>
|
||||||
|
<input type="date" id="cancelDate" name="cancelDate" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Days in force: <span id="forceDays">-</span>
|
||||||
|
<br>
|
||||||
|
Days remaining: <span id="remainingDays">-</span>
|
||||||
|
<br><br>
|
||||||
|
Factor method:
|
||||||
|
<input type="radio" name="calcMethod" id="calcProRata" value="Pro Rata" onclick="calculator();" /> Pro Rata
|
||||||
|
<input type="radio" name="calcMethod" id="calcShortRate" value="Short Rate" onclick="calculator();"/> Short Rate
|
||||||
|
<br><br>
|
||||||
|
Earned factor: <span id="earnedFactor">-</span>
|
||||||
|
<br>
|
||||||
|
Unearned factor: <span id="unearnedFactor">-</span>
|
||||||
|
<br><br>
|
||||||
|
<label for="totalPremium">Total premium:</label>
|
||||||
|
<input type="number" id="totalPremium" name="totalPremium" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedPremium">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedPremium">-</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-2">
|
||||||
|
<h2>Breakdown</h2>
|
||||||
|
<p><span id="checkMatch">Total breakdown: N/A</span></p>
|
||||||
|
|
||||||
|
<label for="breakDO">D&O:</label>
|
||||||
|
<input type="number" id="breakDO" name="breakDO" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedDO">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedDO">-</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="breakEO">E&O:</label>
|
||||||
|
<input type="number" id="breakEO" name="breakEO" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedEO">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedEO">-</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="breakCyber">Cyber:</label>
|
||||||
|
<input type="number" id="breakCyber" name="breakCyber" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedCyber">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedCyber">-</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="breakLEI">Legal Expense:</label>
|
||||||
|
<input type="number" id="breakLEI" name="breakLEI" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedLEI">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedLEI">-</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="breakCGL">CGL:</label>
|
||||||
|
<input type="number" id="breakCGL" name="breakCGL" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedCGL">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedCGL">-</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="breakProperty">Property:</label>
|
||||||
|
<input type="number" id="breakProperty" name="breakProperty" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedProperty">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedProperty">-</span>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<label for="breakEB">Equipment Breakdown::</label>
|
||||||
|
<input type="number" id="breakEB" name="breakEB" onblur="calculator()" min="0" oninput="validity.valid||(value='')">
|
||||||
|
<br>
|
||||||
|
Earned premium: <span id="earnedEB">-</span>
|
||||||
|
<br>
|
||||||
|
Return premium: <span id="unearnedEB">-</span>
|
||||||
|
<br><br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<button onclick="calculator()">Calculate</button>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Created by <a href="https://haothitran.com">Hao Tran</a>.</p>
|
||||||
|
<p>Note: Calculations are rounded to the nearest tenth decimal. As such, there may sometimes be issues of rounding error.</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
<script src="scripts/calculator.js"></script>
|
||||||
|
</html>
|
114
scripts/calculator.js
Normal file
114
scripts/calculator.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
function calculator() {
|
||||||
|
// pull from input fields
|
||||||
|
var effectiveDate = document.getElementById("effectiveDate").value;
|
||||||
|
var expiryDate = document.getElementById("expiryDate").value;
|
||||||
|
var cancelDate = document.getElementById("cancelDate").value;
|
||||||
|
var totalPremium = document.getElementById("totalPremium").value;
|
||||||
|
var breakDO = document.getElementById("breakDO").value || 0;
|
||||||
|
var breakEO = document.getElementById("breakEO").value || 0;
|
||||||
|
var breakCyber = document.getElementById("breakCyber").value || 0;
|
||||||
|
var breakLEI = document.getElementById("breakLEI").value || 0;
|
||||||
|
var breakCGL = document.getElementById("breakCGL").value || 0;
|
||||||
|
var breakProperty = document.getElementById("breakProperty").value || 0;
|
||||||
|
var breakEB = document.getElementById("breakEB").value || 0;
|
||||||
|
|
||||||
|
// calculate dates in policy term
|
||||||
|
var policyDays = new Date(expiryDate).getTime() - new Date(effectiveDate).getTime();
|
||||||
|
var termDays = policyDays / (1000 * 60 * 60 * 24);
|
||||||
|
|
||||||
|
// calculate dates involved with cancellation
|
||||||
|
var cancelDays = new Date(cancelDate).getTime() - new Date(effectiveDate).getTime();
|
||||||
|
var forceDays = cancelDays / (1000 * 60 * 60 * 24);
|
||||||
|
var remainingDays = termDays - forceDays;
|
||||||
|
|
||||||
|
// calculate pro rata
|
||||||
|
if(document.getElementById('calcProRata').checked) {
|
||||||
|
var earnedFactor = Math.round(((forceDays / termDays) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedFactor = Math.round(((remainingDays / termDays) + Number.EPSILON)*1000)/1000;
|
||||||
|
// calculate short rate
|
||||||
|
}else if(document.getElementById('calcShortRate').checked) {
|
||||||
|
var earnedFactor = Math.round(((1 - ((remainingDays / termDays ) * 0.9)) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedFactor = Math.round((((remainingDays / termDays) * 0.9) + Number.EPSILON)*1000)/1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate premiums
|
||||||
|
var earnedPremium = Math.round(((totalPremium * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedPremium = Math.round(((totalPremium * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
|
||||||
|
// calculate breakdown
|
||||||
|
var calcBreak = +breakDO + +breakEO + +breakCyber + +breakLEI + +breakCGL + +breakProperty + +breakEB;
|
||||||
|
// check if breakdown matches total premium
|
||||||
|
var calcMatch = calcBreak-totalPremium;
|
||||||
|
if(totalPremium<calcBreak) {
|
||||||
|
var checkMatch = "Total breakdown is too high by " + calcMatch + ".";
|
||||||
|
document.getElementById("checkMatch").className = 'red';
|
||||||
|
var calculateBreakdown = false;
|
||||||
|
}else if(totalPremium>calcBreak) {
|
||||||
|
var checkMatch = "Total breakdown is too low by " + calcMatch + ".";
|
||||||
|
document.getElementById("checkMatch").className = 'red';
|
||||||
|
var calculateBreakdown = false;
|
||||||
|
}else {
|
||||||
|
var checkMatch = "Total breakdown matches total premium! Success!";
|
||||||
|
document.getElementById("checkMatch").className = 'green';
|
||||||
|
var calculateBreakdown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate breakdowns
|
||||||
|
if(calculateBreakdown == true) {
|
||||||
|
var earnedDO = Math.round(((breakDO * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedDO = Math.round(((breakDO * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var earnedEO = Math.round(((breakEO * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedEO = Math.round(((breakEO * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var earnedCyber = Math.round(((breakCyber * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedCyber = Math.round(((breakCyber * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var earnedLEI = Math.round(((breakLEI * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedLEI = Math.round(((breakLEI * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var earnedCGL = Math.round(((breakCGL * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedCGL = Math.round(((breakCGL * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var earnedProperty = Math.round(((breakProperty * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedProperty = Math.round(((breakProperty * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var earnedEB = Math.round(((breakEB * earnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
var unearnedEB = Math.round(((breakEB * unearnedFactor) + Number.EPSILON)*1000)/1000;
|
||||||
|
}else {
|
||||||
|
var earnedDO = 'ERROR'
|
||||||
|
var unearnedDO = 'ERROR'
|
||||||
|
var earnedEO = 'ERROR'
|
||||||
|
var unearnedEO = 'ERROR'
|
||||||
|
var earnedCyber = 'ERROR'
|
||||||
|
var unearnedCyber = 'ERROR'
|
||||||
|
var earnedLEI = 'ERROR'
|
||||||
|
var unearnedLEI = 'ERROR'
|
||||||
|
var earnedCGL = 'ERROR'
|
||||||
|
var unearnedCGL = 'ERROR'
|
||||||
|
var earnedProperty = 'ERROR'
|
||||||
|
var unearnedProperty = 'ERROR'
|
||||||
|
var earnedEB = 'ERROR'
|
||||||
|
var unearnedEB = 'ERROR'
|
||||||
|
}
|
||||||
|
|
||||||
|
// display policy terms
|
||||||
|
document.getElementById("termDays").innerHTML = termDays;
|
||||||
|
document.getElementById("forceDays").innerHTML = forceDays;
|
||||||
|
document.getElementById("remainingDays").innerHTML = remainingDays;
|
||||||
|
document.getElementById("earnedFactor").innerHTML = earnedFactor;
|
||||||
|
document.getElementById("unearnedFactor").innerHTML = unearnedFactor;
|
||||||
|
document.getElementById("earnedPremium").innerHTML = earnedPremium;
|
||||||
|
document.getElementById("unearnedPremium").innerHTML = unearnedPremium;
|
||||||
|
// display breakdown
|
||||||
|
document.getElementById("checkMatch").innerHTML = checkMatch;
|
||||||
|
document.getElementById("earnedDO").innerHTML = earnedDO;
|
||||||
|
document.getElementById("unearnedDO").innerHTML = unearnedDO;
|
||||||
|
document.getElementById("earnedEO").innerHTML = earnedEO;
|
||||||
|
document.getElementById("unearnedEO").innerHTML = unearnedEO;
|
||||||
|
document.getElementById("earnedCyber").innerHTML = earnedCyber;
|
||||||
|
document.getElementById("unearnedCyber").innerHTML = unearnedCyber;
|
||||||
|
document.getElementById("earnedLEI").innerHTML = earnedLEI;
|
||||||
|
document.getElementById("unearnedLEI").innerHTML = unearnedLEI;
|
||||||
|
document.getElementById("earnedCGL").innerHTML = earnedCGL;
|
||||||
|
document.getElementById("unearnedCGL").innerHTML = unearnedCGL;
|
||||||
|
document.getElementById("earnedProperty").innerHTML = earnedProperty;
|
||||||
|
document.getElementById("unearnedProperty").innerHTML = unearnedProperty;
|
||||||
|
document.getElementById("earnedEB").innerHTML = earnedEB;
|
||||||
|
document.getElementById("unearnedEB").innerHTML = unearnedEB;
|
||||||
|
}
|
||||||
|
doSomething
|
76
style.css
Normal file
76
style.css
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
:root {
|
||||||
|
--width: 900px;
|
||||||
|
--font-family: Verdana, sans-serif;
|
||||||
|
--font-scale: 1em;
|
||||||
|
--bg-100: #100F0F;
|
||||||
|
--bg-200: #1C1B1A;
|
||||||
|
--ui-100: #292726;
|
||||||
|
--ui-200: #343331;
|
||||||
|
--ui-300: #403E3C;
|
||||||
|
--text-100: #CECDC3;
|
||||||
|
|
||||||
|
|
||||||
|
--cyan-400: #3AA99F;
|
||||||
|
--green-400: #879A39;
|
||||||
|
--red-400: #D14D41;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 16px;
|
||||||
|
max-width: var(--width);
|
||||||
|
background-color: var(--bg-100);
|
||||||
|
font-family: var(--font-family);
|
||||||
|
font-size: var(--font-scale);
|
||||||
|
color: var(--text-100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.green { color: var(--green-400); }
|
||||||
|
.red { color: var(--red-400); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding: 10px;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid var(--ui-300);
|
||||||
|
background-color: var(--green-400);
|
||||||
|
color: var(--text-100);
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
border: 1px solid var(--ui-300);
|
||||||
|
background-color: var(--ui-100);
|
||||||
|
color: var(--text-100);
|
||||||
|
}
|
||||||
|
input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--cyan-400);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header {
|
||||||
|
margin-top: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
margin: 4rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
column-gap: 1rem;
|
||||||
|
}
|
||||||
|
.flex-1 {
|
||||||
|
order: 1;
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-2 {
|
||||||
|
order: 2;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user