{
const stadium = svg`<svg viewBox="0 0 ${config.width} ${config.height}" class="chart">
<path id="track" style="stroke: cyan; fill: none; stroke-width: 10" />
<g id="car_legend" transform="translate(600, 500)" fill="steelblue" style="font-size: ${config.font_size}px">
<circle r="${config.circle_r}"></circle>
<text x="${config.circle_r + 8}" alignment-baseline="middle">car</text>
</g>
<g id="shadow_legend" transform="translate(600, 600)" fill="gray" style="font-size: ${config.font_size}px">
<circle r="${config.circle_r}"></circle>
<text x="${config.circle_r + 8}" alignment-baseline="middle">sound amplitude on distance ${config.wave_distance_base}m</text>
<line x1="${config.circle_r + 316}" y1="${config.circle_r + 10}" x2="${config.circle_r + 316}" y2="${config.circle_r + 30}" style="stroke: gray; stroke-width: 6"></line>
<line x1="${config.circle_r + 316 + config.wave_distance_base}" y1="${config.circle_r + 10}" x2="${config.circle_r + 316 + config.wave_distance_base}" y2="${config.circle_r + 30}" style="stroke: gray; stroke-width: 6"></line>
<line x1="${config.circle_r + 316}" y1="${config.circle_r + 20}" x2="${config.circle_r + 316 + config.wave_distance_base}" y2="${config.circle_r + 20}" style="stroke: gray; stroke-width: 6"></line>
</g>
<g id="person" transform="translate(${config.person_x}, ${config.person_y})" style="font-size: ${config.font_size}px">
<circle r="${config.circle_r}" fill="firebrick"></circle>
<text y="${config.circle_r * 3}" fill="firebrick" style="text-anchor: middle">person</text>
</g>
</svg>`;
const corners = config.corners;
const draw = () => {
const path = d3.path();
path.moveTo(corners.left, corners.top);
path.arc(corners.left, corners.center_y, config.radius, Math.PI * 3 / 2, Math.PI / 2, true);
path.lineTo(corners.right, corners.bottom);
path.arc(corners.right, corners.center_y, config.radius, Math.PI / 2, Math.PI * 3 / 2, true);
path.lineTo(corners.left, corners.top);
return path;
};
const track = d3.select(stadium).select("#track");
track.attr("d", draw());
const shadow_position = prepare_shadow_position(config.rev_time, config.sampling_rate);
const max_sample = Math.ceil(config.rev_time * config.sampling_rate);
for (let t = 0; t < config.rev_time; t+=4) {
const car_xy = drive(config.base_x, config.base_y, t);
const car = d3.select(stadium).append("g")
.style("text-anchor", "middle")
.style("font-size", config.font_size + "px")
.attr("fill", "steelblue")
.attr("transform", `translate(${car_xy[0]}, ${car_xy[1]})`);
car.append("circle")
.attr("r", config.circle_r);
car.append("text")
.attr("y", config.circle_r * 3)
.text(`${t}s`);
const shadow_xy = shadow_position[t * config.sampling_rate];
const d = Math.max(dd(shadow_xy[0], shadow_xy[1]), 1);
const ratio = config.wave_distance_base / d;
const shadow = d3.select(stadium).append("g")
.style("text-anchor", "middle")
.style("font-size", config.font_size + "px")
.attr("fill", "gray")
.attr("transform", `translate(${shadow_xy[0]}, ${shadow_xy[1]})`);
shadow.append("circle")
.attr("r", ratio * config.wave_radius_base);
shadow.append("text")
.attr("y", -2 * config.circle_r)
.text(`${t}s`);
}
return stadium;
}