Skip to content

Instantly share code, notes, and snippets.

@mforando
Last active October 18, 2018 20:45
Show Gist options
  • Save mforando/f4a92bc5dda9c6ff8b39362858ebae04 to your computer and use it in GitHub Desktop.
Save mforando/f4a92bc5dda9c6ff8b39362858ebae04 to your computer and use it in GitHub Desktop.
Insurance Plan Benefit Design Terminology NOSWOOP
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
#terminologyCont{
display:inline-block;
}
#coinsurance, #copay, #deductible{
width:400px;
display:inline-block;
margin:20px;
vertical-align:top;
}
.termP{
width:100%;
height:280px;
padding-left:20px;
padding-right:20px;
vertical-align:top;
font-family:Franklin Gothic Book;
}
.termHeader{
width:100%;
padding-left:20px;
padding-right:20px;
margin-top:5px;
vertical-align:top;
color:rgb(0,130,101);
font-family:Franklin Gothic Medium;
}
</style>
</head>
<div id="terminologyCont">
<div id="coinsurance">
<h1 class="termHeader">Coinsurance</h1>
<p class="termP">The percentage of costs of a covered health care service you pay (20%, for example) after you've paid your deductible.
Let's say your health insurance plan's allowed amount for an office visit is $100 and your coinsurance is 20%.
If you've paid your deductible: You pay 20% of $100, or $20. The insurance company pays the rest.
If you haven't met your deductible: You pay the full allowed amount, $100.
Generally speaking, plans with low monthly premiums have higher coinsurance, and plans with higher monthly premiums have lower coinsurance.
</p>
<svg></svg>
<h1 class="termHeader">Your Plan Options</h1>
</div>
<div id="copay">
<h1 class="termHeader">Copayments</h1>
<p class="termP">A fixed amount ($20, for example) you pay for a covered health care service after you've paid your deductible.
Let's say your health insurance plan's allowable cost for a doctor's office visit is $100. Your copayment for a doctor visit is $20.
If you've paid your deductible: You pay $20, usually at the time of the visit.
If you haven't met your deductible: You pay $100, the full allowable amount for the visit.
Copayments (sometimes called "copays") can vary for different services within the same plan, like drugs, lab tests, and visits to specialists.
Generally plans with lower monthly premiums have higher copayments. Plans with higher monthly premiums usually have lower copayments.
</p>
<svg></svg>
<h1 class="termHeader">Your Plan Options</h1>
</div>
<div id="deductible">
<h1 class="termHeader">Deductible(s)</h1>
<p class="termP">The amount you pay for covered health care services before your insurance plan starts to pay. With a $2,000 deductible, for example, you pay the first $2,000 of covered services yourself.
After you pay your deductible, you usually pay only a copayment or coinsurance for covered services. Your insurance company pays the rest.
Many plans pay for certain services, like a checkup or disease management programs, before you've met your deductible. Check your plan details.
All Marketplace health plans pay the full cost of certain preventive benefits even before you meet your deductible.
Some plans have separate deductibles for certain services, like prescription drugs.
Family plans often have both an individual deductible, which applies to each person, and a family deductible, which applies to all family members.
Generally, plans with lower monthly premiums have higher deductibles. Plans with higher monthly premiums usually have lower deductibles.
</p>
<svg></svg>
<h1 class="termHeader">Your Plan Options</h1>
</div>
</div>
<body>
<script>
var coinsData = [{"Charges":100,"Coinsurance":0.1,"Coins":10,"Covered":90,"Label":"10%"}
,{"Charges":100,"Coinsurance":0.2,"Coins":20,"Covered":80,"Label":"20%"}
,{"Charges":100,"Coinsurance":0.3,"Coins":30,"Covered":70,"Label":"30%"}
,{"Charges":100,"Coinsurance":0.4,"Coins":40,"Covered":60,"Label":"40%"}
]
var copayData = [{"Charges":100,"Copay":30,"Label":"Inpatient"}
,{"Charges":60,"Copay":30,"Label":"Inpatient "}
,{"Charges":100,"Copay":10,"Label":"Outpatient"}
,{"Charges":60,"Copay":10,"Label":"Outpatient "}]
var deductData = [{"ID":1,"Charges":100,"Cumulative":0,"CumulativePlus":100,"Flag":true}
,{"ID":2,"Charges":100,"Cumulative":100,"CumulativePlus":200,"Flag":true}
,{"ID":3,"Charges":50,"Cumulative":200,"CumulativePlus":250,"Flag":true}
,{"ID":3,"Charges":30,"Cumulative":250,"CumulativePlus":280,"Flag":false}
,{"ID":4,"Charges":80,"Cumulative":280,"CumulativePlus":360,"Flag":false}
]
var coinsWidth = 250;
var coinsHeight = 250;
var coinsMargin = 80;
create_coins_SVG()
create_copay_SVG()
create_deduct_SVG()
function create_deduct_SVG(){
var scaleBand_coins = d3.scaleBand().range([0,coinsWidth])
.domain(deductData.map(function(d){return d.ID}))
.paddingOuter(.1)
.paddingInner(.2)
var scaleY_coins = d3.scaleLinear().range([coinsHeight,0])
.domain([0,360])
var coinssvg = d3.select("#deductible").select("svg")
.attr("width", coinsWidth + coinsMargin*2)
.attr("height", coinsHeight + coinsMargin*2)
.style("margin","15px")
.style("border-bottom","1px solid rgba(0,0,0,.25)")
.append('g')
.attr("transform","translate("+coinsMargin + "," + coinsMargin + ")")
var defs = coinssvg.append("svg:defs")
coinssvg.append("svg:defs").append("svg:marker")
.attr("id", "arrow")
.attr("refX", 5)
.attr("refY", 5)
.attr("markerWidth", 30)
.attr("markerHeight", 30)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0 0 10 5 0 10 5")
.style("fill", "rgb(196,18,48)")
var coinsRects = coinssvg.selectAll(".fullbars").data(deductData)
coinsRects.enter()
.append("rect")
.attr("class","fullbars")
.attr("x",function(d,i){return scaleBand_coins(d.ID)})
.attr("y",function(d,i){return scaleY_coins(d.CumulativePlus)})
.attr("width",scaleBand_coins.bandwidth() + "px")
.attr("height",function(d,i){return scaleY_coins(d.Cumulative)-scaleY_coins(d.CumulativePlus)})
.style("fill","rgba(200,200,200,.75)")
.style("fill",function(d){
if(d.Flag){return "rgb(196,18,48)"}
else{return "rgba(200,200,200,.75)"}
})
.style("stroke","white")
.style("stroke-width","2px")
coinssvg.append("line")
.style("stroke","rgb(0,62,126)")
.style("stroke-dasharray",4)
.style("stroke-width","2px")
.attr("y1",scaleY_coins(250))
.attr("y2",scaleY_coins(250))
.attr("x1",0)
.attr("x2",coinsWidth)
coinssvg.append("g")
.attr("transform","translate(0," + coinsHeight + ")")
.call(d3.axisBottom(scaleBand_coins))
.selectAll("text")
.style("font-family","Franklin Gothic Book")
.style("font-size","15px")
.attr("dy",18)
coinssvg.append("g")
.attr("transform","translate(" + coinsWidth/2 + "," + (coinsHeight + 60) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Medium")
.style("font-size","22px")
.text("Claim Sequence")
var exposurelabel = coinssvg.append("g")
.attr("transform","translate(" + coinsWidth*.3 + "," + (0) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Medium")
.style("font-size","22px")
.style("fill","rgb(196,18,48)")
.text("Your Exposure")
var bounds = exposurelabel.node().getBoundingClientRect()
var swoopCoords = []
//push left most point, midpoint and end point to an array.
//push left most point, midpoint and end point to an array.
swoopCoords.push({"i":0,"x":(coinsWidth*.2),"y":10,"x1":scaleBand_coins(1) + scaleBand_coins.bandwidth()/2,"y1":scaleY_coins(deductData[0].CumulativePlus)-10})
swoopCoords.push({"i":1,"x":(coinsWidth*.4)+bounds.width/2 - bounds.width*2/3,"y":10,"x1":scaleBand_coins(2) + scaleBand_coins.bandwidth()/2,"y1":scaleY_coins(deductData[1].CumulativePlus)-10})
swoopCoords.push({"i":2,"x":(coinsWidth*.4+bounds.width/2 - bounds.width*1/3),"y":10,"x1":scaleBand_coins(3) + scaleBand_coins.bandwidth()/2,"y1":scaleY_coins(deductData[2].CumulativePlus)-10})
var rootSVG = d3.select(coinssvg.parentNode)
var swoopyArrows = coinssvg.selectAll(".swoop").data(swoopCoords)
swoopyArrows.enter()
.append("path")
.attr("class","swoop")
.attr("d",function(d,i){
var sweepFlag = 0
if(i==2){sweepFlag = 1}
//M start-x, start-y A radius-x, radius-y, x-rotat, lrge-arc-flag, sweep-flag,end-x, end-y
var pathStr = "M " + d.x + ", " + d.y + " C " + ((d.x1)) +" " + ((d.y + d.y1)/2) + ", " + ((d.x1)) + " " + ((d.y + d.y1)*1/3) + ", " + d.x1 + ", " + d.y1 + ", " + d.y1
return pathStr
})
.style("fill","none")
.style('stroke',"rgb(196,18,48)")
.attr("marker-end","url(#arrow)")
}
function create_copay_SVG(){
var scaleBand_coins = d3.scaleBand().range([0,coinsWidth])
.domain(copayData.map(function(d){return d.Label}))
.paddingOuter(.1)
.paddingInner(.2)
var scaleY_coins = d3.scaleLinear().range([coinsHeight,0])
.domain([0,100])
var coinssvg = d3.select("#copay").select("svg")
.attr("width", coinsWidth + coinsMargin*2)
.attr("height", coinsHeight + coinsMargin*2)
.style("margin","15px")
.style("border-bottom","1px solid rgba(0,0,0,.25)")
.append('g')
.attr("transform","translate("+coinsMargin + "," + coinsMargin + ")")
var defs = coinssvg.append("svg:defs")
coinssvg.append("svg:defs").append("svg:marker")
.attr("id", "arrow")
.attr("refX", 5)
.attr("refY", 5)
.attr("markerWidth", 30)
.attr("markerHeight", 30)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0 0 10 5 0 10 5")
.style("fill", "rgb(196,18,48)")
var coinsRects = coinssvg.selectAll(".fullbars").data(copayData)
coinsRects.enter()
.append("rect")
.attr("class","fullbars")
.attr("x",function(d,i){return scaleBand_coins(d.Label)})
.attr("y",function(d,i){return scaleY_coins(d.Charges)})
.attr("width",scaleBand_coins.bandwidth() + "px")
.attr("height",function(d,i){return scaleY_coins(0)-scaleY_coins(d.Charges)})
.style("fill","rgba(200,200,200,.75)")
.style("stroke","white")
.style("stroke-width","2px")
var coinsRects_employee = coinssvg.selectAll(".employeebars").data(copayData)
coinsRects_employee.enter()
.append("rect")
.attr("class","employeebars")
.attr("x",function(d,i){return scaleBand_coins(d.Label)})
.attr("y",function(d,i){return scaleY_coins(d.Charges)})
.attr("width",scaleBand_coins.bandwidth() + "px")
.attr("height",function(d,i){return scaleY_coins(d.Charges-d.Copay)-scaleY_coins(d.Charges)})
.style("fill","rgb(196,18,48)")
.style("stroke","white")
.style("stroke-width","2px")
var copaytext = coinssvg.selectAll(".copaytext").data(copayData)
copaytext.enter()
.append("text")
.attr("class","copaytext")
.attr("x",function(d,i){return scaleBand_coins(d.Label)+scaleBand_coins.bandwidth()/2})
.attr("y",function(d,i){return scaleY_coins(d.Charges-d.Copay/2)})
.text(function(d){return "$" + d.Copay})
.style("font-family","Franklin Gothic Medium")
.style("fill","white")
.style("text-anchor","middle")
.style("dominant-baseline","middle")
coinssvg.append("polyline")
.attr("points",function(){
return (scaleBand_coins("Inpatient") + scaleBand_coins.bandwidth()/2) +
"," + coinsHeight +
"," + (scaleBand_coins("Inpatient") + scaleBand_coins.bandwidth()/2) +
"," + (coinsHeight + 10) +
"," + (scaleBand_coins("Inpatient ") + scaleBand_coins.bandwidth()/2) +
"," + (coinsHeight + 10) +
"," + (scaleBand_coins("Inpatient ") + scaleBand_coins.bandwidth()/2) +
"," + coinsHeight})
.style("stroke","black")
.style("fill","none")
coinssvg.append("polyline")
.attr("points",function(){
return (scaleBand_coins("Outpatient") + scaleBand_coins.bandwidth()/2) +
"," + coinsHeight +
"," + (scaleBand_coins("Outpatient") + scaleBand_coins.bandwidth()/2) +
"," + (coinsHeight + 10) +
"," + (scaleBand_coins("Outpatient ") + scaleBand_coins.bandwidth()/2) +
"," + (coinsHeight + 10) +
"," + (scaleBand_coins("Outpatient ") + scaleBand_coins.bandwidth()/2) +
"," + coinsHeight})
.style("stroke","black")
.style("fill","none")
coinssvg.append("g")
.attr("transform","translate(" + (scaleBand_coins("Inpatient") + scaleBand_coins("Inpatient ")/2 + scaleBand_coins.bandwidth()/2) + "," + (coinsHeight + 28) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Book")
.style("font-size","15px")
.text("Inpatient")
coinssvg.append("g")
.attr("transform","translate(" + ((scaleBand_coins("Outpatient") + scaleBand_coins("Outpatient "))/2 + scaleBand_coins.bandwidth()/2) + "," + (coinsHeight + 28) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Book")
.style("font-size","15px")
.text("Outpatient")
coinssvg.append("g")
.attr("transform","translate(" + coinsWidth/2 + "," + (coinsHeight + 60) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Medium")
.style("font-size","22px")
.text("Type of Service")
var exposurelabel = coinssvg.append("g")
.attr("transform","translate(" + coinsWidth/2 + "," + (-60) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Medium")
.style("font-size","22px")
.style("fill","rgb(196,18,48)")
.text("Your Exposure")
var bounds = exposurelabel.node().getBoundingClientRect()
var swoopCoords = []
//push left most point, midpoint and end point to an array.
swoopCoords.push({"i":0,"x":(coinsWidth/2-bounds.width/2),"y":-50,"x1":scaleBand_coins("Inpatient") + scaleBand_coins.bandwidth()/2,"y1":scaleY_coins(copayData[0].Charges)-10})
swoopCoords.push({"i":1,"x":(coinsWidth/2-bounds.width/2+bounds.width*1/3),"y":-50,"x1":scaleBand_coins("Inpatient ") + scaleBand_coins.bandwidth()/2,"y1":scaleY_coins(copayData[1].Charges)-10})
swoopCoords.push({"i":2,"x":(coinsWidth/2-bounds.width/2+bounds.width*2/3),"y":-50,"x1":scaleBand_coins("Outpatient") + scaleBand_coins.bandwidth()/2,"y1":scaleY_coins(copayData[2].Charges)-10})
swoopCoords.push({"i":3,"x":(coinsWidth/2-bounds.width/2+bounds.width),"y":-50,"x1":scaleBand_coins("Outpatient ") + scaleBand_coins.bandwidth()/2,"y1":scaleY_coins(copayData[3].Charges)-10})
console.log(swoopCoords,scaleY_coins(copayData[0].Charges))
var rootSVG = d3.select(coinssvg.parentNode)
var swoopyArrows = coinssvg.selectAll(".swoop").data(swoopCoords)
swoopyArrows.enter()
.append("path")
.attr("class","swoop")
.attr("d",function(d,i){
var sweepFlag = 0
if(i==2){sweepFlag = 1}
//M start-x, start-y A radius-x, radius-y, x-rotat, lrge-arc-flag, sweep-flag,end-x, end-y
var pathStr = "M " + d.x + ", " + d.y + " A " + (0) +", " + (-5) + ", " + 90 + ", " + 0 + ", " + sweepFlag + ", " + d.x1 + ", " + d.y1
//use bezier instead of an arc!
var pathStr = "M " + d.x + ", " + d.y + " C " + ((d.x1)) +" " + ((d.y + d.y1)/2) + ", " + ((d.x1)) + " " + ((d.y + d.y1)*1/3) + ", " + d.x1 + ", " + d.y1 + ", " + d.y1
return pathStr
})
.style("fill","none")
.style('stroke',"rgb(196,18,48)")
.attr("marker-end","url(#arrow)")
}
function create_coins_SVG(){
var scaleBand_coins = d3.scaleBand().range([0,coinsWidth])
.domain(coinsData.map(function(d){return d.Label}))
.paddingOuter(.1)
.paddingInner(.2)
var scaleY_coins = d3.scaleLinear().range([coinsHeight,0])
.domain([0,100])
var coinssvg = d3.select("#coinsurance").select("svg")
.attr("width", coinsWidth + coinsMargin*2)
.attr("height", coinsHeight + coinsMargin*2)
.style("margin","15px")
.style("border-bottom","1px solid rgba(0,0,0,.25)")
.append('g')
.attr("transform","translate("+coinsMargin + "," + coinsMargin + ")")
var defs = coinssvg.append("svg:defs")
coinssvg.append("svg:defs").append("svg:marker")
.attr("id", "arrow")
.attr("refX", 5)
.attr("refY", 5)
.attr("markerWidth", 30)
.attr("markerHeight", 30)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0 0 10 5 0 10 5")
.style("fill", "rgb(196,18,48)")
var coinsRects = coinssvg.selectAll(".fullbars").data(coinsData)
coinsRects.enter()
.append("rect")
.attr("class","fullbars")
.attr("x",function(d,i){return scaleBand_coins(d.Label)})
.attr("y",function(d,i){return scaleY_coins(d.Charges)})
.attr("width",scaleBand_coins.bandwidth() + "px")
.attr("height",function(d,i){return scaleY_coins(0)-scaleY_coins(d.Charges)})
.style("fill","rgba(200,200,200,.75)")
.style("stroke","white")
.style("stroke-width","2px")
var coinsRects_employee = coinssvg.selectAll(".employeebars").data(coinsData)
coinsRects_employee.enter()
.append("rect")
.attr("class","employeebars")
.attr("x",function(d,i){return scaleBand_coins(d.Label)})
.attr("y",function(d,i){return scaleY_coins(d.Charges)})
.attr("width",scaleBand_coins.bandwidth() + "px")
.attr("height",function(d,i){return scaleY_coins(d.Charges-d.Coins)-scaleY_coins(d.Charges)})
.style("fill","rgb(196,18,48)")
.style("stroke","white")
.style("stroke-width","2px")
coinssvg.append("g")
.attr("transform","translate(0," + coinsHeight + ")")
.call(d3.axisBottom(scaleBand_coins))
.selectAll("text")
.style("font-family","Franklin Gothic Book")
.style("font-size","15px")
.attr("dy",18)
coinssvg.append("g")
.attr("transform","translate(" + coinsWidth/2 + "," + (coinsHeight + 60) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Medium")
.style("font-size","22px")
.text("Coinsurance Rate")
var exposurelabel = coinssvg.append("g")
.attr("transform","translate(" + coinsWidth/2 + "," + (-60) + ")")
.append("text")
.style("text-anchor","middle")
.style("font-family","Franklin Gothic Medium")
.style("font-size","22px")
.style("fill","rgb(196,18,48)")
.text("Your Exposure")
var bounds = exposurelabel.node().getBoundingClientRect()
var swoopCoords = []
//push left most point, midpoint and end point to an array.
swoopCoords.push({"i":0,"x":(coinsWidth/2-bounds.width/2),"y":-50,"x1":scaleBand_coins("10%") + scaleBand_coins.bandwidth()/2,"y1":-15})
swoopCoords.push({"i":1,"x":(coinsWidth/2)+bounds.width/2 - bounds.width*2/3,"y":-50,"x1":scaleBand_coins("20%") + scaleBand_coins.bandwidth()/2,"y1":-15})
swoopCoords.push({"i":2,"x":(coinsWidth/2+bounds.width/2 - bounds.width*1/3),"y":-50,"x1":scaleBand_coins("30%") + scaleBand_coins.bandwidth()/2,"y1":-15})
swoopCoords.push({"i":3,"x":(coinsWidth/2+bounds.width/2),"y":-50,"x1":scaleBand_coins("40%") + scaleBand_coins.bandwidth()/2,"y1":-15})
var rootSVG = d3.select(coinssvg.parentNode)
var swoopyArrows = coinssvg.selectAll(".swoop").data(swoopCoords)
swoopyArrows.enter()
.append("path")
.attr("class","swoop")
.attr("d",function(d,i){
var sweepFlag = 0
if(i==2){sweepFlag = 1}
//M start-x, start-y A radius-x, radius-y, x-rotat, lrge-arc-flag, sweep-flag,end-x, end-y
var pathStr = "M " + d.x + ", " + d.y + " C " + ((d.x1)) +" " + ((d.y + d.y1)/2) + ", " + ((d.x1)) + " " + ((d.y + d.y1)*1/3) + ", " + d.x1 + ", " + d.y1 + ", " + d.y1
return pathStr
})
.style("fill","none")
.style('stroke',"rgb(196,18,48)")
.attr("marker-end","url(#arrow)")
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment