chart = {
const width = 900;
const height = 800;
const centerX = width / 2;
const centerY = height / 2;
const baseRadius = 1;
const outerRadius = 400;
const maxDayLengthMinutes = 1440;
function timeToRadius(timeString) {
const [hours, minutes, seconds] = timeString.split(':').map(Number);
const totalMinutes = hours * 60 + minutes + (seconds || 0) / 60;
const radiusRange = outerRadius - baseRadius;
return baseRadius + (totalMinutes / maxDayLengthMinutes) * radiusRange;
}
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
svg.append("circle")
.attr("cx", centerX)
.attr("cy", centerY)
.attr("r", outerRadius)
.attr("fill", "none")
.attr("stroke", "red")
const totalDays = data_original.length;
const gapAngle = 0.03;
const totalGaps = 12 * gapAngle;
const availableAngle = 2 * Math.PI - totalGaps;
function calculateAngle(dayData) {
const daysPassed = dayData.dayOfYear - 1;
const daysProportion = daysPassed / totalDays;
const baseAngle = daysProportion * availableAngle;
const monthGaps = dayData.month * gapAngle;
return baseAngle + monthGaps - Math.PI / 2;
}
function drawDayLines(data) {
svg.selectAll(".day-line")
.data(data)
.enter()
.append("line")
.attr("class", "day-line")
.each(function(d) {
const angle = calculateAngle(d);
const dayLengthMinutes = calculateDayLength(d.sunrise, d.sunset);
const lengthRatio = dayLengthMinutes / maxDayLengthMinutes;
const innerRadius = outerRadius * (1 - lengthRatio);
const x1 = centerX + outerRadius * Math.cos(angle);
const y1 = centerY + outerRadius * Math.sin(angle);
const x2 = centerX + innerRadius * Math.cos(angle);
const y2 = centerY + innerRadius * Math.sin(angle);
d3.select(this)
.attr("x1", x1)
.attr("y1", y1)
.attr("x2", x2)
.attr("y2", y2)
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("opacity", 0.8);
});
}
data_original.forEach(d => {
const date = new Date(d.date);
d.dayOfYear = Math.floor((date - new Date(date.getFullYear(), 0, 1)) / (24 * 60 * 60 * 1000)) + 1;
d.month = date.getMonth();
});
drawDayLines(data_original, 'sunrise', 'sunset');
return svg.node()
}