Public
Edited
Apr 2, 2023
Insert cell
# 230401_Punk The Stasi overhaul - fleet edit
Insert cell
d3 = require("d3@6")
Insert cell
concertSTOPS = FileAttachment("concertnight_003.csv").csv()
Insert cell
ampelmann = FileAttachment("ampelmaennchen.txt").tsv({array:true})
Insert cell
viewof stops2 = Inputs.radio(["0", "1", "2", "3"], {value:"0"})
Insert cell
border_01 = FileAttachment("border_01.png").url()
Insert cell
border_02 = FileAttachment("border_02@1.png").url()
Insert cell
border_03 = FileAttachment("border_03.png").url()
Insert cell
border_04 = FileAttachment("border_04.png").url()
Insert cell
stops
Insert cell
dashboard =

html`
<div class='outer' style='width:650px;height:750px'>

<div class='chart' style='position:absolute;top:55px;left:280px;width:860px'>
${chart}
</div>


<img src="${border_02}" style="position:absolute;top:0px;left:0px;width: 1200px"/>
<img src="${border_04}" style="position:absolute;top:624px;left:0px;width: 1200px"/>
<img src="${border_03}" style="position:absolute;top:0px;left:1065px;height: 750px"/>
<img src="${border_01}" style="position:absolute;top:0px;left:0px;height: 750px"/>


<div class='pageDisplay' style='position:absolute;width:400px;top:665px;left:250px;font-family:helvetica;font-size:16px;font-weight:400'>
${pageDisplay}
</div>



<div class='time' style='position:absolute;width:200px;top:630px;left:60px;font-family:helvetica;font-size:16px;font-weight:500'>
${time}
${viewof startTimerButton}
</div>



</div>


`
Insert cell
pageDisplay = {

//this cell controls the content that goes into the dashboard depending on my 'stops' radio button
var currentPage
if(stops == "0"){//this is the initial step of the gam
currentPage = html`

${concertSTOPS[stops].message}
${viewof gobutton}
`
set(viewof eyesOnly,"i don't know what that means")
}

if(stops == "1"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof initial}
`
set(viewof caughtresponse,"I've had enough of the daredevil life")
}

/*
if(stops == "BR"){
//have the br question, or some question on the way to br
}
*/

/*
if(stops == "BH"){
//have the berghaim question, or some question on the way to br
}


if(stops == "2"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof parkStop}
`
set(viewof initial,"thinking...")
}



if(stops == "3"){
currentPage = html`
${concertSTOPS[stops].prompt}//question from sheets file
${viewof eyesOnly}//this is the input, it contains the answers to the question
`
set(viewof parkStop,"thinking.....")// reset the previous input to a neutral value(you don't want the input to remain on the correct value)
}

*/


if(stops == "2"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof hotel}
`
set(viewof infoRV,"who cares")
}

if(stops == "3"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof golf}
`
set(viewof initial,"thinking...")
}

if(stops == "4"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof charlie}
`
set(viewof infoBERG,"who cares")
}

if(stops == "5"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof delta}
`
set(viewof initial,"thinking...")
}


if(stops == "6"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof hotel}
`
set(viewof initial,"thinking...")
}


if(stops == "7"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof echo}
`
set(viewof initial,"thinking...")
}

if(stops == "8"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof bravo}
`
set(viewof initial,"thinking...")
}

if(stops == "9"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoBERG}
`
set(viewof initial,"thinking...")
}

if(stops == "10"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoSUP}
`
set(viewof initial,"thinking...")
}
if(stops == "11"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoRV}
`
set(viewof charlie,"i need a minute")
}


if(stops == "12"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoRVSP}
`
set(viewof initial,"thinking...")
}


if(stops == "13"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoRR}
`
set(viewof initial,"thinking...")
}


if(stops == "14"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoSCHOKO}
`
set(viewof initial,"thinking...")
}


if(stops == "15"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoFRANNZ}
`
set(viewof initial,"thinking...")
}


