<commit_before>/**
json data format
{"STATION":{"LONGITUDE":116.587,"LATITUDE":40.074,"ELEVATION":55,"NAME":"Beijing","CODE":"ZBAA"},
"DATA": [[minTemperature], [maxTemperature], [Precipitation], [DatetimeValue]]}

Quantity Metric:
minTemperature: \[Degree]C
maxTemperature: \[Degree]C
Precipitation: cm
DatetimeValue: YYYYMMDD
*/
const api = `Shanghai.json`,
  margin = 20,
  WIDTH = Math.min(window.innerWidth, 1.3 * window.innerHeight) - margin,
  HEIGHT = window.innerHeight - margin,
  LOWEST = -40,
  HIGHEST = 60,
  maxPRCPRadius = WIDTH / 16;
const ANIMATION = {
  durationPerDay: 7.5 // unit: ms
};
const svg = d3.select("svg").attr("width", WIDTH).attr("height", HEIGHT);
// remove body unresolved when WIDTH and HEIGHT is setup
d3.select("#app").attr("unresolved", null);

const viewport = svg
  .append("g")
  .attr("class", "viewport")
  .attr("transform", "translate(" + WIDTH / 2 + "," + HEIGHT / 2 + ")");
const rScale = d3
  .scaleLinear()
  .domain([LOWEST, HIGHEST])
  .range([0, HEIGHT / 2 - margin]);
const yScale = (day, temp) =>
  -Math.cos(angleScale(day) * Math.PI / 180) * rScale(parseInt(temp));
const xScale = (day, temp) =>
  Math.sin(angleScale(day) * Math.PI / 180) * rScale(parseInt(temp));
const angleScale = d3.scaleLinear().range([0, 360]);
const prcpScale = d3.scaleLinear().range([0, maxPRCPRadius]);

const generateRadialGradient = selection => {
  const gradientControl = [
    {
      offset: "0%",
      stopColor: "rgb(0,24,35)"
    },
    {
      offset: "15%",
      stopColor: "rgb(0,59,93)"
    },
    {
      offset: "35%",
      stopColor: "rgb(30,107,154)"
    },
    {
      offset: "60%",
      stopColor: "rgb(81,183,231)"
    },
    {
      offset: "70%",
      stopColor: "rgb(147,222,168)"
    },
    {
      offset: "80%",
      stopColor: "rgb(253,212,95)"
    },
    {
      offset: "93%",
      stopColor: "rgb(230,108,86)"
    },
    {
      offset: "100%",
      stopColor: "rgb(105,37,19)"
    }
  ];
  selection
    .selectAll("stop")
    .data(gradientControl)
    .enter()
    .append("stop")
    .attr("offset", d => d.offset)
    .attr("stop-color", d => d.stopColor);
};

const renderAxis = axis => {
  axis
    .append("line")
    .attr("x2", d => xScale(d.index, 41))
    .attr("y2", d => yScale(d.index, 41))
    .attr("class", "axis-line");

  axis
    .append("line")
    .attr("x1", d => xScale(d.index, HIGHEST - 17))
    .attr("y1", d => yScale(d.index, HIGHEST - 17))
    .attr("x2", d => xScale(d.index, HIGHEST - 10.2))
    .attr("y2", d => yScale(d.index, HIGHEST - 10.2))
    .attr("class", "tick");

  axis
    .append("text")
    .attr("x", d => xScale(0, HIGHEST - 12))
    .attr("y", d => yScale(0, HIGHEST - 12))
    .attr("dx", ".25em")
    .attr("transform", d => {
      return `rotate(${angleScale(d.index)})`;
    })
    .text(d => d.month)
    .attr("class", "months")
    .style("font-size", 0.013 * HEIGHT);
};
const mathematicaPreprocess = json => {
  const data = json.DATA;
  return data[3].map((v, k) => ({
    date: v,
    tmin: +data[0][k],
    tmax: +data[1][k],
    prcp: +data[2][k] * 10
  }));
};

