Public
Edited
Feb 15, 2023
Insert cell
# 230215_SYD final
Insert cell
d3 = require("d3@6")
Insert cell
plX = [

{name: "Coles", time:1.1, cost:52},
{name: "NooS", time:0.5, cost:15},
{name: "IstOx", time:0.7, cost:24},
{name: "Mille", time:1.4, cost:61},
{name: "Lib", time:0.9, cost:0},
{name: "Prop", time:1.3, cost:44},
{name: "RowH", time:0.1, cost:3},
{name: "MarM", time:1.9, cost:22},
{name: "Pow", time:2.1, cost:17},
{name: "Pyr", time:0.3, cost:4},
{name: "Pad", time:2.8, cost:43},
{name: "Hob", time:1.2, cost:58},
{name: "Quay", time:1.5, cost:11},
{name: "Opo", time:0.4, cost:18},
{name: "ThThP", time:0.8, cost:28},
{name: "Home", time:0.0, cost:0}

]
Insert cell
totalValues = {
var totalTime = 0
var totalCost = 0

totalTime = totalTime + (plX[0].time*Coles)
totalTime = totalTime + (plX[1].time*NooS)
totalTime = totalTime + (plX[2].time*IstOx)
totalTime = totalTime + (plX[3].time*Mille)
totalTime = totalTime + (plX[4].time*Lib)
totalTime = totalTime + (plX[5].time*Prop)
totalTime = totalTime + (plX[6].time*RowH)
totalTime = totalTime + (plX[7].time*MarM)
totalTime = totalTime + (plX[8].time*Pow)
totalTime = totalTime + (plX[9].time*Pyr)
totalTime = totalTime + (plX[10].time*Pad)
totalTime = totalTime + (plX[11].time*Hob)
totalTime = totalTime + (plX[12].time*Quay)
totalTime = totalTime + (plX[13].time*Opo)
totalTime = totalTime + (plX[14].time*ThThP)
totalTime = totalTime + (plX[15].time*Home)

totalCost = totalCost + (plX[0].cost*Coles)
totalCost = totalCost + (plX[1].cost*NooS)
totalCost = totalCost + (plX[2].cost*IstOx)
totalCost = totalCost + (plX[3].cost*Mille)
totalCost = totalCost + (plX[4].cost*Lib)
totalCost = totalCost + (plX[5].cost*Prop)
totalCost = totalCost + (plX[6].cost*RowH)
totalCost = totalCost + (plX[7].cost*MarM)
totalCost = totalCost + (plX[8].cost*Pow)
totalCost = totalCost + (plX[9].cost*Pyr)
totalCost = totalCost + (plX[10].cost*Pad)
totalCost = totalCost + (plX[11].cost*Hob)
totalCost = totalCost + (plX[12].cost*Quay)
totalCost = totalCost + (plX[13].cost*Opo)
totalCost = totalCost + (plX[14].cost*ThThP)
totalCost = totalCost + (plX[15].cost*Home)

return[totalTime, totalCost]
}
Insert cell
viewof colorchange = Inputs.range([0, 255], {step: 1, label: "Color Changer", value:131})
Insert cell
viewof radvar = Inputs.radio([2,3,4], {label: "Radius size", value: 3})
Insert cell
viewof Coles = Inputs.radio([0, 1, 2, 3, 4], {label: "Coles", value: 0})
Insert cell
viewof NooS = Inputs.radio([0, 1, 2, 3, 4], {label: "Noodle Star", value: 0})
Insert cell
viewof IstOx = Inputs.radio([0, 1, 2, 3, 4], {label: "Istanbul On Oxford", value: 0})
Insert cell
viewof Mille = Inputs.radio([0, 1, 2, 3, 4], {label: "Mille Vini Bar", value: 0})
Insert cell
viewof Lib = Inputs.radio([0, 1, 2, 3, 4], {label: "Surry Hills Library", value: 0})
Insert cell
viewof Prop = Inputs.radio([0, 1, 2, 3, 4], {label: "The Prophet", value: 0})
Insert cell
viewof RowH = Inputs.radio([0, 1, 2, 3, 4], {label: "Rowhouses", value: 0})
Insert cell
viewof MarM = Inputs.radio([0, 1, 2, 3, 4], {label: "Maritime Museum", value: 0})
Insert cell
viewof Pow = Inputs.radio([0, 1, 2, 3, 4], {label: "Powerhouse", value: 0})
Insert cell
viewof Pyr = Inputs.radio([0, 1, 2, 3, 4], {label: "Pyrmont Bridge", value: 0})
Insert cell
viewof Pad = Inputs.radio([0, 1, 2, 3, 4], {label: "Paddy's Markets", value: 0})
Insert cell
viewof Hob = Inputs.radio([0, 1, 2, 3, 4], {label: "Hobbyco", value: 0})
Insert cell
viewof Quay = Inputs.radio([0, 1, 2, 3, 4], {label: "Circular Quay", value: 0})
Insert cell
viewof Opo = Inputs.radio([0, 1, 2, 3, 4], {label: "Oporto", value: 0})
Insert cell
viewof ThThP = Inputs.radio([0, 1, 2, 3, 4], {label: "Thai Tha Poh", value: 0})
Insert cell
viewof Home = Inputs.radio([0, 1, 2, 3, 4], {label: "Home", value: 0})
Insert cell
chart = {
const width = 380,
height = 450;
const svg = d3.create("svg")
.attr("viewBox", [100, 0, width-100, height-180]);

// Use Mercator projection
var projection = d3
.geoMercator()
.fitSize([width - 50, height - 50], SYDbox);

var path1 = d3.geoPath().projection(projection);
var path2 = d3.geoPath().projection(projection);
var path3 = d3.geoPath().projection(projection);
var path4 = d3.geoPath().projection(projection);
var path5 = d3.geoPath().projection(projection);
var g = svg.append("g").attr("id", "paths");
//i'm not using the boundary lines, so I'm going to comment them out
/*
g.selectAll("path1") //d3 geopath
.data(boundary.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path1) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
*/




g.selectAll("path4") //d3 geopath
.data(SYDwater.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path4) //The d attribute defines a path to be drawn, only applies to appended elements
.style('fill', 'lavenderblush')
.style("fill-opacity", ".6")
.style('stroke-opacity','.4')
.style("stroke-width", '.25')
.style('stroke', 'maroon')
g.selectAll("path4") //d3 geopath
.data(SYDbuildings.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path3) //The d attribute defines a path to be drawn, only applies to appended elements
.style('fill', 'salmon')
.style("fill-opacity", ".3")
.style('stroke-opacity','.2')
.style("stroke-width", '.15')
.style('stroke', 'maroon')

g.selectAll("path5") //d3 geopath
.data(SYDroads.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','outlines')
.attr("d", path2) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','.3')
.style("stroke-width", '.2')
.style('stroke', 'firebrick')


var c = svg.selectAll("circle") //d3 geopath
.data(SYDspots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function(d) {return projection([d.LONG,d.LAT])[0]})
.attr("cy", function(d) {return projection([d.LONG,d.LAT])[1]})
.attr('r', radvar)
.attr('fill',colorType) // add function to control color by 'type'
.attr('stroke-opacity','.55')
.attr("stroke-width", "2")
.attr('stroke', 'plum')
.style('fill-opacity','1')
.on('mouseover', spotText)
.on('mouseout', removeSpotText)

function colorType(d,i) {
var color = 'black'

if(d.CATEGORY=='Restaurant'){color = 'mediumvioletred'}
if(d.CATEGORY=='Place'){color = 'purple'}
if(d.CATEGORY=='Thing'){color = 'rgb(255,255,'+colorchange+')'}

return color
}



svg.append("rect")
.attr("x", 305)
.attr("y", 31)
.attr("height", 51)
.attr("width", 32)
.attr('stroke','black')
.attr("stroke-width", '.5')
.attr('stroke-opacity', '.4')
.style("fill", 'white');


svg.append('text')
.attr('x','310')
.attr('y','40')
.attr('font-family','Helvetica')
.attr('font-size','.2em')
.attr('text-anchor','start')
.attr('font-weight','normal')
.attr('font-style','regular')
.text("Time (hours)")
svg.append('text')
.attr('x','310')
.attr('y','50')
.attr('font-family','Helvetica')
.attr('font-size','.6em')
.attr('text-anchor','start')
.attr('font-weight','bold')
.attr('font-style','regular')
.text(totalValues[0])

svg.append('text')
.attr('x','310')
.attr('y','65')
.attr('font-family','Helvetica')
.attr('font-size','.2em')
.attr('text-anchor','start')
.attr('font-weight','normal')
.attr('font-style','regular')
.text("Cost (AUD)")
svg.append('text')
.attr('x','310')
.attr('y','75')
.attr('font-family','Helvetica')
.attr('font-size','.6em')
.attr('text-anchor','start')
.attr('font-weight','bold')
.attr('font-style','regular')
.text(totalValues[1])



if(totalValues[0] > 36){
svg.append("text")
//.attr('class','spotInfo')
.attr('x','190')
.attr('y','85')
.attr('font-family','Tahoma')
.attr('font-size','0.7em')
.attr('font-weight','Bold')
.attr('fill','firebrick')
.attr('text-anchor','middle')
.text('OUT OF TIME!')
}

if(totalValues[0] > 36){
svg.append("text")
//.attr('class','spotInfo')
.attr('x','190')
.attr('y','95')
.attr('font-family','Tahoma')
.attr('font-size','0.3em')
.attr('font-weight','Bold')
.attr('fill','firebrick')
.attr('text-anchor','middle')
.text('Did you really think you had all the time in the world?')
}

if(totalValues[1] > 800){
svg.append("text")
//.attr('class','spotInfo')
.attr('x','190')
.attr('y','150')
.attr('font-family','Tahoma')
.attr('font-size','0.7em')
.attr('font-weight','Bold')
.attr('fill','firebrick')
.attr('text-anchor','middle')
.text('EMPTY WALLET!')
}

if(totalValues[1] > 800){
svg.append("text")
//.attr('class','spotInfo')
.attr('x','190')
.attr('y','160')
.attr('font-family','Tahoma')
.attr('font-size','0.3em')
.attr('font-weight','Bold')
.attr('fill','firebrick')
.attr('text-anchor','middle')
.text('You wasted all your money...again. Hope it was worth it!!')
}


function spotText(event,d){
d3.select(this)
.attr('fill', 'indigo')
.attr('r', '6')
.style('stroke', 'mediumslateblue')
.style("stroke-opacity",'.65')
.style("stroke-width", '5')



svg.append("rect")
.attr('class','whitebox')
.attr("x", 245)
.attr("y", 170)
.attr("height", 30)
.attr("width", 100)
.attr('stroke','black')
.attr("stroke-width", '.5')
.attr('stroke-opacity', '.4')
.style("fill", 'white');

svg.append('text')
.attr('class','spots')
.attr('x','252')
.attr('y','183')
.attr('font-family','Helvetica')
.attr('font-size','.35em')
.attr('text-anchor','start')
.attr('font-weight','bold')
.text(d.NAME)

svg.append('text')
.attr('class','spots')
.attr('x','252')
.attr('y','191')
.attr('font-family','Helvetica')
.attr('font-size','.2em')
.attr('text-anchor','start')
.attr('font-weight','normal')
.attr('font-style','italic')
.text(d.DESCRIPTION)

svg.append('line')
.attr('class','spotLine')
.attr('x1','245')
.attr('y1','183')
.attr('x2',projection([d.LONG,d.LAT])[0])
.attr('y2','183')
.style('stroke-width','.5')
.style('stroke','black')
.style('stroke-dasharray','2 1')

svg.append('line')
.attr('class','spotLine')
.attr('x1',projection([d.LONG,d.LAT])[0])
.attr('y1','183')
.attr('x2',projection([d.LONG,d.LAT])[0])
.attr('y2',projection([d.LONG,d.LAT])[1])
.style('stroke-width','.5')
.style('stroke','black')
.style('stroke-dasharray','2 1')





}
function removeSpotText(event,d) {
d3.select(this).attr('fill', colorType)
d3.select(this).attr('r', 3)
d3.select(this).style('stroke', 'orchid')
d3.select(this).style('fill-opacity','1')
d3.select(this).style('stroke-opacity','.55')
d3.select(this).style('stroke-width', '2')
d3.selectAll('text.spots').remove()
d3.selectAll('line.spotLine').remove()
d3.selectAll('rect.whitebox').remove()




var wrap = svg.selectAll("text.spots")
.each(function(d,i) {wrap_text(d3.select(this), 100) } );
}

/*

c.enter.append('circle')// format to add additional circles
.data(spots)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function(d) {return projection([d.longitude,d.latitude])[0]})
.attr("cy", function(d) {return projection([d.longitude,d.latitude])[1]})
.attr('r',3)
.attr('fill','black')
.style('fill-opacity','1')

*/


return svg.node();
}
Insert cell
frameimport = FileAttachment("export_test_frompython_010.txt").tsv({array:true})
Insert cell
border = {
const width = 1200,
height = 800;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

var p = svg.selectAll("polyline")
.data(frameimport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.style("fill", "firebrick")
.style('fill-opacity', '1')
.style('stroke-opacity','.8')
.style("stroke-width", '.4')
.style('stroke', 'maroon')

return svg.node();
}
Insert cell
patchimport = FileAttachment("bigpatch@1.txt").tsv({array:true})
Insert cell
patch = {
const width = 1200,
height = 800;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

var p = svg.selectAll("polyline")
.data(patchimport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.style("fill", "white")
.style('fill-opacity', '1')
.style('stroke', 'none')

return svg.node();
}
Insert cell
redpatchimport = FileAttachment("redpatch.txt").tsv({array:true})
Insert cell
redpatch = {
const width = 1200,
height = 800;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

var p = svg.selectAll("polyline")
.data(redpatchimport) //get data to define path
.enter() //there are more data than elements, this selects them
.append("polyline") //appends path to data
.attr('points', function(d){return d})
.style("fill", "white")
.style('fill-opacity', '1')
.style('stroke', 'none')

return svg.node();
}
Insert cell
dashboard =

html`

<div class='dashboardOuter' style='height:800px;width:1200px'>



<div class='border' style='position:absolute;width:790px;top:20px;left:489px'>
${chart}
</div>

<div class='border' style='position:absolute;width:1200px;top:0px;left:0px'>
${patch}
</div>

<div class='border' style='position:absolute;width:1200px;top:0px;left:0px'>
${redpatch}
</div>

<div class='border' style='position:absolute;width:1200px;top:0px;left:0px'>
${border}
</div>

<div class='indexes' style='position:absolute;top:120px;left:85px;font-family:tahoma;text-align:right'>
${md` Time (hours): **${totalValues[0]}** `}
</div>

<div class='indexes' style='position:absolute;top:140px;left:85px;font-family:tahoma;text-align:right'>
${md` Cost (AUD): **$${totalValues[1]}** `}
</div>

<div class='indexes' style='position:absolute;top:160px;left:85px;font-family:tahoma'>
${md` **Select** the number of visits to each location `}
</div>

<div class='indexes' style='position:absolute;top:741px;left:43px;font-family:tahoma;font-size:21px;color:white'>
${md` 36 hours in ****SYDNEY****, NEW SOUTH WALES `}
</div>


<div class='border' style='position:absolute;width:400px;top:220px;left:85px'>
${viewof Home}
</div>

<div class='border' style='position:absolute;width:400px;top:240px;left:85px'>
${viewof Coles}
</div>

<div class='border' style='position:absolute;width:400px;top:260px;left:85px'>
${viewof NooS}
</div>

<div class='border' style='position:absolute;width:400px;top:280px;left:85px'>
${viewof IstOx}
</div>

<div class='border' style='position:absolute;width:400px;top:300px;left:85px'>
${viewof Mille}
</div>

<div class='border' style='position:absolute;width:400px;top:320px;left:85px'>
${viewof Lib}
</div>

<div class='border' style='position:absolute;width:400px;top:340px;left:85px'>
${viewof Prop}
</div>

<div class='border' style='position:absolute;width:400px;top:360px;left:85px'>
${viewof RowH}
</div>

<div class='border' style='position:absolute;width:400px;top:380px;left:85px'>
${viewof MarM}
</div>

<div class='border' style='position:absolute;width:400px;top:400px;left:85px'>
${viewof Pow}
</div>

<div class='border' style='position:absolute;width:400px;top:420px;left:85px'>
${viewof Pyr}
</div>

<div class='border' style='position:absolute;width:400px;top:440px;left:85px'>
${viewof Pad}
</div>

<div class='border' style='position:absolute;width:400px;top:460px;left:85px'>
${viewof Hob}
</div>

<div class='border' style='position:absolute;width:400px;top:480px;left:85px'>
${viewof Quay}
</div>

<div class='border' style='position:absolute;width:400px;top:500px;left:85px'>
${viewof Opo}
</div>

<div class='border' style='position:absolute;width:400px;top:520px;left:85px'>
${viewof ThThP}
</div>



</div>

`
Insert cell
SYDbuildings = FileAttachment("SYD_buildings_004.geojson").json()
Insert cell
SYDbox = FileAttachment("SYD_boundingbox_001.geojson").json()
Insert cell
SYDroads = FileAttachment("SYD_roads_004.geojson").json()
Insert cell
SYDwater = FileAttachment("SYD_water_001.geojson").json()
Insert cell
SYDrails = FileAttachment("SYD_railways_001.geojson").json()
Insert cell
SYDspots = FileAttachment("220118_SYD_locations_V3.csv").csv()
Insert cell
import { wrap_text, wrap_text_nchar } from "@ben-tanen/svg-text-and-tspan-word-wrapping"
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