Published
Edited
Jul 17, 2022
Fork of XML to JSON
Insert cell
Insert cell
function getCategories(items) {
return items.map((d) => {
if (Array.isArray(d["category"])) {
return d["category"].map((cat) => cleanCategory(cat)[1]);
}
return ["podcast"];
});
}
Insert cell
data["rss"]["channel"]["item"][0]["category"].map((d) => cleanCategory(d)[1])
Insert cell
drawEpisodes(data["rss"]["channel"])
Insert cell
data["rss"]["channel"]["item"].filter(
(d) => duration2second(d.duration) > 3600 * 2.5
)
Insert cell
Insert cell
toBeRemoved = [
"concast",
"solocast",
"podcast",
"Football",
"!",
"spoana",
"ann",
"HWN",
"neo4j",
"ZECCARS",
"graphdb",
"kaggle",
"solo",
"さかろぐ",
"ビヨンドマックスギガキング",
"打線",
"Wikipediaごっこ",
"Hot Week News",
"reinforcement learning",
"未分類",
"5時チャレ",
"Life in Germany",
"Sports Data",
"upuraさんのMC力",
"M-1"
]
Insert cell
function cleanCategory(category) {
const re = /<!\[CDATA\[([\w\s\S\W]+)\]\]>/;
const result = re.exec(category);
if (result != null) return result;
return category;
}
Insert cell
starrs = {
const res = [];
const episodes = data["rss"]["channel"]["item"].filter(
(d) => d["title"][0] == "#"
);
const starrs = getCategories(episodes).map((d) => {
res.push(...d);
});
return Array.from(d3.union(res))
.map((d) => {
return {
name: d,
appearance: countAppearance(episodes, d)
};
})
.filter((d) => {
return toBeRemoved.indexOf(d["name"]) === -1;
});
}
Insert cell
function countAppearance(data, target) {
let res = 0;
getCategories(data).map((d) => {
if (d.indexOf(target) !== -1) {
res += 1;
}
});
return res;
}
Insert cell
parser = new DOMParser()
Insert cell
Insert cell
data = xmlToJSON(feed)
Insert cell
Insert cell
class ChartObject {
constructor(selector, data, height = 500, width = 500, margin = 25) {
this.selector = selector;
this.data = data;
this.height = height;
this.width = width;
this.margin = margin;

selector.selectAll("svg").remove();
this.svg = selector
.append("svg")
.attr("width", this.width)
.attr("height", this.height);
}

getScaleLinearX(domain, range=[this.margin, this.width - this.margin]) {
return d3.scaleLinear().domain(domain).range(range)
}

getScaleLinearY(domain, range=[this.height - this.margin, this.margin]) {
return d3.scaleLinear().domain(domain).range(range)
}

getScaleBandX(domain, range=[this.margin, this.width - this.margin]) {
return d3.scaleBand().domain(domain).range(range)
}

getScaleLinearY(domain, range=[this.height - this.margin, this.margin]) {
return d3.scaleBand().domain(domain).range(range)
}
}
Insert cell
function duration2second(duration) {
if (duration == null) return 0;

const split = duration.split(":").map((d) => parseInt(d));
if (split.length === 2) {
return split[0] * 60 + split[1];
}
return 3600 * split[0] + 60 * split[1] + split[2];
}
Insert cell
Insert cell
function drawLength(data) {
const height = 500;
const mainWidth = 500;
const legendWidth = 300;
const width = mainWidth + legendWidth;
const margin = 45;
const svg = d3.create("svg").attr("width", width).attr("height", height);

const g = svg.append("g");

const nEpisodes = data["item"].length;
// const tParser = d3.timeParse()
const dates = data["item"].map((d) => Date.parse(d.pubDate));
const st = d3
.scaleBand()
.domain(dates)
.range([margin, mainWidth - margin]);

const sDuration = d3
.scaleLinear()
.domain([0, 3600 * 3])
.range([height - margin, margin]);

const taxis = d3.axisBottom(st);
svg
.append("g")
.attr("transform", `translate(0, ${height - margin})`)
.call(taxis);

const yaxis = d3.axisLeft(sDuration);
svg
.append("g")
.attr("transform", `translate(${margin - 5}, 0)`)
.call(yaxis);

const title = g
.append("text")
.attr("x", margin)
.attr("y", margin + 20)
.attr("font-size", 25)
.attr("fill", "#222")
.text(data["title"]);

const subtitle = g
.append("text")
.attr("x", margin + 13 * data["title"].length)
.attr("y", margin + 20)
.attr("font-size", 15)
.attr("fill", "#777")
.text(data["description"]);

const selectedTitle = g
.append("text")
.attr("x", margin)
.attr("y", margin + 40)
.attr("font-size", 13)
.attr("fill", "#333");

const selectedSubtitle = g
.append("text")
.attr("x", margin)
.attr("y", margin + 40 + 13)
.attr("font-size", 10)
.attr("fill", "#777");

// 数字が#つきじゃない全エピソード対象になっている
const episodes = g.append("g");
episodes
.selectAll("rect")
.data(data["item"])
.join("rect")
.attr("x", (d) => st(Date.parse(d["pubDate"])))
.attr("y", (d) => {
const second = duration2second(d["duration"]);
return second !== 0 ? sDuration(second) : 0;
})
.attr("width", st.bandwidth())
.attr("height", function (d) {
return sDuration(0) - d3.select(this).attr("y");
})
.attr("fill", "#0dd");
return svg.node();
}
Insert cell
drawLength(data["rss"]["channel"])
Insert cell
starrs
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more