const d3Preprocess = json => {
  console.log(json);
  json.DATA = mathematicaPreprocess(json);
  const months = [];
  //find index for months based on data
  json.DATA.forEach((d, i) => {
    const day = moment(d.date, "YYYYMMDD");
    if (i === 0 || !moment(json.DATA[i - 1].date).isSame(day, "month")) {
      months.push({
        month: day.format("MMM").toUpperCase(),
        index: i
      });
    }
  });
  Object.assign(json.STATION, {
    geolocationDisplay:
      (json.STATION.LONGITUDE > 0
        ? `${json.STATION.LONGITUDE.toFixed(4)}° E`
        : `${-json.STATION.LONGITUDE.toFixed(4)}° W`) +
      "  " +
      (json.STATION.LATITUDE > 0
        ? `${json.STATION.LATITUDE.toFixed(4)}° N`
        : `${-json.STATION.LATITUDE.toFixed(4)}° S`) +
      "  " +
      `${json.STATION.ELEVATION}m`
  });
  return Object.assign({}, json, {
    months
  });
};

d3.json(api, (err, json) => {
  json = d3Preprocess(json);
  const days = json.DATA.length;
  angleScale.domain([0, days - 1]);
  const maxPRCP = d3.max(json.DATA, d => d.prcp);
  prcpScale.domain([0, maxPRCP]);

  // define gradients
  svg
    .append("defs")
    .append("radialGradient")
    .attr("gradientUnits", "userSpaceOnUse")
    .attr("cx", 0)
    .attr("cy", 0)
    .attr("r", "33%")
    .attr("id", "heatGradient")
    .call(generateRadialGradient);

  //circle axis
  viewport
    .append("g")
    .attr("class", "circle-axis-container")
    .selectAll("circle.axis")
    .data(d3.range(LOWEST + 20, HIGHEST - 10, 10))
    .enter()
    .append("circle")
    .attr("r", d => rScale(d))
    .attr("class", "axis record");

  //axis lines
  viewport
    .append("g")
    .attr("class", "axis-container")
    .selectAll(".axis")
    .data(json.months)<commit_msg>fix: use consistent gradient radius<commit_after>/**
json data format
{"STATION":{"LONGITUDE":116.587,"LATITUDE":40.074,"ELEVATION":55,"NAME":"Beijing","CODE":"ZBAA"},
"DATA": [[minTemperature], [maxTemperature], [Precipitation], [DatetimeValue]]}

Quantity Metric:
minTemperature: \[Degree]C
maxTemperature: \[Degree]C
Precipitation: cm
DatetimeValue: YYYYMMDD
*/
const api = `Shanghai.json`,
  margin = 20,
  WIDTH = Math.min(window.innerWidth, 1.3 * window.innerHeight) - margin,
  HEIGHT = window.innerHeight - margin,
  LOWEST = -40,
  HIGHEST = 60,
  maxPRCPRadius = WIDTH / 16;
const ANIMATION = {
  durationPerDay: 7.5 // unit: ms
};
const svg = d3.select("svg").attr("width", WIDTH).attr("height", HEIGHT);
// remove body unresolved when WIDTH and HEIGHT is setup
d3.select("#app").attr("unresolved", null);

const viewport = svg
  .append("g")
  .attr("class", "viewport")
  .attr("transform", "translate(" + WIDTH / 2 + "," + HEIGHT / 2 + ")");
const rScale = d3
  .scaleLinear()
  .domain([LOWEST, HIGHEST])
  .range([0, HEIGHT / 2 - margin]);
const yScale = (day, temp) =>
  -Math.cos(angleScale(day) * Math.PI / 180) * rScale(parseInt(temp));
const xScale = (day, temp) =>
  Math.sin(angleScale(day) * Math.PI / 180) * rScale(parseInt(temp));
const angleScale = d3.scaleLinear().range([0, 360]);
const prcpScale = d3.scaleLinear().range([0, maxPRCPRadius]);

const generateRadialGradient = selection => {
  const gradientControl = [
    {
      offset: "0%",
      stopColor: "rgb(0,24,35)"
    },
    {
      offset: "15%",
      stopColor: "rgb(0,59,93)"
    },
    {
      offset: "35%",
      stopColor: "rgb(30,107,154)"
    },
    {
      offset: "60%",
      stopColor: "rgb(81,183,231)"
    },
    {
      offset: "70%",
      stopColor: "rgb(147,222,168)"
    },
    {
      offset: "80%",
      stopColor: "rgb(253,212,95)"
    },
    {
      offset: "93%",
      stopColor: "rgb(230,108,86)"
    },
    {
      offset: "100%",
      stopColor: "rgb(105,37,19)"
    }
  ];
  selection
    .selectAll("stop")
    .data(gradientControl)
    .enter()
    .append("stop")
    .attr("offset", d => d.offset)
    .attr("stop-color", d => d.stopColor);
};

const renderAxis = axis => {
  axis
    .append("line")
    .attr("x2", d => xScale(d.index, 41))
    .attr("y2", d => yScale(d.index, 41))
    .attr("class", "axis-line");

  axis
    .append("line")
    .attr("x1", d => xScale(d.index, HIGHEST - 17))
    .attr("y1", d => yScale(d.index, HIGHEST - 17))
    .attr("x2", d => xScale(d.index, HIGHEST - 10.2))
    .attr("y2", d => yScale(d.index, HIGHEST - 10.2))
    .attr("class", "tick");

  axis
    .append("text")
    .attr("x", d => xScale(0, HIGHEST - 12))
    .attr("y", d => yScale(0, HIGHEST - 12))
    .attr("dx", ".25em")
    .attr("transform", d => {
      return `rotate(${angleScale(d.index)})`;
    })
    .text(d => d.month)
    .attr("class", "months")
    .style("font-size", 0.013 * HEIGHT);
};
const mathematicaPreprocess = json => {
  const data = json.DATA;
  return data[3].map((v, k) => ({
    date: v,
    tmin: +data[0][k],
    tmax: +data[1][k],
    prcp: +data[2][k] * 10
  }));
};

const d3Preprocess = json => {
  console.log(json);
  json.DATA = mathematicaPreprocess(json);
  const months = [];
  //find index for months based on data
  json.DATA.forEach((d, i) => {
    const day = moment(d.date, "YYYYMMDD");
    if (i === 0 || !moment(json.DATA[i - 1].date).isSame(day, "month")) {
      months.push({
        month: day.format("MMM").toUpperCase(),
        index: i
      });
    }
  });
  Object.assign(json.STATION, {
    geolocationDisplay:
      (json.STATION.LONGITUDE > 0
        ? `${json.STATION.LONGITUDE.toFixed(4)}° E`
        : `${-json.STATION.LONGITUDE.toFixed(4)}° W`) +
      "  " +
      (json.STATION.LATITUDE > 0
        ? `${json.STATION.LATITUDE.toFixed(4)}° N`
        : `${-json.STATION.LATITUDE.toFixed(4)}° S`) +
      "  " +
      `${json.STATION.ELEVATION}m`
  });
  return Object.assign({}, json, {
    months
  });
};

d3.json(api, (err, json) => {
  json = d3Preprocess(json);
  const days = json.DATA.length;
  angleScale.domain([0, days - 1]);
  const maxPRCP = d3.max(json.DATA, d => d.prcp);
  prcpScale.domain([0, maxPRCP]);

  // define gradients
  svg
    .append("defs")
    .append("radialGradient")
    .attr("gradientUnits", "userSpaceOnUse")
    .attr("cx", 0)
    .attr("cy", 0)
    .attr("r", rScale(HIGHEST - 20))
    .attr("id", "heatGradient")
    .call(generateRadialGradient);

  //circle axis
  viewport
    .append("g")
    .attr("class", "circle-axis-container")
    .selectAll("circle.axis")
    .data(d3.range(LOWEST + 20, HIGHEST - 10, 10))
    .enter()
    .append("circle")
    .attr("r", d => rScale(d))
    .attr("class", "axis record");

  //axis lines
  viewport
    .append("g")
    .attr("class", "axis-container")
    .selectAll(".axis")
    .data(json.months)
{'fraction_non_alphanumeric': 0.21031542176101922, 'fraction_numerical': 0.037604027535189564, 'mean_word_length': 2.8936, 'pattern_counts': {'":': 14, '<': 3, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1572771', 'n_tokens_mistral': 4007, 'n_tokens_neox': 3744, 'n_words': 706}