plotConsumption = (type) => {
const Brennwert = 10.5
const mdata = data.filter(d => d.term === "V39."+type)
.filter(d => new Date(d.timestamp) > new Date("2024-01-01T00:00:00+00:00"))
const r2d = x => Math.round(100*x)/100
const KWh = type === "Erdgas" ? r2d(mdata.length*Brennwert/1000) : r2d(mdata.length/75)
const title = type+"-Verbrauch "+ d3.min(mdata, d => d.timestamp).substring(0,10) + " - " + d3.max(mdata, d => d.timestamp).substring(0,10) +": "
+ ((type === "Erdgas" )
? r2d(mdata.length/1000) + "m³ Erdgas === " + KWh + "kWh"
: KWh + "kWh")
+ " entries: " + mdata.length + ""
const boxWidth = 700
const boxHeight = boxWidth*1/3
const margin = ({top: 30, right: 30, bottom: 30, left: 50})
const x = d3.scaleTime()
.domain([new Date(d3.min(mdata, d => d.timestamp)), new Date(d3.max(mdata, d => d.timestamp))])
.range([0, boxWidth ])
const y = d3.scaleSqrt()
.domain([0, d3.max(mdata, d => d.Watt)])
.range([boxHeight , 0])
const canvas = d3.select(DOM.svg(boxWidth + margin.left + margin.right, boxHeight + margin.top + margin.bottom))
canvas.node().style.border = '1px solid lightgrey'
canvas.append("text")
.attr("transform", "translate("+margin.left+",20)")
.attr("font-size", "14px")
.attr("f0nt-family","sans-serif")
.attr("y", 0)
.attr("x", 0)
.attr("font-family", "monospace")
.text(title)
const drawredline = (evt, text="") => {
const xpos = evt.offsetX
const ypos = boxHeight - evt.offsetY
const lineOffsetFromMouse = 0
const redColor = "red"
canvas.selectAll(".redLine").remove()
d3.select("#xMouse-value").text(evt.offsetX)
d3.select("#yMouse-value").text(evt.offsetY)
plot.append ("path")
.attr("class", "redLine")
.attr("stroke", redColor)
.attr("d", "M "+(evt.offsetX - lineOffsetFromMouse - margin.left)+","+(boxHeight)+",L "+(evt.offsetX - lineOffsetFromMouse- margin.left)+",0 Z")
plot.append ("path")
.attr("class", "redLine")
.attr("stroke", redColor)
.attr("d", "M "+(evt.offsetX - 10 - margin.left)+","+(evt.offsetY-margin.top)+",L "+(evt.offsetX + 10- margin.left)+","+(evt.offsetY-margin.top)+" Z")
plot.append ("text")
.attr("class", "redLine")
.text( text )
.attr("x", evt.offsetX+5)
.attr("y", 10)
.attr("dy", ".75em")
.attr("fill", redColor)
.attr("text-anchor", "left")
.style("font", "12px sans-serif")
.append("tspan")
.attr("x", evt.offsetX+5- margin.left)
.attr("dy", "1em")
.text( "Energy: "+Math.round(y.invert(boxHeight-ypos-margin.top)) + " Watt" )
.append("tspan")
.attr("x", evt.offsetX+5- margin.left)
.attr("dy", "1em")
.text( "Date: "+new Date(x.invert(xpos)).toISOString().substring(0,10) )
.append("tspan")
.attr("x", evt.offsetX+5- margin.left)
.attr("dy", "1em")
.text( "Time: "+new Date(x.invert(xpos)).toISOString().substring(11,19) )
}
const plot = d3.create("svg")
.append("g")
.attr("transform", "translate("+margin.left+","+margin.top+")")
.on("mouseout", canvas.selectAll(".redLine").remove() )
.on("mousemove", evt => drawredline(evt, "") )
canvas.append(() => plot.node())
plot.append("rect")
.attr("width", boxWidth)
.attr("height", boxHeight)
.attr("fill", "lightgrey")
.attr("stroke", "grey")
.attr("stroke-width", 1)
.attr("opacity", 0.2)
plot.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0," + (boxHeight) + ")")
.call(d3.axisBottom(x))
plot.append("g")
.attr("class", "y-axis")
.call(d3.axisLeft(y))
.call(g => g.selectAll(".tick:not(:first-of-type) line").attr("stroke", "#ddd").attr('opacity',0.1))
const hourlyData = []
const firstTimestamp = new Date(d3.min(mdata, d => d.timestamp))
const lastTimestamp = new Date(d3.max(mdata, d => d.timestamp))
let timeQuant = firstTimestamp
while (timeQuant < lastTimestamp) {
const hourData = mdata.filter(d => d.timestamp.substring(0,14) === timeQuant.toISOString().substring(0,14))
const hourAverage = d3.mean(hourData, d => d.Watt)
hourlyData.push({time: timeQuant.toISOString().substring(0,14)+"00:00+00:00", Watt: hourAverage || 0})
timeQuant = new Date(timeQuant.getTime() + 60*60*1000)
}
plot.selectAll("rect")
.data(hourlyData)
.enter()
.append("rect")
.attr("x", d => x(new Date(d.time)))
.attr("y", d => y(d.Watt))
.attr("width", boxWidth/hourlyData.lenght)
.attr("height", d => boxHeight - y(d.Watt))
.attr("fill", "blue")
.attr("stroke", "blue")
.attr("stroke-width", 1)
.attr("opacity", 0.3)
return canvas.node()
}