From 1c570ea2a0e81d9d736c896f330fc8ba38363ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Z=C3=ADpek?= Date: Sun, 30 Jun 2024 09:06:59 +0200 Subject: [PATCH] Only display max values once --- server/src/app/routes/dow.ts | 128 +++++++++++++++++++++------------- server/static/app.css | 5 ++ server/static/dow-emulator.js | 8 ++- 3 files changed, 92 insertions(+), 49 deletions(-) diff --git a/server/src/app/routes/dow.ts b/server/src/app/routes/dow.ts index 6034d99..8ace527 100644 --- a/server/src/app/routes/dow.ts +++ b/server/src/app/routes/dow.ts @@ -7,6 +7,7 @@ import { TYPES } from '../../lib/dow/constants' import { ALIGN } from '../../lib/dow/constants' import { DowWidget } from '../../lib/dow/constants' import { rectangleWithTitle } from '../../lib/dow/widgets/rectangleWithTitle' +import { text } from '../../lib/dow/primitives/text' const weekdaysInCs = [ 'Pondeli', @@ -68,26 +69,24 @@ export const dowRoutes = router((router, ctx) => { } const widgets: DowWidget[] = [ - { + text({ x: WIDTH / 2, y: 30, - t: TYPES.TEXT, - c: `${hours}:${minutes}`, - va: ALIGN.START, - ha: ALIGN.CENTER, - f: 2, - }, - { + text: `${hours}:${minutes}`, + verticalAlign: ALIGN.START, + horizontalAlign: ALIGN.CENTER, + font: 2, + }), + text({ x: WIDTH / 2, y: 140, - c: `${ + text: `${ Math.round((weather.now?.temperature as number) ?? 0) ?? '-' } C ${summary}`, - t: TYPES.TEXT, - va: ALIGN.START, - ha: ALIGN.CENTER, - f: 1, - }, + verticalAlign: ALIGN.START, + horizontalAlign: ALIGN.CENTER, + font: 1, + }), ] // #region CALENDAR @@ -100,40 +99,28 @@ export const dowRoutes = router((router, ctx) => { const calendarEventsY = calendarY + 40 - widgets.push({ - x: Math.round(calendarX + calendarW / 2), - y: calendarY + 15, - c: `${dayOfWeek} ${day}.${month}`, - t: TYPES.TEXT, - va: ALIGN.CENTER, - ha: ALIGN.CENTER, - f: 0, - }) - - widgets.push({ - x: calendarX, - y: calendarY + 30, - x2: calendarX + calendarW, - y2: calendarY + 30, - t: TYPES.LINE, - }) - - widgets.push({ - x: calendarX, - y: calendarY, - x2: calendarW, - y2: calendarH, - t: TYPES.RECT, - }) + widgets.push( + ...rectangleWithTitle({ + x: calendarX, + y: calendarY, + width: calendarW, + height: calendarH, + title: `${dayOfWeek} ${day}.${month}`, + titleHeight: 30, + titleFont: 0, + }), + ) if (events.length === 0) { - widgets.push({ - x: calendarX, - y: calendarEventsY, - c: 'Zadne udalosti', - t: TYPES.TEXT, - f: 3, - }) + widgets.push( + text({ + x: calendarX + calendarW / 2, + y: calendarEventsY, + text: 'Zadne udalosti', + horizontalAlign: ALIGN.CENTER, + font: 3, + }), + ) } for (const [i, e] of events.entries()) { @@ -183,10 +170,40 @@ export const dowRoutes = router((router, ctx) => { const minTemp = Math.min(...next12Hours.map(([, h]) => h.temperature as number)) - 5 + const minTempIndex = Object.entries(weather.hours).reduce( + (acc, [i, h]) => { + if (typeof h.temperature !== 'number') { + return acc + } + + if (!acc || h.temperature < acc.temp) { + return { temp: h.temperature, index: i } + } + + return acc + }, + {} as { temp: number; index: string } | undefined, + )?.index + const maxTemp = Math.max( ...next12Hours.map(([, h]) => h.temperature as number), ) + const maxTempIndex = Object.entries(weather.hours).reduce( + (acc, [i, h]) => { + if (typeof h.temperature !== 'number') { + return acc + } + + if (!acc || h.temperature > acc.temp) { + return { temp: h.temperature, index: i } + } + + return acc + }, + {} as { temp: number; index: string } | undefined, + )?.index + const tempRange = maxTemp - minTemp const tempY = 250 @@ -231,7 +248,7 @@ export const dowRoutes = router((router, ctx) => { t: TYPES.RECT_FILL, }) - if (temperature === maxTemp || temperature === minTemp + 5) { + if (offset === minTempIndex || offset === maxTempIndex) { widgets.push({ x: x + 10, y: y, @@ -264,6 +281,21 @@ export const dowRoutes = router((router, ctx) => { ...next12Hours.map(([, h]) => h.precipitationAmount as number), ) + const maxPreIndex = Object.entries(weather.hours).reduce( + (acc, [i, h]) => { + if (typeof h.precipitationAmount !== 'number') { + return acc + } + + if (!acc || h.precipitationAmount > acc.pre) { + return { pre: h.precipitationAmount, index: i } + } + + return acc + }, + {} as { pre: number; index: string } | undefined, + )?.index + const displayedMaxPre = Math.max(maxPre, 1) const preRange = displayedMaxPre - minPre @@ -307,7 +339,7 @@ export const dowRoutes = router((router, ctx) => { t: TYPES.RECT_FILL, }) - if (pre === maxPre && maxPre > 0.01) { + if (offset === maxPreIndex && maxPre > 0.01) { widgets.push({ x: x + 10, y: y, diff --git a/server/static/app.css b/server/static/app.css index ba1f525..b873fe9 100644 --- a/server/static/app.css +++ b/server/static/app.css @@ -11,4 +11,9 @@ body { display: block; margin: 1rem auto; background: #fff; + image-rendering: optimizeSpeed; + image-rendering: -webkit-optimize-contrast; + image-rendering: -o-crisp-edges; + image-rendering: optimize-contrast; + -ms-interpolation-mode: nearest-neighbor; } diff --git a/server/static/dow-emulator.js b/server/static/dow-emulator.js index 442aaf5..2cc5cd5 100644 --- a/server/static/dow-emulator.js +++ b/server/static/dow-emulator.js @@ -34,11 +34,11 @@ function render(data) { throw new Error('Canvas 2D context is not available') } - ctx.imageSmoothingEnabled = false ctx.clearRect(0, 0, $canvas.width * 2, $canvas.height * 2) ctx.textBaseline = 'alphabetic' ctx.fillStyle = '#222' ctx.strokeStyle = '#222' + ctx.imageSmoothingEnabled = false for (const item of data) { switch (item.t) { @@ -92,9 +92,11 @@ function render(data) { const x2 = item.x2 const y2 = item.y2 + ctx.translate(0.5, 0.5) ctx.moveTo(x, y) ctx.lineTo(x2, y2) ctx.stroke() + ctx.resetTransform() break } @@ -104,9 +106,11 @@ function render(data) { const y = item.y const radius = item.r + ctx.translate(0.5, 0.5) ctx.beginPath() ctx.arc(x, y, radius, 0, 2 * Math.PI) ctx.stroke() + ctx.resetTransform() break } @@ -129,7 +133,9 @@ function render(data) { const w = item.x2 const h = item.y2 + ctx.translate(0.5, 0.5) ctx.strokeRect(x, y, w, h) + ctx.resetTransform() break }