if(stops == "16"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof infoDUN}
`
set(viewof initial,"thinking...")
}


if(stops == "17"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof caughtresponse}
`
set(viewof initial,"thinking...")
}

if(stops == "18"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof caughtresponse}
`
set(viewof initial,"thinking...")
}

if(stops == "19"){
currentPage = html`
${concertSTOPS[stops].message}
${viewof caughtresponse}
`
set(viewof hotel,"Let's hide out and think for a minute")
}




return currentPage
}
Insert cell
viewof gobutton = Inputs.button("Let the night begin!")
Insert cell
viewof initial = Inputs.radio(["How about Berghain?", "To Roadrunner's Paradise!","thinking..."], {})
Insert cell
viewof preBerghain = Inputs.radio(["Super excited for Berghain!", "Nervous...?"], {})
Insert cell
viewof choiceresponse = Inputs.radio(["The first one!", "Perhaps the second one?"], {})
Insert cell
viewof bravo = Inputs.radio(["Let's go to Schokoladen", "FRANNZ Club!"], {})
Insert cell
viewof charlie = Inputs.radio(["Rock & Viking Bar!", "Supamolly sounds good...", "i need a minute"], {})
Insert cell
viewof delta = Inputs.radio(["Party's not over...to FRANNZ Club!", "Let's try to escape to the West"], {})
Insert cell
viewof echo = Inputs.radio(["Dunckerclub sounds like a plan", "Maybe we call it a night?"], {})
Insert cell
viewof foxtrot = Inputs.radio(["To Rock & Viking we go!", "I don't know...maybe we should head back?"], {})
Insert cell
viewof golf = Inputs.radio(["Let's go to Supamolly", "Shall we escape to West Berlin?"], {})
Insert cell
viewof hotel = Inputs.radio(["On to Rock & Viking!", "Let's head back to West Berlin","Let's hide out and think for a minute"], {})
Insert cell
viewof india = Inputs.radio(["Time to head back to West Berlin!"], {})
Insert cell
viewof juliet = Inputs.radio(["Let's try to hit up Dunckerclub", "I don't know, maybe we head back..."], {})
Insert cell
viewof infoBERG = Inputs.radio(["Cool, good to know!", "who cares"], {})
Insert cell
viewof infoSUP = Inputs.radio(["Cool, good to know!"], {})
Insert cell
viewof infoRV = Inputs.radio(["Cool, good to know!", "who cares"], {})
Insert cell
viewof infoRVSP = Inputs.radio(["Cool, good to know!"], {})
Insert cell
viewof infoRR = Inputs.radio(["Cool, good to know!"], {})
Insert cell
viewof infoSCHOKO = Inputs.radio(["Cool, good to know!"], {})
Insert cell
viewof infoFRANNZ = Inputs.radio(["Cool, good to know!"], {})
Insert cell
viewof infoDUN = Inputs.radio(["Cool, good to know!"], {})
Insert cell
viewof caughtresponse = Inputs.radio(["Damn, that's too bad... guess I'll try again?","I've had enough of the daredevil life"], {})
Insert cell
viewof eyesOnly = Inputs.select(responses, {})
Insert cell
responses = ["Sure, let's give it a go","Do you see a Stasi officer?","I am lost in Berlin"]
Insert cell
mutable stops = 0
Insert cell
viewof i = Inputs.input(100)
Insert cell
Inputs.bind(Inputs.radio([0, 100]), viewof i)
Insert cell
Inputs.bind(Inputs.radio([0, 100]), viewof i)
Insert cell
i
Insert cell
//set(i,0)
Insert cell
{

//this cell looks for correct answers from the input, and progresses to the next step when appropriate
if(gobutton==1){
mutable stops = 1 //change to next stop on the map3
set(viewof gobutton,0)//reset button
set(viewof initial,null)
}

if(initial == "How about Berghain?"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "9"
}

if(initial == "To Roadrunner's Paradise!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "13"
}


if(bravo == "Let's go to Schokoladen"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "14"
}
if(bravo == "FRANNZ Club!"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "15"
}



if(charlie == "Rock & Viking Bar!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "11"
}
if(charlie == "Supamolly sounds good..."){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "10"
}

if(delta == "Party's not over...to FRANNZ Club!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "18"
}
if(delta == "Let's try to escape to the West"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "1"
}

if(echo == "Dunckerclub sounds like a plan"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "18"
}
if(echo == "Maybe we call it a night?"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "15"
}

if(foxtrot == "To Rock & Viking we go!"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "12"
}

if(foxtrot == "I don't know...maybe we should head back?"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "1"
}


if(golf == "Let's go to Supamolly"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "12"
}

if(golf == "Shall we escape to West Berlin?"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "1"
}

if(hotel == "On to Rock & Viking!"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "19"
}

if(hotel == "Let's head back to West Berlin"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "1"
}

if(india == "Time to head back to West Berlin!"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "1"
}


if(juliet == "Let's try to hit up Dunckerclub"){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "17"
}

if(juliet == "I don't know, maybe we head back..."){//these if statements allow us to continue the game
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "1"
}













if(infoBERG == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "4"
}

if(infoSUP == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "3"
}

if(infoRV == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "2"
}

if(infoRVSP == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "19" // THIS IS WRONG - NEED TO SEPARATE THIS INTO SEPARATE MOVES FOR R&V AND SUPAMOLLY
}


if(infoRR == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "8"
}

if(infoSCHOKO == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "5"
}


if(infoFRANNZ == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "7"
}


if(infoDUN == "Cool, good to know!"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "6"
}

if(caughtresponse == "Damn, that's too bad... guess I'll try again?"){//these if statements allow us to move the game to the next location
//mutable stops = "BR" //if correct answer = bandito rosso, move to stop BR
mutable stops = "1"
}



/*
if(initial == "berghaim"){
//mutable stops = "BH"
}
*/

/*
if(postBerghaim == "prenzlauerberg"){
//mutable stops = "PB"
}
*/

/*
if(postBerghaim == "kreuzberg"){
//mutable stops = "KB"
}


if(parkStop == "I'm not so sure about this..."){
mutable stops = 3
}


*/
if(eyesOnly == "Do you see a Stasi officer?"){
mutable stops = 0
}





if(stops == "0"){
//viewof initial = Inputs.input("nice walk")
//set(viewof initial,null)
//set(viewof parkStop,null)
//set(viewof eyesOnly,null)
}

}
Insert cell
function set(input, value) {
input.value = value;
input.dispatchEvent(new Event("input", {bubbles: true}));
}
Insert cell
viewof seconds = Inputs.range([0, 59], {value: 0, step:1, label: "seconds"})
Insert cell
viewof minutes = Inputs.range([0, 59], {value: 2, step:1, label: "minutes", value:2})
Insert cell
hours = 0
Insert cell
function* timer(i = 0) {
yield i;
while (true) {
yield Promises.tick(1000).then(() => i++);
}
}
Insert cell
currentTime = {
if(startTimerButton>0){
return timer();
}else{mutable stops = 0}
}
Insert cell
countdownTime = {
return minutes*60 + seconds;
}
Insert cell
//mutable timesup = 0
Insert cell
time = {
let result = countdownTime - currentTime;
if (currentTime == undefined){result = 0}
if ( result < 0 ){
result = "Time Up!";

}
else {
const remainHours = ""+parseInt(result/3600);
result = result - remainHours*3600;
const remainMinutes = ""+parseInt(result/60);
const remainSeconds = ""+parseInt(result%60);
result = remainMinutes.padStart(2,"0") + ":" +
remainSeconds.padStart(2,"0") ;
}

return html`
<style>
.countdown{ font-size: 40px;font-family:helvetica;font-weight:800 }
</style>
<span class="countdown">${result}</span>
`
}
Insert cell
viewof startTimerButton = Inputs.button([
["Start", value => value + 1],
["Reset", value => 0]
], {value: 0})
Insert cell
_berUpdatedDash3 = FileAttachment("230220_BER Updated Dash@3.png").image()
Insert cell
viewof choices = Inputs.radio(["Bandito Rosso", "SO36", "Dunckerclub"], {label: "Select a venue:", value: 0})
Insert cell
_berConcertChoice = FileAttachment("concert choice dash-04.png").image()
Insert cell
chart = {
const width = 400,
height = 350;
const svg = d3.create("svg")
.attr("viewBox", [5, 30, width-50, height-105]);

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

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 path6 = d3.geoPath().projection(projection);
var path7 = d3.geoPath().projection(projection);
var path8 = d3.geoPath().projection(projection);
var path9 = 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)")
*/


if(stops=="0"){
//then draw the first stop line segment
}
if(stops=="1"){
//then draw the first stop line segment
}


g.selectAll("path4") //d3 geopath
.data(BERwater.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', 'maroon')
.style("fill-opacity", ".3")
.style('stroke-opacity','.7')
.style("stroke-width", '.1')
.style('stroke', 'rosybrown')

g.selectAll("path6") //d3 geopath
.data(BERwall.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('stroke-opacity','.7')
.style("stroke-width", '.5')
.style('stroke', 'firebrick')
.style('fill', 'lightblue')
.style("fill-opacity", "0")



g.selectAll("path7") //d3 geopath
.data(BERbuildings.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', 'tan')
.style("fill-opacity", ".5")
.style('stroke-opacity','.5')
.style("stroke-width", '.1')
.style('stroke', 'darkred')


/*
g.selectAll("path5") //d3 geopath
.data(BERroads.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','.4')
.style("stroke-width", '.3')
.style('stroke', 'dodgerblue')

*/


var c = svg.selectAll("circle") //d3 geopath
.data(BERspots)
.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', 3)
.attr('fill',colorType) // add function to control color by 'type'
.attr('stroke-opacity','.65')
.attr("stroke-width", ".2")
.attr('stroke', 'pink')
.style('fill-opacity','1')
.on('mouseover', spotText)
.on('mouseout', removeSpotText)


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

if(d.Sector=='east'){color = 'maroon'}
if(d.Sector=='west'){color = 'lightslategrey'}

return color
}

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



svg.append("rect")
.attr('class','whitebox')
.attr("x", 65)
.attr("y", 127)
.attr("height", 21)
.attr("width", 59)
.attr('stroke','black')
.attr("stroke-width", '.5')
.attr('stroke-opacity', '.4')
.style("fill", 'white');

svg.append('text')
.attr('class','spots')
.attr('x','70')
.attr('y','135')
.attr('font-family','Helvetica')
.attr('font-size','.22em')
.attr('text-anchor','start')
.attr('font-weight','bold')
.text(d.Name)

svg.append('text')
.attr('class','spots')
.attr('x','70')
.attr('y','140')
.attr('font-family','Helvetica')
.attr('font-size','.15em')
.attr('text-anchor','start')
.attr('font-weight','normal')
.attr('font-style','italic')
.text(d.Neighborhood)

svg.append('text')
.attr('class','spots')
.attr('x','70')
.attr('y','143')
.attr('font-family','Helvetica')
.attr('font-size','.15em')
.attr('text-anchor','start')
.attr('font-weight','normal')
.attr('font-style','italic')
.text(d.ActivityType)

svg.append('line')
.attr('class','spotLine')
.attr('x1','124')
.attr('y1','137')
.attr('x2',projection([d.Long,d.Lat])[0])
.attr('y2','137')
.style('stroke-width','.3')
.style('stroke','black')
.style('stroke-dasharray','1 1')

svg.append('line')
.attr('class','spotLine')
.attr('x1',projection([d.Long,d.Lat])[0])
.attr('y1','137')
.attr('x2',projection([d.Long,d.Lat])[0])
.attr('y2',projection([d.Long,d.Lat])[1])
.style('stroke-width','.3')
.style('stroke','black')
.style('stroke-dasharray','1 1')





}
function removeSpotText(event,d) {
d3.select(this).attr('fill', colorType)
d3.select(this).attr('r', 3)
d3.select(this).style('stroke', 'pink')
d3.select(this).style('fill-opacity','1')
d3.select(this).style('stroke-opacity','.65')
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')

*/




function walkText(event,d){
d3.select(this).style("stroke-width", '3');
d3.select(this).style("stroke-dasharray", '4 0');

svg
.append('text')
.attr('class','walkText')
.attr('x','370')
.attr('y','385')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
//.attr('background-color', 'rgba(255, 0, 0)')
.text(d.properties.Text)

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

function walkErase(event,d){
d3.selectAll('path.walks').style('stroke-width','1')
d3.selectAll('path.walks').style('stroke-dasharray','4 2')
d3.selectAll('text.walkText').remove()
}

var p = svg.selectAll("polyline")
.data(ampelmann) //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", "black")
.style('stroke-opacity','0')
.style("stroke-width", '0')
.style("stroke", "rgb(0,0,0)")
.attr('transform',iconLocation)
function iconLocation(){
var xVal = projection([concertSTOPS[stops].Long,concertSTOPS[stops].Lat])[0]
var yVal = projection([concertSTOPS[stops].Long,concertSTOPS[stops].Lat])[1]

//console.log(xVal)
return "translate("+(xVal-5)+" "+(yVal+5)+")"
}

/*
svg
.append("image")
attr('x','0')
.attr('y','0')
.attr('width','100')
.attr('height','100')
.attr('href',tunnel)
*/

//if(showTunnels=="yes"){
var i = svg.selectAll("image")
.data(tunnelPng)//the key is that this dataset has both the image url and the lat/long
.enter()
.append("image")
.attr('x','0')
.attr('y','0')
.attr('width','14')
.attr('height','14')
.attr('href',function(d){return d.image})
.attr("transform", movePng)

function movePng(d,i){
var xVal = projection([d.Long, d.Lat])[0]-7
var yVal = projection([d.Long, d.Lat])[1]-7

return "translate("+xVal+" "+yVal+")"

}
//}

return svg.node();


}
Insert cell
paperDash = FileAttachment("230220_BER Updated Dash@1.png").image()
Insert cell
margin = ({top: 30, right: 20, bottom: 30, left: 40})
Insert cell
BERbuildings = FileAttachment("BER_buildingscropped_V2.geojson").json()
Insert cell
BERbox = FileAttachment("BER_bb.geojson").json()
Insert cell
BERwater = FileAttachment("BER_waterhatches_V1.geojson").json()
Insert cell
BERwall = FileAttachment("BER_wall.geojson").json()
Insert cell
Insert cell
Insert cell
tunnelPng = {//this cell combines the locations of the tunnels with the tunnel png.

var tunnelList = []
for (let i = 0; i < tunnelLoc.length; i++) {

tunnelList.push({Lat:tunnelLoc[i].Lat,Long:tunnelLoc[i].Long,type:"unclear",image:tunnel})
}


return tunnelList
}
Insert cell
import { wrap_text, wrap_text_nchar } from "@ben-tanen/svg-text-and-tspan-word-wrapping"
Insert cell
tooltip = d3
.select('body')
.append('div')
.attr('class', 'tooltip')
.style('position', 'absolute')
.style('z-index', '10')
.style('visibility', 'hidden')
.style('padding', '10px')
.style('background-color', 'white')
.style('border-radius', '4px')
.style('-webkit-border-radius', '10px')
.style('-moz-border-radius', '10px')
.style('-webkit-box-shadow', '4px 4px 10px rgba(0, 0, 0, 0.4)')
.style('-moz-box-shadow', '4px 4px 10px rgba(0, 0, 0, 0.4)')
.style('box-shadow', '4px 4px 10px rgba(0, 0, 0, 0.4)')
.style('color', 'white')
.style('font-family','sans-serif')
.text('a simple tooltip');
Insert cell
tunnel = FileAttachment("tunnel.png").url()
Insert cell
Insert cell
tunnelLoc = d3.csv(tunnelLink,d3.autoType)
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more