chart4 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width +80, height/1.8]);
svg
.append('defs')
.append('pattern')
.attr('id', 'diagonalHatch')
.attr('patternUnits', 'userSpaceOnUse')
.attr('width', 4)
.attr('height', 4)
.append('path')
.attr('d', 'M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2')
.attr('stroke', '#ccc')
.attr('stroke-width', 0.6);
const ks = Object.keys(categories);
const totals = [0, d3.sum(categories["education"][0].map(d => test[d])), d3.sum(categories["socioeconomic"][0].map(d => test[d])),d3.sum(categories["housing"][0].map(d => test[d])),d3.sum(categories["technology"][0].map(d => test[d])), 100];
var minibar = svg.append('g').attr('transform', 'translate(0,80)').selectAll(".minibar")
.data(Object.keys(categories))
.enter();
svg.append("text")
.attr("x", 240)
.attr("y", (d, i) => 100)
.style("fill", "black")
.attr("text-anchor", "end")
.text(test.name);
minibar.append("text")
.attr("x", xmod3(100)+10)
.attr("y",20)
.style("fill", "black")
.attr("text-anchor", "start")
.text(test.score);
minibar.append("rect")
.attr("x", (d, i) => xmod3(0))
.attr("y",0)
.attr("width", (d, i) => xmod3(100) - 250)
.style("fill", 'url(#diagonalHatch)')
.attr("height", 30);
minibar.append("rect")
.attr("x", (d, i) => xmod3(d3.sum(totals.slice(0,i+1))))
.attr("width", (d, i) => d === "null" ? xmod3(100 - test.score) - 250 : xmod3(totals[i+1]) - 250)
.style("fill", d => d === "null" ? 'url(#diagonalHatch)' : colorCats(d))
.attr("height", 30)
.on("click", onTabClick);
minibar.append("text")
.attr("x", (d, i) => d === "null" ? xmod3(d3.sum(totals.slice(0,i+1))) + ((xmod3(100 - test.score) - 250)/2) : xmod3(d3.sum(totals.slice(0,i+1))) + ((xmod3(totals[i+1]) - 250)/2))
.attr("y", -10)
.style("fill", "black")
.text(d => d === "null" ? "" : categories[d][1])
.style("text-anchor", "end")
.attr("transform", function (d) {
var xRot = d3.select(this).attr("x");
var yRot = d3.select(this).attr("y");
return `rotate(35, ${xRot}, ${yRot} )` //ES6 template literal to set x and y rotation points
});
var header = svg.append('g').attr('transform', 'translate(0,120)').selectAll(".header")
.data([test])
.enter();
header.append("rect")
.attr("width", width / 4)
.attr("y", 0)
.attr("x", 80)
.attr("height", 60)
.attr("fill", colorCats(cats))
.style("stroke-dasharray", "5,5")
.style("stroke", "#ccc")
.attr("class", "header");
header.append('text')
.attr('x', 110)
.attr('y', 40)
.style("fill", "#fff")
.text(d => `Goal: ${categories[cats][1]}`);
var score = svg.append('g').attr('transform', 'translate(80,180)').selectAll(".score")
.data([test])
.enter();
score.append("rect")
.attr("width", width / 4)
.attr("y", 0)
.attr("height", 120)
.attr("fill", "#fff")
.style("stroke-dasharray", "5,5")
.style("stroke", "#ccc")
.attr("class", "header");
const other = svg.append('g').attr('transform', `translate(${(width / 4) + 80},120)`).selectAll('.other')
.data(Object.keys(categories).filter(x => x !== cats))
.enter()
other.append("rect")
.attr("width", width / 5.5)
.attr("x", 0)
.attr("y", (d, i) => i * (180/3))
.attr("height", 60)
.attr("fill", d => colorCats(d))
.style("stroke-dasharray", "5,5")
.style("stroke", "#ccc")
.attr("class", "header")
.on("click", onTabClick);
other.append('text')
.attr('x',20)
.attr('y', (d, i) => (i * (180/3)) + 30)
.attr("text-anchor", "left")
.text(d => `${categories[d][1]}`);
other.append('text')
.attr('x', (width / 5.5) - 8)
.attr('y', (d, i) => (i * (180/3)) + 30)
.attr("style", "font-size: 18px; font-weight: 700")
.attr("text-anchor", "end")
.text(d => `${d3.sum(categories[d][0].map(e => test[e]))}`);
var totalscore = svg.append('g').attr('transform', `translate(${(3 * width) / 4},120)`).selectAll(".total-score")
.data([test])
.enter()
totalscore.append("rect")
.attr("width", width / 4)
.attr("x", 0)
.attr("y", 0)
.attr("height", 180)
.attr("fill", "#fff")
.style("stroke-dasharray", "5,5")
.style("stroke", "#ccc")
.attr("class", "header");
const total = d3.sum(categories[cats][0].map(d => test[d]))
const sumlist = mod2.map(x => d3.sum(categories[cats][0].map(y => x[y])))
const max = d3.max(sumlist)
const min = d3.min(sumlist)
const avg = d3.mean(sumlist)
score.selectAll(".score-label")
.data([test])
.enter()
.append("text")
.text(d => `${total}`)
.attr('style', "font-size: 80px;")
.attr("x", width / 8)
.attr("y", 80)
.attr("text-anchor", "middle");
score.selectAll(".score-label")
.data([test])
.enter()
.append("text")
.text(`min: ${Number(min).toFixed(2)} | avg: ${Number(avg).toFixed(2)} | max: ${Number(max).toFixed(2)} `)
.attr('class', "stats")
.attr("x", width / 8)
.attr("y", 100)
.attr("text-anchor", "middle");
totalscore.selectAll(".totalscore-label-overall")
.data([test])
.enter()
.append("text")
.text("OVERALL SCORE")
.attr("x", width / 8)
.attr("y", 50)
.attr("class", "data-head")
.attr("text-anchor", "middle");
totalscore.selectAll(".totalscore-label")
.data([test])
.enter()
.append("text")
.text(d => d["score"])
.attr('style', "font-size: 80px;")
.attr("x", width / 8)
.attr("y", 120)
.attr("text-anchor", "middle");
totalscore.selectAll(".totalscore-label-city")
.data([test])
.enter()
.append("text")
.text(test["name"])
.attr("class", "data-head")
.attr("x", width / 8)
.attr("y", 160)
.attr("text-anchor", "middle");
const innerSVG = svg.append('g').attr('transform', 'translate(0,330)');
innerSVG.append('g').call(xAxisMod);
innerSVG.append('g').call(yAxisMod);
const indicatorBars = innerSVG.append('g').selectAll('g').data(categories[cats][0]).join('g');
indicatorBars.append("rect")
.attr('rx', 6)
.attr('ry', 6)
.attr("x", d => xmod(0))
.attr('y', (d, i) => ymod(d))
.attr("stroke", "#aaa")
.attr('height', 15)
.attr('width', width - margin.right - xmod(0))
.attr('fill', 'url(#diagonalHatch)');
indicatorBars.append('rect')
.attr('rx', 6)
.attr('ry', 6)
.attr("width", (d, i) => xmod(test[d]) - xmod(0))
.attr("x", d => xmod(0))
.attr('y', (d, i) => ymod(d))
.style("fill", colorCats(cats))
.attr('class', 'scoring')
.attr("height", 15);
return svg.node();
}