Published
Edited
Apr 14, 2022
1 star
Insert cell
# Arcade Game Pricing
Insert cell
Insert cell
Insert cell
heroPickRate = {
let svg = d3.create('svg').style("background-color", 'white').attr("preserveAspectRatio", "none") .attr("viewBox", "0 0 963 580")
svg.append("image")
.attr("xlink:href", background)
.attr("x", 0)
.attr("y", 0)
.attr("width", 1045)
.attr("height", 600).attr("opacity", 0.5);
svg.append('text')
// From https://fonts.googleapis.com/css?family=Pacifico, pick the url under `/* latin */`
.call(addWebFont, 'VT323', 'https://fonts.gstatic.com/s/vt323/v15/pxiKyp0ihIEF2isfFJXUdVNF.woff2')
.attr('style', "font-size: 40px; font-family: 'VT323';")
.text('Maximizing Arcade Profit through Difficulty')
.attr('x', 983 / 2)
.attr('y', 50)
.attr('dominant-baseline', 'middle')
.attr('text-anchor', 'middle');
svg.append("image")
.attr("xlink:href", "https://greblytics.com/wp-content/uploads/2021/03/cropped-Grebnesor-Analytics-SK_JRD-01.png")
.attr("x", 803)
.attr("y", 0)
.attr("width", 180)
.attr("height", 90);


let yScale = d3.scaleLinear()
.domain(d3.extent(tot_price_per_play))
.range([500, 100])

let xScale = d3.scaleLinear()
.domain([0,tot_price_per_play.length])
.range([100, 900])

svg.append("text")
.attr("class", "signature")
.attr("text-anchor", "left")
.attr("y", 2)
.attr("x", 0)
.attr("dy", ".75em")
.attr('style', "font-size: 20px; font-family: 'VT323';")
.text("Author: Sam Rosenberg")


svg.append("text")
.attr("text-anchor", "end")
.attr("y", 300)
.attr("x", 943)
.attr("dy", ".75em")
.attr('style', "font-size: 20px; font-family: 'VT323';")
.text("Percentage winning each try: " + clear_pct + "%")
svg.append("text")
.attr("text-anchor", "end")
.attr("y", 317)
.attr("x", 943)
.attr("dy", ".75em")
.attr('style', "font-size: 20px; font-family: 'VT323';")
.text("Price of one play: $" + price)

svg.append("text")
.attr("text-anchor", "end")
.attr("y", 283)
.attr("x", 943)
.attr("dy", ".75em")
.attr('style', "font-size: 20px; font-family: 'VT323';")
.text("People playing game: " + players)
svg.selectAll('play')
.data(tot_price_per_play)
.join('image')
.attr('x', function(d, i){console.log(xScale(i)); return xScale(i+1)-15})
.attr('y', function(d, i){console.log(yScale(d)); return yScale(d)-15})
.attr('width', 30).attr('height', 30).attr("xlink:href", "https://www.tynker.com/minecraft/api/block?id=5878df4a1c36d1504b8b456c&w=400&h=400&width=400&height=400&mode=contain&format=jpg&quality=75&cache=max&v=1484316490")

svg.append('g')
.attr('transform', `translate(${60}, 0)`)
.call(d3.axisLeft(yScale)).attr('style', "font-size: 20px; font-family: 'VT323';");

svg.append('g')
.attr('transform', `translate(${0}, ${530})`)
.call(d3.axisBottom(xScale)).attr('style', "font-size: 40px; font-family: 'VT323';");

return svg.node();
}
Insert cell
players = 1000

Insert cell
tot_price_per_play = {
let toAdd = [];
let prev = 0;
let players_remaining = players;
while (players_remaining > 1)
{
toAdd.push(prev + players_remaining*price)
prev = prev + players_remaining*price
players_remaining = players_remaining - players_remaining*(clear_pct/100)
}
return toAdd;
}
Insert cell
background = "https://wallpaperaccess.com/full/3739446.jpg"
Insert cell
chart = {
const width = 600;
const height = 400;
const svg = d3.select(DOM.svg(width, height));
svg.append('text')
// From https://fonts.googleapis.com/css?family=Pacifico, pick the url under `/* latin */`
.call(addWebFont, 'VT323', 'https://fonts.gstatic.com/s/vt323/v15/pxiKyp0ihIEF2isfFJXUdVNF.woff2')
.attr('style', "font-size: 25px; font-family: 'VT323';")
.text('Maximizing Arcade Profit through Difficulty')
.attr('x', width / 2)
.attr('y', height / 2)
.attr('dominant-baseline', 'middle')
.attr('text-anchor', 'middle');
return svg.node();
}
Insert cell
async function addWebFont(selection, fontName, fontURL, fontType = 'woff2') {
const fontData = await toDataURL(fontURL);
return selection.append('style').text(`
@font-face {
font-family: '${fontName}';
src: url(${fontData}) format('${fontType}');
}
`);
};
Insert cell
async function toDataURL(url) {
return new Promise(async(resolve, reject) => {
const res = await fetch(url);
if(!res.ok) return reject(`Error: ${res.status} ${res.statusText}`);
const blob = await res.blob();
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => resolve(reader.result);
});
}
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