From 9754bd2390a5069f18d1d63e3b3f82fc5e3ff34c Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 7 Feb 2025 23:29:19 +0000 Subject: [PATCH 01/23] fix: requirements.txt to reduce vulnerabilities The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-FONTTOOLS-6133203 From 96298dbf5279dbe1b4780290c8e304b3c1cf2288 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sat, 8 Feb 2025 12:52:33 +0000 Subject: [PATCH 02/23] dead code --- index.html | 134 ---------------------------------------- src/bitbot.py | 4 -- tests/images/intro0.png | Bin 0 -> 21861 bytes tests/images/intro1.png | Bin 0 -> 22020 bytes tests/images/intro2.png | Bin 0 -> 21949 bytes 5 files changed, 138 deletions(-) delete mode 100644 index.html create mode 100644 tests/images/intro0.png create mode 100644 tests/images/intro1.png create mode 100644 tests/images/intro2.png diff --git a/index.html b/index.html deleted file mode 100644 index 6e7fdfe8..00000000 --- a/index.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - 🤖 Bitbot - - - - - - - - - - - - - - - -

🤖 BitBot Config

-
-

🖼️ Last refresh

- -
-
-

⚙️ Application Config

-
-

Edit 'config.ini' to set the exchange, currency, screen refresh, overlay and layout options

- -
-
-
-
-

📸 Picture Mode

-
-
-

- - -

-

- - -

- - -
-
-
-

📈 Chart Styles

-
-

These files manage the colours and layout of the chart plot, they are matplolib style files and follow the example defined here

- -
-
-

🌳 Logs

-
-

Check here if something isn't working!

- -
- - - \ No newline at end of file diff --git a/src/bitbot.py b/src/bitbot.py index 5f799178..df389607 100644 --- a/src/bitbot.py +++ b/src/bitbot.py @@ -15,10 +15,6 @@ class BitBot(): - def __init__(self, config, display): - self.config = config - self.display = display - def __init__(self, config, files): self.config = config self.files = files diff --git a/tests/images/intro0.png b/tests/images/intro0.png new file mode 100644 index 0000000000000000000000000000000000000000..5a688aba2c7b98976838026b6c93c0f6887c6ad3 GIT binary patch literal 21861 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 D2RjgA literal 0 HcmV?d00001 diff --git a/tests/images/intro2.png b/tests/images/intro2.png new file mode 100644 index 0000000000000000000000000000000000000000..da0e7a1329c500bf267c596b55cbe61333c0c3a0 GIT binary patch literal 21949 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 literal 0 HcmV?d00001 From 599987f2ffde769d7d32cd94aa61fcaec5b9f47a Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 11:50:16 +0000 Subject: [PATCH 03/23] staged container build, saves 200meg odd --- bitbot.dockerfile | 46 ++++++++++++++++++++++++++++------------------ test.dockerfile | 45 --------------------------------------------- 2 files changed, 28 insertions(+), 63 deletions(-) delete mode 100644 test.dockerfile diff --git a/bitbot.dockerfile b/bitbot.dockerfile index 9a6e6b81..7a70d1ac 100644 --- a/bitbot.dockerfile +++ b/bitbot.dockerfile @@ -1,35 +1,45 @@ -FROM python:3.11-slim-bookworm +# Stage 1: Build stage +FROM python:3.11-slim-bookworm AS builder -# avoid bytecode baggage +# Avoid bytecode baggage ENV PYTHONDONTWRITEBYTECODE=1 -# install OS reqs -RUN apt-get update -y && \ - apt-get install -y \ - --no-install-recommends \ - libopenblas-dev libopenjp2-7 libtiff6 libxcb1 libfreetype6-dev \ - && rm -rf /var/lib/apt/lists/* - -# venv to keep python happy +# Create a virtual environment RUN python3 -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" -# update pip +# Update pip RUN python3 -m pip install --upgrade pip --no-cache-dir -# download python reqs +# Copy and install Python dependencies COPY requirements.txt . -RUN python3 -m pip download \ - -r requirements.txt \ - --extra-index-url https://www.piwheels.org/simple -# install python reqs RUN python3 -m pip install -v \ --prefer-binary \ -r requirements.txt \ - --extra-index-url https://www.piwheels.org/simple + --extra-index-url https://www.piwheels.org/simple \ + --no-cache-dir -# app code +# Stage 2: Final stage +FROM python:3.11-slim-bookworm + +# Avoid bytecode baggage +ENV PYTHONDONTWRITEBYTECODE=1 + +# Install only the necessary runtime dependencies +RUN apt-get update -y && \ + apt-get install -y \ + --no-install-recommends \ + libopenblas-dev libopenjp2-7 libtiff6 libxcb1 libfreetype6-dev \ + && rm -rf /var/lib/apt/lists/* + +# Copy the virtual environment from the builder stage +COPY --from=builder /opt/venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +# Copy only the necessary application code WORKDIR /code COPY . . + +# Set the default command CMD ["python", "run.py"] \ No newline at end of file diff --git a/test.dockerfile b/test.dockerfile deleted file mode 100644 index 7a70d1ac..00000000 --- a/test.dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -# Stage 1: Build stage -FROM python:3.11-slim-bookworm AS builder - -# Avoid bytecode baggage -ENV PYTHONDONTWRITEBYTECODE=1 - -# Create a virtual environment -RUN python3 -m venv /opt/venv -ENV PATH="/opt/venv/bin:$PATH" - -# Update pip -RUN python3 -m pip install --upgrade pip --no-cache-dir - -# Copy and install Python dependencies -COPY requirements.txt . - -RUN python3 -m pip install -v \ - --prefer-binary \ - -r requirements.txt \ - --extra-index-url https://www.piwheels.org/simple \ - --no-cache-dir - -# Stage 2: Final stage -FROM python:3.11-slim-bookworm - -# Avoid bytecode baggage -ENV PYTHONDONTWRITEBYTECODE=1 - -# Install only the necessary runtime dependencies -RUN apt-get update -y && \ - apt-get install -y \ - --no-install-recommends \ - libopenblas-dev libopenjp2-7 libtiff6 libxcb1 libfreetype6-dev \ - && rm -rf /var/lib/apt/lists/* - -# Copy the virtual environment from the builder stage -COPY --from=builder /opt/venv /opt/venv -ENV PATH="/opt/venv/bin:$PATH" - -# Copy only the necessary application code -WORKDIR /code -COPY . . - -# Set the default command -CMD ["python", "run.py"] \ No newline at end of file From a27e537f9a859943766a79ec63ba3729952c3506 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 13:17:12 +0000 Subject: [PATCH 04/23] hack in whitby tides --- src/configuration/bitbot_config.py | 3 +- src/drawing/tide_times/tidal_graph.py | 64 +++++++++++++------------- tests/images/TidalGraph.png | Bin 0 -> 34346 bytes tests/test_tides.py | 14 ++++++ 4 files changed, 47 insertions(+), 34 deletions(-) create mode 100644 tests/images/TidalGraph.png create mode 100644 tests/test_tides.py diff --git a/src/configuration/bitbot_config.py b/src/configuration/bitbot_config.py index 655b75f9..740884bc 100644 --- a/src/configuration/bitbot_config.py +++ b/src/configuration/bitbot_config.py @@ -220,9 +220,10 @@ def tide_times_enabled(self): def tide_location_id(self): return self.config['tide_times']["location_id"] - # timed meaages + # timed messages def today_has_special_message(self, datetime): return self.special_message(datetime) != None def special_message(self, datetime): return self.config.get('special_messages', datetime.strftime("%YYYY-%MM-%DD"), fallback=None) + diff --git a/src/drawing/tide_times/tidal_graph.py b/src/drawing/tide_times/tidal_graph.py index fe9433f7..f66ffc4d 100644 --- a/src/drawing/tide_times/tidal_graph.py +++ b/src/drawing/tide_times/tidal_graph.py @@ -3,36 +3,35 @@ from datetime import datetime from PIL import Image -def get_noaa_tide_data(station_id): -# date = datetime.date.today().strftime("%Y-%m-%d") +def get_tide_data(station_id): -# # Using NOAA Tides & Currents API -# # station_id = '9414290' # Example station ID for San Francisco -# api_url = f"https://environment.data.gov.uk/flood-monitoring/id/stations/{station_id}/readings?_sorted&date={date}" -# response = requests.get(api_url) -# response.raise_for_status() # Raise an exception for bad status codes -# data = response.json() + base_url = "https://easytide.admiralty.co.uk/Home/GetPredictionData" - url = f'https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?product=predictions&application=NOS.COOPS.TAC.WL&begin_date={datetime.now().strftime("%Y%m%d")}&range=168&datum=MLLW&station={station_id}&time_zone=lst_ldt&units=metric&interval=h&format=json' - try: - response = requests.get(url) - response.raise_for_status() - data = response.json() - - tide_data = [] - for prediction in data['predictions']: - tide_data.append({ - 'date': prediction['t'], - 'height': float(prediction['v']) - }) - return tide_data - except Exception as e: - print(f"Error fetching tide data: {e}") - return [] + params = { + 'stationId': station_id, + } + + response = requests.get(base_url, params=params) + if response.status_code != 200: + raise Exception(f"Failed to fetch data: HTTP {response.status_code}") + + data = response.json() + + if not data["tidalEventList"]: + raise Exception("No tide data found in the response") + + tide_data = [] + for entry in data["tidalEventList"]: + # Convert timestamp to a readable format + date = datetime.strptime(entry['dateTime'], "%Y-%m-%dT%H:%M:%S").strftime('%Y-%m-%d %H:%M') + height = entry['height'] + tide_data.append({'date': date, 'height': height}) + + return tide_data def render_tide_chart(location_id, img_buf): - tide_data = get_noaa_tide_data(location_id) + tide_data = get_tide_data(location_id) from datetime import datetime dates = [datetime.strptime(d['date'], '%Y-%m-%d %H:%M') for d in tide_data] @@ -62,14 +61,13 @@ def render_tide_chart(location_id, img_buf): for date, height in zip(dates, heights): day = date.strftime('%Y-%m-%d') - if day_counts[day] == 24: # Only consider days with 24 data points - if day not in daily_min_max: - daily_min_max[day] = {'min': (date, height), 'max': (date, height)} - else: - if height < daily_min_max[day]['min'][1]: - daily_min_max[day]['min'] = (date, height) - if height > daily_min_max[day]['max'][1]: - daily_min_max[day]['max'] = (date, height) + if day not in daily_min_max: + daily_min_max[day] = {'min': (date, height), 'max': (date, height)} + else: + if height < daily_min_max[day]['min'][1]: + daily_min_max[day]['min'] = (date, height) + if height > daily_min_max[day]['max'][1]: + daily_min_max[day]['max'] = (date, height) # Add labels for min and max for day, values in daily_min_max.items(): diff --git a/tests/images/TidalGraph.png b/tests/images/TidalGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..58298f37b4e75057742d77dbc2bb8c07ca9e7bf9 GIT binary patch literal 34346 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 D?kcBT literal 0 HcmV?d00001 diff --git a/tests/test_tides.py b/tests/test_tides.py new file mode 100644 index 00000000..3bb98634 --- /dev/null +++ b/tests/test_tides.py @@ -0,0 +1,14 @@ +import io +import unittest +from src.drawing.tide_times import tidal_graph +from PIL import Image, ImageDraw + +class TestTidalGraph(unittest.TestCase): + + def test_data_fetch_and_render(self): + + with io.BytesIO() as img_buf: + tidal_graph.render_tide_chart("0184", img_buf) + + image = Image.open(img_buf) + image.save(f'tests/images/TidalGraph.png') From d8235ab5d7c091235c749295f0aeff7ed4c74021 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 13:18:18 +0000 Subject: [PATCH 05/23] store tide data for better testing later --- tests/data/whitby_tides.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/data/whitby_tides.json diff --git a/tests/data/whitby_tides.json b/tests/data/whitby_tides.json new file mode 100644 index 00000000..11570c9e --- /dev/null +++ b/tests/data/whitby_tides.json @@ -0,0 +1 @@ +{"tidalEventList":[{"eventType":1,"dateTime":"2025-02-08T06:18:00","height":2.250927077638894,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-08T00:00:00"},{"eventType":0,"dateTime":"2025-02-08T12:33:00","height":4.50918972731683,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-08T00:00:00"},{"eventType":1,"dateTime":"2025-02-08T19:01:00","height":2.0853662323155526,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-08T00:00:00"},{"eventType":0,"dateTime":"2025-02-09T01:15:00","height":4.6573249943865145,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-09T00:00:00"},{"eventType":1,"dateTime":"2025-02-09T07:41:00","height":2.1723152205092107,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-09T00:00:00"},{"eventType":0,"dateTime":"2025-02-09T13:46:00","height":4.730628059134607,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-09T00:00:00"},{"eventType":1,"dateTime":"2025-02-09T20:15:00","height":1.763520214165164,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-09T00:00:00"},{"eventType":0,"dateTime":"2025-02-10T02:24:00","height":4.858152287952238,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-10T00:00:00"},{"eventType":1,"dateTime":"2025-02-10T08:41:00","height":1.9814674061220303,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-10T00:00:00"},{"eventType":0,"dateTime":"2025-02-10T14:42:00","height":5.004950966474468,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-10T00:00:00"},{"eventType":1,"dateTime":"2025-02-10T21:11:00","height":1.4278918078855554,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-10T00:00:00"},{"eventType":0,"dateTime":"2025-02-11T03:16:00","height":5.059063440048395,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-11T00:00:00"},{"eventType":1,"dateTime":"2025-02-11T09:28:00","height":1.779085496410402,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-11T00:00:00"},{"eventType":0,"dateTime":"2025-02-11T15:27:00","height":5.247440375380359,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-11T00:00:00"},{"eventType":1,"dateTime":"2025-02-11T21:56:00","height":1.16184957015816,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-11T00:00:00"},{"eventType":0,"dateTime":"2025-02-12T03:59:00","height":5.200586351290798,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-12T00:00:00"},{"eventType":1,"dateTime":"2025-02-12T10:07:00","height":1.6071006495793392,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-12T00:00:00"},{"eventType":0,"dateTime":"2025-02-12T16:07:00","height":5.425011191464042,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-12T00:00:00"},{"eventType":1,"dateTime":"2025-02-12T22:36:00","height":0.9928605605025923,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-12T00:00:00"},{"eventType":0,"dateTime":"2025-02-13T04:36:00","height":5.270786648463542,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-13T00:00:00"},{"eventType":1,"dateTime":"2025-02-13T10:42:00","height":1.484266893296131,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-13T00:00:00"},{"eventType":0,"dateTime":"2025-02-13T16:43:00","height":5.528284041729102,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-13T00:00:00"},{"eventType":1,"dateTime":"2025-02-13T23:11:00","height":0.9233890962693343,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-13T00:00:00"},{"eventType":0,"dateTime":"2025-02-14T05:10:00","height":5.275528669494031,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-14T00:00:00"},{"eventType":1,"dateTime":"2025-02-14T11:14:00","height":1.4205558364075426,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-14T00:00:00"},{"eventType":0,"dateTime":"2025-02-14T17:16:00","height":5.557999002562121,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-14T00:00:00"},{"eventType":1,"dateTime":"2025-02-14T23:42:00","height":0.944651202343493,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-14T00:00:00"},{"eventType":0,"dateTime":"2025-02-15T05:42:00","height":5.226291012611799,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-15T00:00:00"},{"eventType":1,"dateTime":"2025-02-15T11:43:00","height":1.419590908938737,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-15T00:00:00"},{"eventType":0,"dateTime":"2025-02-15T17:47:00","height":5.519299591512786,"isApproximateTime":null,"isApproximateHeight":null,"date":"2025-02-15T00:00:00"}],"tidalHeightOccurrenceList":[{"dateTime":"2025-02-08T23:00:00Z","height":3.916645},{"dateTime":"2025-02-08T23:30:00Z","height":4.185804},{"dateTime":"2025-02-09T00:00:00Z","height":4.404631},{"dateTime":"2025-02-09T00:30:00Z","height":4.562275},{"dateTime":"2025-02-09T01:00:00Z","height":4.645841},{"dateTime":"2025-02-09T01:30:00Z","height":4.648231},{"dateTime":"2025-02-09T02:00:00Z","height":4.570677},{"dateTime":"2025-02-09T02:30:00Z","height":4.422385},{"dateTime":"2025-02-09T03:00:00Z","height":4.21686},{"dateTime":"2025-02-09T03:30:00Z","height":3.969473},{"dateTime":"2025-02-09T04:00:00Z","height":3.695627},{"dateTime":"2025-02-09T04:30:00Z","height":3.40792},{"dateTime":"2025-02-09T05:00:00Z","height":3.116596},{"dateTime":"2025-02-09T05:30:00Z","height":2.835423},{"dateTime":"2025-02-09T06:00:00Z","height":2.584642},{"dateTime":"2025-02-09T06:30:00Z","height":2.384243},{"dateTime":"2025-02-09T07:00:00Z","height":2.246322},{"dateTime":"2025-02-09T07:30:00Z","height":2.178079},{"dateTime":"2025-02-09T08:00:00Z","height":2.189037},{"dateTime":"2025-02-09T08:30:00Z","height":2.287581},{"dateTime":"2025-02-09T09:00:00Z","height":2.469514},{"dateTime":"2025-02-09T09:30:00Z","height":2.716126},{"dateTime":"2025-02-09T10:00:00Z","height":3.005216},{"dateTime":"2025-02-09T10:30:00Z","height":3.319045},{"dateTime":"2025-02-09T11:00:00Z","height":3.640694},{"dateTime":"2025-02-09T11:30:00Z","height":3.949819},{"dateTime":"2025-02-09T12:00:00Z","height":4.22665},{"dateTime":"2025-02-09T12:30:00Z","height":4.4562},{"dateTime":"2025-02-09T13:00:00Z","height":4.624896},{"dateTime":"2025-02-09T13:30:00Z","height":4.717224},{"dateTime":"2025-02-09T14:00:00Z","height":4.72096},{"dateTime":"2025-02-09T14:30:00Z","height":4.634716},{"dateTime":"2025-02-09T15:00:00Z","height":4.467853},{"dateTime":"2025-02-09T15:30:00Z","height":4.234976},{"dateTime":"2025-02-09T16:00:00Z","height":3.952256},{"dateTime":"2025-02-09T16:30:00Z","height":3.63539},{"dateTime":"2025-02-09T17:00:00Z","height":3.297398},{"dateTime":"2025-02-09T17:30:00Z","height":2.95044},{"dateTime":"2025-02-09T18:00:00Z","height":2.612124},{"dateTime":"2025-02-09T18:30:00Z","height":2.3066},{"dateTime":"2025-02-09T19:00:00Z","height":2.056223},{"dateTime":"2025-02-09T19:30:00Z","height":1.875637},{"dateTime":"2025-02-09T20:00:00Z","height":1.777164},{"dateTime":"2025-02-09T20:30:00Z","height":1.776093},{"dateTime":"2025-02-09T21:00:00Z","height":1.882673},{"dateTime":"2025-02-09T21:30:00Z","height":2.090288},{"dateTime":"2025-02-09T22:00:00Z","height":2.37758},{"dateTime":"2025-02-09T22:30:00Z","height":2.720788},{"dateTime":"2025-02-09T23:00:00Z","height":3.098193},{"dateTime":"2025-02-09T23:30:00Z","height":3.485305},{"dateTime":"2025-02-10T00:00:00Z","height":3.855635},{"dateTime":"2025-02-10T00:30:00Z","height":4.188873},{"dateTime":"2025-02-10T01:00:00Z","height":4.471927},{"dateTime":"2025-02-10T01:30:00Z","height":4.689947},{"dateTime":"2025-02-10T02:00:00Z","height":4.82313},{"dateTime":"2025-02-10T02:30:00Z","height":4.856639},{"dateTime":"2025-02-10T03:00:00Z","height":4.790144},{"dateTime":"2025-02-10T03:30:00Z","height":4.635666},{"dateTime":"2025-02-10T04:00:00Z","height":4.410172},{"dateTime":"2025-02-10T04:30:00Z","height":4.131722},{"dateTime":"2025-02-10T05:00:00Z","height":3.817236},{"dateTime":"2025-02-10T05:30:00Z","height":3.480236},{"dateTime":"2025-02-10T06:00:00Z","height":3.13385},{"dateTime":"2025-02-10T06:30:00Z","height":2.79753},{"dateTime":"2025-02-10T07:00:00Z","height":2.496298},{"dateTime":"2025-02-10T07:30:00Z","height":2.25152},{"dateTime":"2025-02-10T08:00:00Z","height":2.077567},{"dateTime":"2025-02-10T08:30:00Z","height":1.989033},{"dateTime":"2025-02-10T09:00:00Z","height":2.002977},{"dateTime":"2025-02-10T09:30:00Z","height":2.127473},{"dateTime":"2025-02-10T10:00:00Z","height":2.351999},{"dateTime":"2025-02-10T10:30:00Z","height":2.653826},{"dateTime":"2025-02-10T11:00:00Z","height":3.009054},{"dateTime":"2025-02-10T11:30:00Z","height":3.392711},{"dateTime":"2025-02-10T12:00:00Z","height":3.775395},{"dateTime":"2025-02-10T12:30:00Z","height":4.13041},{"dateTime":"2025-02-10T13:00:00Z","height":4.44282},{"dateTime":"2025-02-10T13:30:00Z","height":4.703554},{"dateTime":"2025-02-10T14:00:00Z","height":4.895762},{"dateTime":"2025-02-10T14:30:00Z","height":4.995301},{"dateTime":"2025-02-10T15:00:00Z","height":4.985936},{"dateTime":"2025-02-10T15:30:00Z","height":4.86869},{"dateTime":"2025-02-10T16:00:00Z","height":4.656865},{"dateTime":"2025-02-10T16:30:00Z","height":4.36836},{"dateTime":"2025-02-10T17:00:00Z","height":4.022693},{"dateTime":"2025-02-10T17:30:00Z","height":3.638112},{"dateTime":"2025-02-10T18:00:00Z","height":3.229167},{"dateTime":"2025-02-10T18:30:00Z","height":2.811358},{"dateTime":"2025-02-10T19:00:00Z","height":2.40807},{"dateTime":"2025-02-10T19:30:00Z","height":2.047507},{"dateTime":"2025-02-10T20:00:00Z","height":1.75306},{"dateTime":"2025-02-10T20:30:00Z","height":1.542703},{"dateTime":"2025-02-10T21:00:00Z","height":1.436488},{"dateTime":"2025-02-10T21:30:00Z","height":1.454511},{"dateTime":"2025-02-10T22:00:00Z","height":1.603301},{"dateTime":"2025-02-10T22:30:00Z","height":1.869819},{"dateTime":"2025-02-10T23:00:00Z","height":2.230223},{"dateTime":"2025-02-10T23:30:00Z","height":2.657026},{"dateTime":"2025-02-11T00:00:00Z","height":3.116361},{"dateTime":"2025-02-11T00:30:00Z","height":3.570096},{"dateTime":"2025-02-11T01:00:00Z","height":3.989617},{"dateTime":"2025-02-11T01:30:00Z","height":4.362221},{"dateTime":"2025-02-11T02:00:00Z","height":4.677421},{"dateTime":"2025-02-11T02:30:00Z","height":4.912627},{"dateTime":"2025-02-11T03:00:00Z","height":5.04041},{"dateTime":"2025-02-11T03:30:00Z","height":5.047109},{"dateTime":"2025-02-11T04:00:00Z","height":4.938651},{"dateTime":"2025-02-11T04:30:00Z","height":4.732241},{"dateTime":"2025-02-11T05:00:00Z","height":4.449186},{"dateTime":"2025-02-11T05:30:00Z","height":4.112058},{"dateTime":"2025-02-11T06:00:00Z","height":3.740195},{"dateTime":"2025-02-11T06:30:00Z","height":3.34784},{"dateTime":"2025-02-11T07:00:00Z","height":2.951386},{"dateTime":"2025-02-11T07:30:00Z","height":2.5761},{"dateTime":"2025-02-11T08:00:00Z","height":2.250409},{"dateTime":"2025-02-11T08:30:00Z","height":1.996583},{"dateTime":"2025-02-11T09:00:00Z","height":1.832776},{"dateTime":"2025-02-11T09:30:00Z","height":1.779357},{"dateTime":"2025-02-11T10:00:00Z","height":1.852867},{"dateTime":"2025-02-11T10:30:00Z","height":2.05306},{"dateTime":"2025-02-11T11:00:00Z","height":2.361905},{"dateTime":"2025-02-11T11:30:00Z","height":2.752959},{"dateTime":"2025-02-11T12:00:00Z","height":3.194082},{"dateTime":"2025-02-11T12:30:00Z","height":3.645204},{"dateTime":"2025-02-11T13:00:00Z","height":4.067942},{"dateTime":"2025-02-11T13:30:00Z","height":4.441997},{"dateTime":"2025-02-11T14:00:00Z","height":4.763241},{"dateTime":"2025-02-11T14:30:00Z","height":5.02215},{"dateTime":"2025-02-11T15:00:00Z","height":5.192696},{"dateTime":"2025-02-11T15:30:00Z","height":5.247205},{"dateTime":"2025-02-11T16:00:00Z","height":5.175469},{"dateTime":"2025-02-11T16:30:00Z","height":4.986029},{"dateTime":"2025-02-11T17:00:00Z","height":4.696961},{"dateTime":"2025-02-11T17:30:00Z","height":4.330944},{"dateTime":"2025-02-11T18:00:00Z","height":3.91202},{"dateTime":"2025-02-11T18:30:00Z","height":3.459476},{"dateTime":"2025-02-11T19:00:00Z","height":2.987861},{"dateTime":"2025-02-11T19:30:00Z","height":2.516825},{"dateTime":"2025-02-11T20:00:00Z","height":2.076074},{"dateTime":"2025-02-11T20:30:00Z","height":1.696682},{"dateTime":"2025-02-11T21:00:00Z","height":1.403069},{"dateTime":"2025-02-11T21:30:00Z","height":1.217291},{"dateTime":"2025-02-11T22:00:00Z","height":1.162925},{"dateTime":"2025-02-11T22:30:00Z","height":1.255717},{"dateTime":"2025-02-11T23:00:00Z","height":1.492775},{"dateTime":"2025-02-11T23:30:00Z","height":1.854879},{"dateTime":"2025-02-12T00:00:00Z","height":2.312951},{"dateTime":"2025-02-12T00:30:00Z","height":2.826648},{"dateTime":"2025-02-12T01:00:00Z","height":3.346474},{"dateTime":"2025-02-12T01:30:00Z","height":3.831488},{"dateTime":"2025-02-12T02:00:00Z","height":4.26437},{"dateTime":"2025-02-12T02:30:00Z","height":4.639998},{"dateTime":"2025-02-12T03:00:00Z","height":4.941285},{"dateTime":"2025-02-12T03:30:00Z","height":5.136496},{"dateTime":"2025-02-12T04:00:00Z","height":5.200514},{"dateTime":"2025-02-12T04:30:00Z","height":5.130329},{"dateTime":"2025-02-12T05:00:00Z","height":4.940622},{"dateTime":"2025-02-12T05:30:00Z","height":4.654385},{"dateTime":"2025-02-12T06:00:00Z","height":4.298944},{"dateTime":"2025-02-12T06:30:00Z","height":3.900402},{"dateTime":"2025-02-12T07:00:00Z","height":3.476757},{"dateTime":"2025-02-12T07:30:00Z","height":3.04179},{"dateTime":"2025-02-12T08:00:00Z","height":2.61727},{"dateTime":"2025-02-12T08:30:00Z","height":2.23485},{"dateTime":"2025-02-12T09:00:00Z","height":1.92481},{"dateTime":"2025-02-12T09:30:00Z","height":1.710017},{"dateTime":"2025-02-12T10:00:00Z","height":1.611236},{"dateTime":"2025-02-12T10:30:00Z","height":1.647735},{"dateTime":"2025-02-12T11:00:00Z","height":1.826699},{"dateTime":"2025-02-12T11:30:00Z","height":2.136713},{"dateTime":"2025-02-12T12:00:00Z","height":2.552635},{"dateTime":"2025-02-12T12:30:00Z","height":3.038908},{"dateTime":"2025-02-12T13:00:00Z","height":3.547795},{"dateTime":"2025-02-12T13:30:00Z","height":4.028984},{"dateTime":"2025-02-12T14:00:00Z","height":4.451726},{"dateTime":"2025-02-12T14:30:00Z","height":4.811598},{"dateTime":"2025-02-12T15:00:00Z","height":5.108093},{"dateTime":"2025-02-12T15:30:00Z","height":5.321733},{"dateTime":"2025-02-12T16:00:00Z","height":5.420922},{"dateTime":"2025-02-12T16:30:00Z","height":5.385852},{"dateTime":"2025-02-12T17:00:00Z","height":5.218269},{"dateTime":"2025-02-12T17:30:00Z","height":4.934187},{"dateTime":"2025-02-12T18:00:00Z","height":4.557319},{"dateTime":"2025-02-12T18:30:00Z","height":4.11595},{"dateTime":"2025-02-12T19:00:00Z","height":3.635074},{"dateTime":"2025-02-12T19:30:00Z","height":3.130761},{"dateTime":"2025-02-12T20:00:00Z","height":2.618574},{"dateTime":"2025-02-12T20:30:00Z","height":2.12573},{"dateTime":"2025-02-12T21:00:00Z","height":1.688176},{"dateTime":"2025-02-12T21:30:00Z","height":1.337798},{"dateTime":"2025-02-12T22:00:00Z","height":1.099268},{"dateTime":"2025-02-12T22:30:00Z","height":0.99557},{"dateTime":"2025-02-12T23:00:00Z","height":1.045485},{"dateTime":"2025-02-12T23:30:00Z","height":1.253304},{"dateTime":"2025-02-13T00:00:00Z","height":1.605684},{"dateTime":"2025-02-13T00:30:00Z","height":2.075385},{"dateTime":"2025-02-13T01:00:00Z","height":2.620353},{"dateTime":"2025-02-13T01:30:00Z","height":3.184525},{"dateTime":"2025-02-13T02:00:00Z","height":3.715564},{"dateTime":"2025-02-13T02:30:00Z","height":4.187116},{"dateTime":"2025-02-13T03:00:00Z","height":4.595242},{"dateTime":"2025-02-13T03:30:00Z","height":4.930825},{"dateTime":"2025-02-13T04:00:00Z","height":5.165338},{"dateTime":"2025-02-13T04:30:00Z","height":5.267649},{"dateTime":"2025-02-13T05:00:00Z","height":5.22614},{"dateTime":"2025-02-13T05:30:00Z","height":5.050913},{"dateTime":"2025-02-13T06:00:00Z","height":4.764492},{"dateTime":"2025-02-13T06:30:00Z","height":4.396677},{"dateTime":"2025-02-13T07:00:00Z","height":3.979223},{"dateTime":"2025-02-13T07:30:00Z","height":3.535709},{"dateTime":"2025-02-13T08:00:00Z","height":3.07973},{"dateTime":"2025-02-13T08:30:00Z","height":2.628179},{"dateTime":"2025-02-13T09:00:00Z","height":2.211477},{"dateTime":"2025-02-13T09:30:00Z","height":1.865727},{"dateTime":"2025-02-13T10:00:00Z","height":1.619983},{"dateTime":"2025-02-13T10:30:00Z","height":1.495726},{"dateTime":"2025-02-13T11:00:00Z","height":1.511069},{"dateTime":"2025-02-13T11:30:00Z","height":1.675811},{"dateTime":"2025-02-13T12:00:00Z","height":1.983533},{"dateTime":"2025-02-13T12:30:00Z","height":2.411912},{"dateTime":"2025-02-13T13:00:00Z","height":2.925269},{"dateTime":"2025-02-13T13:30:00Z","height":3.47313},{"dateTime":"2025-02-13T14:00:00Z","height":3.997753},{"dateTime":"2025-02-13T14:30:00Z","height":4.457571},{"dateTime":"2025-02-13T15:00:00Z","height":4.842366},{"dateTime":"2025-02-13T15:30:00Z","height":5.156649},{"dateTime":"2025-02-13T16:00:00Z","height":5.390425},{"dateTime":"2025-02-13T16:30:00Z","height":5.515104},{"dateTime":"2025-02-13T17:00:00Z","height":5.505734},{"dateTime":"2025-02-13T17:30:00Z","height":5.357577},{"dateTime":"2025-02-13T18:00:00Z","height":5.083133},{"dateTime":"2025-02-13T18:30:00Z","height":4.705009},{"dateTime":"2025-02-13T19:00:00Z","height":4.253072},{"dateTime":"2025-02-13T19:30:00Z","height":3.757084},{"dateTime":"2025-02-13T20:00:00Z","height":3.236836},{"dateTime":"2025-02-13T20:30:00Z","height":2.705785},{"dateTime":"2025-02-13T21:00:00Z","height":2.186551},{"dateTime":"2025-02-13T21:30:00Z","height":1.715845},{"dateTime":"2025-02-13T22:00:00Z","height":1.331941},{"dateTime":"2025-02-13T22:30:00Z","height":1.063799},{"dateTime":"2025-02-13T23:00:00Z","height":0.93318},{"dateTime":"2025-02-13T23:30:00Z","height":0.957303},{"dateTime":"2025-02-14T00:00:00Z","height":1.142843},{"dateTime":"2025-02-14T00:30:00Z","height":1.480485},{"dateTime":"2025-02-14T01:00:00Z","height":1.945671},{"dateTime":"2025-02-14T01:30:00Z","height":2.497936},{"dateTime":"2025-02-14T02:00:00Z","height":3.080584},{"dateTime":"2025-02-14T02:30:00Z","height":3.635272},{"dateTime":"2025-02-14T03:00:00Z","height":4.126637},{"dateTime":"2025-02-14T03:30:00Z","height":4.54732},{"dateTime":"2025-02-14T04:00:00Z","height":4.893714},{"dateTime":"2025-02-14T04:30:00Z","height":5.144017},{"dateTime":"2025-02-14T05:00:00Z","height":5.266717},{"dateTime":"2025-02-14T05:30:00Z","height":5.244201},{"dateTime":"2025-02-14T06:00:00Z","height":5.081393},{"dateTime":"2025-02-14T06:30:00Z","height":4.798646},{"dateTime":"2025-02-14T07:00:00Z","height":4.425803},{"dateTime":"2025-02-14T07:30:00Z","height":3.997786},{"dateTime":"2025-02-14T08:00:00Z","height":3.54384},{"dateTime":"2025-02-14T08:30:00Z","height":3.080312},{"dateTime":"2025-02-14T09:00:00Z","height":2.620638},{"dateTime":"2025-02-14T09:30:00Z","height":2.190947},{"dateTime":"2025-02-14T10:00:00Z","height":1.829},{"dateTime":"2025-02-14T10:30:00Z","height":1.569301},{"dateTime":"2025-02-14T11:00:00Z","height":1.435354},{"dateTime":"2025-02-14T11:30:00Z","height":1.443015},{"dateTime":"2025-02-14T12:00:00Z","height":1.600909},{"dateTime":"2025-02-14T12:30:00Z","height":1.904661},{"dateTime":"2025-02-14T13:00:00Z","height":2.334357},{"dateTime":"2025-02-14T13:30:00Z","height":2.855702},{"dateTime":"2025-02-14T14:00:00Z","height":3.419277},{"dateTime":"2025-02-14T14:30:00Z","height":3.965878},{"dateTime":"2025-02-14T15:00:00Z","height":4.447281},{"dateTime":"2025-02-14T15:30:00Z","height":4.845658},{"dateTime":"2025-02-14T16:00:00Z","height":5.165169},{"dateTime":"2025-02-14T16:30:00Z","height":5.403238},{"dateTime":"2025-02-14T17:00:00Z","height":5.537823},{"dateTime":"2025-02-14T17:30:00Z","height":5.543587},{"dateTime":"2025-02-14T18:00:00Z","height":5.411343},{"dateTime":"2025-02-14T18:30:00Z","height":5.149827},{"dateTime":"2025-02-14T19:00:00Z","height":4.779215},{"dateTime":"2025-02-14T19:30:00Z","height":4.328419},{"dateTime":"2025-02-14T20:00:00Z","height":3.829596},{"dateTime":"2025-02-14T20:30:00Z","height":3.306886},{"dateTime":"2025-02-14T21:00:00Z","height":2.774556},{"dateTime":"2025-02-14T21:30:00Z","height":2.25121},{"dateTime":"2025-02-14T22:00:00Z","height":1.770913},{"dateTime":"2025-02-14T22:30:00Z","height":1.37501},{"dateTime":"2025-02-14T23:00:00Z","height":1.096842},{"dateTime":"2025-02-14T23:30:00Z","height":0.957915},{"dateTime":"2025-02-15T00:00:00Z","height":0.972001},{"dateTime":"2025-02-15T00:30:00Z","height":1.144268},{"dateTime":"2025-02-15T01:00:00Z","height":1.466656},{"dateTime":"2025-02-15T01:30:00Z","height":1.916511},{"dateTime":"2025-02-15T02:00:00Z","height":2.456002},{"dateTime":"2025-02-15T02:30:00Z","height":3.031801},{"dateTime":"2025-02-15T03:00:00Z","height":3.585913},{"dateTime":"2025-02-15T03:30:00Z","height":4.077999},{"dateTime":"2025-02-15T04:00:00Z","height":4.495594},{"dateTime":"2025-02-15T04:30:00Z","height":4.836565},{"dateTime":"2025-02-15T05:00:00Z","height":5.085383},{"dateTime":"2025-02-15T05:30:00Z","height":5.213825},{"dateTime":"2025-02-15T06:00:00Z","height":5.201706},{"dateTime":"2025-02-15T06:30:00Z","height":5.049507},{"dateTime":"2025-02-15T07:00:00Z","height":4.774529},{"dateTime":"2025-02-15T07:30:00Z","height":4.40486},{"dateTime":"2025-02-15T08:00:00Z","height":3.975799},{"dateTime":"2025-02-15T08:30:00Z","height":3.520497},{"dateTime":"2025-02-15T09:00:00Z","height":3.059675},{"dateTime":"2025-02-15T09:30:00Z","height":2.606321},{"dateTime":"2025-02-15T10:00:00Z","height":2.182011},{"dateTime":"2025-02-15T10:30:00Z","height":1.822306},{"dateTime":"2025-02-15T11:00:00Z","height":1.564142},{"dateTime":"2025-02-15T11:30:00Z","height":1.433103},{"dateTime":"2025-02-15T12:00:00Z","height":1.443041},{"dateTime":"2025-02-15T12:30:00Z","height":1.599433},{"dateTime":"2025-02-15T13:00:00Z","height":1.897374},{"dateTime":"2025-02-15T13:30:00Z","height":2.318429},{"dateTime":"2025-02-15T14:00:00Z","height":2.830258},{"dateTime":"2025-02-15T14:30:00Z","height":3.386507},{"dateTime":"2025-02-15T15:00:00Z","height":3.931085},{"dateTime":"2025-02-15T15:30:00Z","height":4.414811},{"dateTime":"2025-02-15T16:00:00Z","height":4.814346},{"dateTime":"2025-02-15T16:30:00Z","height":5.130128},{"dateTime":"2025-02-15T17:00:00Z","height":5.36268},{"dateTime":"2025-02-15T17:30:00Z","height":5.496328},{"dateTime":"2025-02-15T18:00:00Z","height":5.508614},{"dateTime":"2025-02-15T18:30:00Z","height":5.388634},{"dateTime":"2025-02-15T19:00:00Z","height":5.142147},{"dateTime":"2025-02-15T19:30:00Z","height":4.786613},{"dateTime":"2025-02-15T20:00:00Z","height":4.348474},{"dateTime":"2025-02-15T20:30:00Z","height":3.859572},{"dateTime":"2025-02-15T21:00:00Z","height":3.34699},{"dateTime":"2025-02-15T21:30:00Z","height":2.827535},{"dateTime":"2025-02-15T22:00:00Z","height":2.317969},{"dateTime":"2025-02-15T22:30:00Z","height":1.848494},{"dateTime":"2025-02-15T23:00:00Z","height":1.459909},{"dateTime":"2025-02-15T23:30:00Z","height":1.188069}],"lunarPhaseList":[{"lunarPhaseType":3,"dateTime":"2025-02-12T13:53:00"}],"footerNote":""} \ No newline at end of file From 690664c539ac29def30b378c8e683a201b38fcfa Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 13:37:14 +0000 Subject: [PATCH 06/23] tidal graph rcparams --- src/drawing/tide_times/tidal_graph.py | 11 +++++++++++ tests/images/TidalGraph.png | Bin 34346 -> 5622 bytes 2 files changed, 11 insertions(+) diff --git a/src/drawing/tide_times/tidal_graph.py b/src/drawing/tide_times/tidal_graph.py index f66ffc4d..fb2bf547 100644 --- a/src/drawing/tide_times/tidal_graph.py +++ b/src/drawing/tide_times/tidal_graph.py @@ -2,6 +2,7 @@ import matplotlib.pyplot as plt from datetime import datetime from PIL import Image +import matplotlib as mpl def get_tide_data(station_id): @@ -37,6 +38,16 @@ def render_tide_chart(location_id, img_buf): dates = [datetime.strptime(d['date'], '%Y-%m-%d %H:%M') for d in tide_data] heights = [d['height'] for d in tide_data] + + mpl.rcParams["text.hinting_factor"] = "1" + mpl.rcParams["text.hinting"] = "native" + mpl.rcParams["text.antialiased"] = "False" + mpl.rcParams["patch.antialiased"] = "False" + mpl.rcParams["lines.antialiased"] = "False" + mpl.rcParams["font.family"] = "sans-serif" + mpl.rcParams["font.sans-serif"] = "basis33" + mpl.rcParams["font.size"] = "11" + plt.figure(figsize=(4, 3)) plt.plot(dates, heights) plt.title('Next 7 Days') diff --git a/tests/images/TidalGraph.png b/tests/images/TidalGraph.png index 58298f37b4e75057742d77dbc2bb8c07ca9e7bf9..e1c653a6ddb0bca9f0bf651b6d5a21682f7b8f74 100644 GIT binary patch literal 5622 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 D?kcBT From a04a73fdd49a236b89e180e9c55fc11fe71fbaf7 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 13:44:43 +0000 Subject: [PATCH 07/23] larger annotation font --- src/drawing/tide_times/tidal_graph.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drawing/tide_times/tidal_graph.py b/src/drawing/tide_times/tidal_graph.py index fb2bf547..833492fb 100644 --- a/src/drawing/tide_times/tidal_graph.py +++ b/src/drawing/tide_times/tidal_graph.py @@ -89,7 +89,7 @@ def render_tide_chart(location_id, img_buf): xytext=(-15, 0), textcoords='offset points', ha='center', - fontsize=8, + fontsize=11, color='red' ) # Label for maximum @@ -99,7 +99,7 @@ def render_tide_chart(location_id, img_buf): xytext=(14, 0), textcoords='offset points', ha='center', - fontsize=8, + fontsize=11, color='blue' ) From 3829dfb1df91e1fff3824022d9eabee19bceda99 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 14:23:17 +0000 Subject: [PATCH 08/23] limit tests to pickles --- tests/test_chart_rendering.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_chart_rendering.py b/tests/test_chart_rendering.py index c2af6c2e..bf52bf2c 100644 --- a/tests/test_chart_rendering.py +++ b/tests/test_chart_rendering.py @@ -6,6 +6,7 @@ import os import pathlib import unittest +import glob from src.drawing.market_charts.mpf_plotted_chart import MplFinanceChart from src.exchanges.CandleData import CandleData @@ -59,7 +60,8 @@ def test(self): return test - for file_name in os.listdir(test_data_path): + for file_path in glob.glob(f"{test_data_path}/*.pkl"): + file_name = os.path.basename(file_path) test_name = f"test_{file_name}".replace(".pkl","") this_tests_images_path=os.path.join(test_images_path, chart_size) os.makedirs(this_tests_images_path, exist_ok=True) From 6f80b195bcf5c3133555a89ba4769002b90f59d7 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 14:23:29 +0000 Subject: [PATCH 09/23] updated image --- tests/images/TidalGraph.png | Bin 5622 -> 5742 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/images/TidalGraph.png b/tests/images/TidalGraph.png index e1c653a6ddb0bca9f0bf651b6d5a21682f7b8f74..4c8b2dbe6dc24cbb03b6f5b3579f3cf796ff659e 100644 GIT binary patch literal 5742 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 Date: Sun, 9 Feb 2025 14:31:49 +0000 Subject: [PATCH 10/23] simplify test --- tests/test_tides.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_tides.py b/tests/test_tides.py index 3bb98634..c078d959 100644 --- a/tests/test_tides.py +++ b/tests/test_tides.py @@ -8,7 +8,5 @@ class TestTidalGraph(unittest.TestCase): def test_data_fetch_and_render(self): with io.BytesIO() as img_buf: - tidal_graph.render_tide_chart("0184", img_buf) - - image = Image.open(img_buf) + image = tidal_graph.render_tide_chart("0184", img_buf) image.save(f'tests/images/TidalGraph.png') From 7c103f88b444a442bff5f93886ebed7c767faf0d Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 14:33:36 +0000 Subject: [PATCH 11/23] update to match branch naming change --- .github/workflows/build-and-push-image.yaml | 2 +- docs/development.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-push-image.yaml b/.github/workflows/build-and-push-image.yaml index 08013287..7736580c 100644 --- a/.github/workflows/build-and-push-image.yaml +++ b/.github/workflows/build-and-push-image.yaml @@ -2,7 +2,7 @@ name: Create and publish Docker image on: push: - branches: ['main', 'release', 'project_structure'] + branches: ['develop', 'release'] env: REGISTRY: ghcr.io diff --git a/docs/development.md b/docs/development.md index 4ec9d0c8..7cccb4da 100644 --- a/docs/development.md +++ b/docs/development.md @@ -41,7 +41,7 @@ UML diagram of broad [package interactions](http://www.plantuml.com/plantuml/svg - [`Pillow`](https://github.com/python-pillow/Pillow) draws **drawing overlay** text onto the graph ## 🐳 Docker -**Github actions** builds and tests and publishes a **container image** on each commit to `main` and `release` +**Github actions** builds and tests and publishes a **container image** on each commit to `develop` and `release` 🐳 `x86` faster than the Pi. ```sh From 517bf2eb5f91d0705a79bbb6a689bcd1aeb8aa35 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 15:35:14 +0000 Subject: [PATCH 12/23] tweak tides display --- src/drawing/tide_times/tidal_graph.py | 1 + tests/images/TidalGraph.png | Bin 5742 -> 5727 bytes tests/test_tides.py | 2 -- 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/drawing/tide_times/tidal_graph.py b/src/drawing/tide_times/tidal_graph.py index 833492fb..20af2083 100644 --- a/src/drawing/tide_times/tidal_graph.py +++ b/src/drawing/tide_times/tidal_graph.py @@ -47,6 +47,7 @@ def render_tide_chart(location_id, img_buf): mpl.rcParams["font.family"] = "sans-serif" mpl.rcParams["font.sans-serif"] = "basis33" mpl.rcParams["font.size"] = "11" + mpl.rcParams["axes.linewidth"] = "0.5" plt.figure(figsize=(4, 3)) plt.plot(dates, heights) diff --git a/tests/images/TidalGraph.png b/tests/images/TidalGraph.png index 4c8b2dbe6dc24cbb03b6f5b3579f3cf796ff659e..e8c22cb30d01c5c96895e3c43b7e7a29321af172 100644 GIT binary patch delta 5192 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 delta 5221 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 NlY_f`y=_qX{{i%qCFTGC diff --git a/tests/test_tides.py b/tests/test_tides.py index c078d959..85e4cef1 100644 --- a/tests/test_tides.py +++ b/tests/test_tides.py @@ -4,9 +4,7 @@ from PIL import Image, ImageDraw class TestTidalGraph(unittest.TestCase): - def test_data_fetch_and_render(self): - with io.BytesIO() as img_buf: image = tidal_graph.render_tide_chart("0184", img_buf) image.save(f'tests/images/TidalGraph.png') From b8f72e72db560f11ae94667fdcaa1946cea0087a Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 15:35:34 +0000 Subject: [PATCH 13/23] bigger tide label size --- src/drawing/tide_times/tidal_graph.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drawing/tide_times/tidal_graph.py b/src/drawing/tide_times/tidal_graph.py index 20af2083..17b1f813 100644 --- a/src/drawing/tide_times/tidal_graph.py +++ b/src/drawing/tide_times/tidal_graph.py @@ -90,7 +90,7 @@ def render_tide_chart(location_id, img_buf): xytext=(-15, 0), textcoords='offset points', ha='center', - fontsize=11, + fontsize=16, color='red' ) # Label for maximum @@ -100,7 +100,7 @@ def render_tide_chart(location_id, img_buf): xytext=(14, 0), textcoords='offset points', ha='center', - fontsize=11, + fontsize=16, color='blue' ) From dd3fbeed53778baf1e5bb368eedcc68c7fa2e343 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 15:37:07 +0000 Subject: [PATCH 14/23] use whitby as default tide location --- config/config.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.ini b/config/config.ini index 2667eee5..80845995 100644 --- a/config/config.ini +++ b/config/config.ini @@ -32,7 +32,7 @@ enabled = false [tide_times] enabled = false -location_id = 9414290 +location_id = 0184 [comments] up = moon,yolo,pump it,gentlemen From d267e6af4f5b184120790f2f1a6bfd0aca48d8de Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 15:53:47 +0000 Subject: [PATCH 15/23] more fiddling --- src/drawing/tide_times/tidal_graph.py | 11 +++++++---- tests/images/TidalGraph.png | Bin 5727 -> 6869 bytes 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/drawing/tide_times/tidal_graph.py b/src/drawing/tide_times/tidal_graph.py index 17b1f813..ca866962 100644 --- a/src/drawing/tide_times/tidal_graph.py +++ b/src/drawing/tide_times/tidal_graph.py @@ -48,6 +48,9 @@ def render_tide_chart(location_id, img_buf): mpl.rcParams["font.sans-serif"] = "basis33" mpl.rcParams["font.size"] = "11" mpl.rcParams["axes.linewidth"] = "0.5" + mpl.rcParams["grid.linestyle"] = "--" + mpl.rcParams["grid.linewidth"] = "0.5" + mpl.rcParams["grid.color"] = "red" plt.figure(figsize=(4, 3)) plt.plot(dates, heights) @@ -87,20 +90,20 @@ def render_tide_chart(location_id, img_buf): plt.annotate( f"{values['min'][0].strftime('%-I:%p')}", xy=(values['min'][0], values['min'][1]), - xytext=(-15, 0), + xytext=(-15, -5), textcoords='offset points', ha='center', - fontsize=16, + fontsize=11, color='red' ) # Label for maximum plt.annotate( f"{values['max'][0].strftime('%-I:%p')}", xy=(values['max'][0], values['max'][1]), - xytext=(14, 0), + xytext=(14, 5), textcoords='offset points', ha='center', - fontsize=16, + fontsize=11, color='blue' ) diff --git a/tests/images/TidalGraph.png b/tests/images/TidalGraph.png index e8c22cb30d01c5c96895e3c43b7e7a29321af172..a1fa898ba4695a09bdcf2af78ec9c4a28676b52e 100644 GIT binary patch literal 6869 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 Date: Sun, 9 Feb 2025 17:56:00 +0000 Subject: [PATCH 16/23] rename test png --- tests/images/{TidalGraph.png => tide_times.png} | Bin tests/test_tides.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/images/{TidalGraph.png => tide_times.png} (100%) diff --git a/tests/images/TidalGraph.png b/tests/images/tide_times.png similarity index 100% rename from tests/images/TidalGraph.png rename to tests/images/tide_times.png diff --git a/tests/test_tides.py b/tests/test_tides.py index 85e4cef1..d4b6cbb6 100644 --- a/tests/test_tides.py +++ b/tests/test_tides.py @@ -7,4 +7,4 @@ class TestTidalGraph(unittest.TestCase): def test_data_fetch_and_render(self): with io.BytesIO() as img_buf: image = tidal_graph.render_tide_chart("0184", img_buf) - image.save(f'tests/images/TidalGraph.png') + image.save(f'tests/images/tide_times.png') From 9eda7c6fd71e7c20df1f64d4dbd05e64c5277631 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 18:02:34 +0000 Subject: [PATCH 17/23] add ip to intro --- src/drawing/intro.py | 7 +++++-- src/drawing/tide_times/tidal_graph.py | 10 +++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/drawing/intro.py b/src/drawing/intro.py index 1d1b1524..1f246735 100644 --- a/src/drawing/intro.py +++ b/src/drawing/intro.py @@ -2,6 +2,9 @@ import time from .image_utils.CenteredText import centered_text from ..configuration.network_utils import wait_for_internet_connection + +from src.configuration.network_utils import get_ip + page1 = '''I'm Bitbot. I can chart crypto and stock markets. @@ -20,10 +23,10 @@ Once I have internet access, I will load the next page...''' -page3 = '''Good job! I'm connected :D +page3 = f'''Good job! I'm connected :D To change my config, -visit 'http://bitbot:8080' +visit 'http://{get_ip()}:8080' from any device in your network. In 30 seconds time, diff --git a/src/drawing/tide_times/tidal_graph.py b/src/drawing/tide_times/tidal_graph.py index ca866962..7436cd5f 100644 --- a/src/drawing/tide_times/tidal_graph.py +++ b/src/drawing/tide_times/tidal_graph.py @@ -4,16 +4,14 @@ from PIL import Image import matplotlib as mpl -def get_tide_data(station_id): - - base_url = "https://easytide.admiralty.co.uk/Home/GetPredictionData" +easytide_base_url = "https://easytide.admiralty.co.uk/Home/GetPredictionData" - +def get_tide_data(station_id): params = { 'stationId': station_id, } - response = requests.get(base_url, params=params) + response = requests.get(easytide_base_url, params=params) if response.status_code != 200: raise Exception(f"Failed to fetch data: HTTP {response.status_code}") @@ -24,7 +22,6 @@ def get_tide_data(station_id): tide_data = [] for entry in data["tidalEventList"]: - # Convert timestamp to a readable format date = datetime.strptime(entry['dateTime'], "%Y-%m-%dT%H:%M:%S").strftime('%Y-%m-%d %H:%M') height = entry['height'] tide_data.append({'date': date, 'height': height}) @@ -38,7 +35,6 @@ def render_tide_chart(location_id, img_buf): dates = [datetime.strptime(d['date'], '%Y-%m-%d %H:%M') for d in tide_data] heights = [d['height'] for d in tide_data] - mpl.rcParams["text.hinting_factor"] = "1" mpl.rcParams["text.hinting"] = "native" mpl.rcParams["text.antialiased"] = "False" From c920161980739fb112948ccf5f685aa041ab61a2 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Sun, 9 Feb 2025 18:17:57 +0000 Subject: [PATCH 18/23] update intro png --- tests/images/intro2.png | Bin 21949 -> 21959 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/images/intro2.png b/tests/images/intro2.png index da0e7a1329c500bf267c596b55cbe61333c0c3a0..4f30e3721bf7995f845a2e403f7778ac6e5f040f 100644 GIT binary patch delta 17736 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 Date: Tue, 11 Feb 2025 00:14:15 +0000 Subject: [PATCH 19/23] fix align --- src/drawing/image_utils/Align.py | 6 +++--- src/drawing/youtube_stats/subscriber_counter.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/drawing/image_utils/Align.py b/src/drawing/image_utils/Align.py index 6f7c1793..da66478a 100644 --- a/src/drawing/image_utils/Align.py +++ b/src/drawing/image_utils/Align.py @@ -14,9 +14,9 @@ def BottomLeft(display, message_size): def TopLeft(display, message_size): return (0 + padding + 1, 0 + padding + 1) - def Centre(display, message_size): - message_y = (display.size[1][1] - message_size[1]) / 2 - message_x = (display.size[1][0] - message_size[0]) / 2 + def Centre(display_size, message_size): + message_y = (display_size[1] - message_size[1]) / 2 + message_x = (display_size[0] - message_size[0]) / 2 return (message_y, message_x) # 🏳️ select image area with the most white pixels diff --git a/src/drawing/youtube_stats/subscriber_counter.py b/src/drawing/youtube_stats/subscriber_counter.py index c724b36a..2baa344e 100644 --- a/src/drawing/youtube_stats/subscriber_counter.py +++ b/src/drawing/youtube_stats/subscriber_counter.py @@ -23,5 +23,5 @@ def play(self): text_to_draw = f"{subscriber_count} Subscribers" img = Image.new("RGBA", self.display_size.size, transparent) draw = ImageDraw.Draw(img) - centered_text(draw, text_to_draw, self.font, self.display_size, 'centre') + centered_text(draw, text_to_draw, self.font, self.display_size.size, 'centre') return img \ No newline at end of file From a5e66aa25893ab5316ea3b69159207657bf9cb9c Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Tue, 11 Feb 2025 12:05:39 +0000 Subject: [PATCH 20/23] text layout --- src/bitbot.py | 4 ++-- src/drawing/image_utils/Align.py | 6 +++--- tests/images/test_centered.png | Bin 0 -> 674 bytes tests/test_overlay_drawing.py | 22 ++++++++++++++++++++++ 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 tests/images/test_centered.png diff --git a/src/bitbot.py b/src/bitbot.py index df389607..3cb09f9c 100644 --- a/src/bitbot.py +++ b/src/bitbot.py @@ -54,9 +54,9 @@ def display_chart(self): @info_log def display_message(self, message): - img = Image.new("P", self.display.size()) + img = Image.new("RGBA", self.display.size(), (255, 0, 0, 0)) draw = ImageDraw.Draw(img) - centered_text(draw, message, self.display.title_font, self.display.size(), border=True) + centered_text(draw, message, self.display.title_font, self.display.size(), border=True, pos="topright") self.display.show(img) return img diff --git a/src/drawing/image_utils/Align.py b/src/drawing/image_utils/Align.py index da66478a..d334fc9a 100644 --- a/src/drawing/image_utils/Align.py +++ b/src/drawing/image_utils/Align.py @@ -3,13 +3,13 @@ class Align: def TopRight(display, message_size): - return (display.size[0] - message_size[0] - padding - 1, padding) + return (display[0] - message_size[0] - padding - 1, padding) def BottomRight(display, message_size): - return (display.size[0] - message_size[0], display.size[1] - message_size[1]) + return (display[0] - message_size[0], display[1] - message_size[1]) def BottomLeft(display, message_size): - return (0, display.size[1] - message_size[1]) + return (0, display[1] - message_size[1]) def TopLeft(display, message_size): return (0 + padding + 1, 0 + padding + 1) diff --git a/tests/images/test_centered.png b/tests/images/test_centered.png new file mode 100644 index 0000000000000000000000000000000000000000..7fc4227eba1b85b928b521994e30764d8b1ee9ee GIT binary patch literal 674 zcmeAS@N?(olHy`uVBq!ia0y~yV4MKNIvi|3k+<8Q9%5i%%Jg(`45^s&_O>I}VFMnP z16#iQkI#F*Yen4bSv!okJ0yu1=xn-J$_Ugj(!qhc{=2LN(eFRi+={dM`#<4UaXBNy zoyiQ03Q7(P9TwN0Mt}8NaQW@pyuBCqT1MZ0^}qS?OP~aY0D}?}OG8I-Owi(Dp}W5q zmn*G)AD~sNaN$BDgMgp{g9{4>!^G?Fn0`cWF6Y@l&zO-*mV-f%k;%cOfkB{ Date: Tue, 11 Feb 2025 18:21:12 +0000 Subject: [PATCH 21/23] and more --- src/bitbot.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bitbot.py b/src/bitbot.py index 3cb09f9c..8e13210b 100644 --- a/src/bitbot.py +++ b/src/bitbot.py @@ -85,13 +85,13 @@ def display_tide_times(self): @info_log def display_connection_error(self): self.display_message(""" - NO INTERNET CONNECTION - ---------------------------- - Please check your WIFI - ---------------------------- - To configure WiFi access, - connect to 'bitbot-' WiFi AP - and follow the instructions""") +NO INTERNET CONNECTION +---------------------------- +Please check your WIFI +---------------------------- +To configure WiFi access, +connect to 'bitbot-' WiFi AP +and follow the instructions""") def __repr__(self): return f'' From 4aeba7da93aacdde67daf71a1dcd0e92b078ae94 Mon Sep 17 00:00:00 2001 From: Chris Bingham Date: Tue, 11 Feb 2025 22:16:43 +0000 Subject: [PATCH 22/23] actually fix text centring --- src/bitbot.py | 2 +- src/drawing/image_utils/Align.py | 6 ++--- src/drawing/image_utils/CenteredText.py | 16 ++++++------ src/drawing/market_charts/chart_overlay.py | 2 +- tests/images/test_centered.png | Bin 674 -> 724 bytes tests/test_overlay_drawing.py | 28 +++++++++------------ 6 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/bitbot.py b/src/bitbot.py index 8e13210b..a3123900 100644 --- a/src/bitbot.py +++ b/src/bitbot.py @@ -56,7 +56,7 @@ def display_chart(self): def display_message(self, message): img = Image.new("RGBA", self.display.size(), (255, 0, 0, 0)) draw = ImageDraw.Draw(img) - centered_text(draw, message, self.display.title_font, self.display.size(), border=True, pos="topright") + centered_text(draw, message, self.display.title_font, img.size, border=True, pos="centre") self.display.show(img) return img diff --git a/src/drawing/image_utils/Align.py b/src/drawing/image_utils/Align.py index d334fc9a..24abb95b 100644 --- a/src/drawing/image_utils/Align.py +++ b/src/drawing/image_utils/Align.py @@ -14,9 +14,9 @@ def BottomLeft(display, message_size): def TopLeft(display, message_size): return (0 + padding + 1, 0 + padding + 1) - def Centre(display_size, message_size): - message_y = (display_size[1] - message_size[1]) / 2 - message_x = (display_size[0] - message_size[0]) / 2 + def Centre(display, message_size): + message_y = (display[0] - message_size[0]) / 2 + message_x = (display[1] - message_size[1]) / 2 return (message_y, message_x) # 🏳️ select image area with the most white pixels diff --git a/src/drawing/image_utils/CenteredText.py b/src/drawing/image_utils/CenteredText.py index fc8479b1..59a24a9e 100644 --- a/src/drawing/image_utils/CenteredText.py +++ b/src/drawing/image_utils/CenteredText.py @@ -8,15 +8,15 @@ def centered_text(draw, text, font, container_size, pos='centre', border=False): # 📏 where to position the message if pos == 'centre': - message_x, message_y = Align.Centre(container_size, message_size) + message_y, message_x = Align.Centre(container_size, message_size) elif pos == 'topright': - message_x, message_y = Align.TopRight(container_size, message_size) + message_y, message_x = Align.TopRight(container_size, message_size) elif pos == 'topleft': - message_x, message_y = Align.TopLeft(container_size, message_size) + message_y, message_x = Align.TopLeft(container_size, message_size) # 🖊️ draw the message at position draw.multiline_text( - (message_x, message_y), + (message_y, message_x), text, fill='black', font=font, @@ -24,8 +24,8 @@ def centered_text(draw, text, font, container_size, pos='centre', border=False): # 📏 measure border box if border: - x0, y0 = (message_x - padding, message_y - padding) - x1 = message_x + message_size[0] + padding - y1 = message_y + message_size[1] + padding + y0, x0 = (message_y - padding, message_x - padding) + y1 = message_y + message_size[0] + padding + x1 = message_x + message_size[1] + padding # 🖊️ draw box at position - draw.rectangle([(x0, y0), (x1, y1)], outline='red') + draw.rectangle([(y0, x0), (y1, x1)], outline='red') diff --git a/src/drawing/market_charts/chart_overlay.py b/src/drawing/market_charts/chart_overlay.py index 18f251bd..16a0d95d 100644 --- a/src/drawing/market_charts/chart_overlay.py +++ b/src/drawing/market_charts/chart_overlay.py @@ -104,7 +104,7 @@ def price_increasing(self, chartdata): return chartdata.start_price() < chartdata.last_close() def format_time(self): - return datetime.now().strftime("%-H:%M%b%-d") + return datetime.now().strftime("%-H:%M %b%-d") def ai_comments(self): return self.config.get_price_action_comments() diff --git a/tests/images/test_centered.png b/tests/images/test_centered.png index 7fc4227eba1b85b928b521994e30764d8b1ee9ee..0b3209b013fbd80bbbc78781b0226e5edea588df 100644 GIT binary patch delta 280 zcmZ3)dWCg@irQ>X7srr_IdAWHa~)P-V7aj5%fE2H?MI!COuXiQKYIB=kwXg>Tk=f| zyjtIoZ|Tm@a4+_FVXxfbH-7JR52!O1o&SH>M{Y4Y!+}{W91IhmzhHE5-I=oa_OJi% z&L2N^#(|-OLx4eviKU@~uSN21ZfNdXo~+w((bnzPa<@GFo4x;f=LQ~Qs0s!~g+S>LWDpPp z%7LV0IW}k8nqRDbxA@BMx2vzcp39vG)(6#g)`-`jc87Br_mS~u|hv99h VtoeVtEdmTc;OXk;vd$@?2>`~UcEtby delta 224 zcmV<603ZL<1)>FzBqwP}L_t(|obB5|3d1lA1i-ZP|6gwJx~N{8nz%E!Kw=ayEV9vc z0g+M8kzh4{zkx{M} afY1l#Y7r>k8pu)r0000 Date: Wed, 12 Feb 2025 00:10:02 +0000 Subject: [PATCH 23/23] qickfix textblock size --- src/bitbot.py | 3 +-- src/drawing/image_utils/Align.py | 23 ++++++++++++---------- src/drawing/image_utils/DrawText.py | 2 +- src/drawing/image_utils/TextBlock.py | 4 ++-- src/drawing/market_charts/chart_overlay.py | 9 ++++----- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/bitbot.py b/src/bitbot.py index a3123900..120338b1 100644 --- a/src/bitbot.py +++ b/src/bitbot.py @@ -2,7 +2,6 @@ from os.path import exists import io -from matplotlib import font_manager from src.drawing.market_charts.mpf_plotted_chart import MplFinanceChart from src.exchanges import crypto_exchanges, stock_exchanges from src.configuration.log_decorator import info_log @@ -90,7 +89,7 @@ def display_connection_error(self): Please check your WIFI ---------------------------- To configure WiFi access, -connect to 'bitbot-' WiFi AP +connect to 'comitup-' WiFi AP and follow the instructions""") def __repr__(self): diff --git a/src/drawing/image_utils/Align.py b/src/drawing/image_utils/Align.py index 24abb95b..b9312732 100644 --- a/src/drawing/image_utils/Align.py +++ b/src/drawing/image_utils/Align.py @@ -2,21 +2,24 @@ class Align: - def TopRight(display, message_size): - return (display[0] - message_size[0] - padding - 1, padding) + def TopRight(display_size, message_size): + return (display_size[0] - message_size[0] - padding - 1, padding) - def BottomRight(display, message_size): - return (display[0] - message_size[0], display[1] - message_size[1]) + def BottomRight(display_size, message_size): + display_width_minus_text_width = display_size[0] - message_size[0] + display_height_minus_text_height = display_size[1] - message_size[1] + + return (display_width_minus_text_width, display_height_minus_text_height) - def BottomLeft(display, message_size): - return (0, display[1] - message_size[1]) + def BottomLeft(display_size, message_size): + return (0, display_size[1] - message_size[1]) - def TopLeft(display, message_size): + def TopLeft(display_size, message_size): return (0 + padding + 1, 0 + padding + 1) - def Centre(display, message_size): - message_y = (display[0] - message_size[0]) / 2 - message_x = (display[1] - message_size[1]) / 2 + def Centre(display_size, message_size): + message_y = (display_size[0] - message_size[0]) / 2 + message_x = (display_size[1] - message_size[1]) / 2 return (message_y, message_x) # 🏳️ select image area with the most white pixels diff --git a/src/drawing/image_utils/DrawText.py b/src/drawing/image_utils/DrawText.py index 1fa98df6..b7080408 100644 --- a/src/drawing/image_utils/DrawText.py +++ b/src/drawing/image_utils/DrawText.py @@ -59,5 +59,5 @@ def __init__(self, text, font, colour='black', align=None): self.align = align def draw_on(self, draw, pos=(0, 0)): - pos = self.align(draw.im, self.size) if self.align else pos + pos = self.align(draw.im.size, self.size) if self.align else pos draw.text(pos, self.text, self.colour, self.font) \ No newline at end of file diff --git a/src/drawing/image_utils/TextBlock.py b/src/drawing/image_utils/TextBlock.py index f0d2eb2a..8e0be54d 100644 --- a/src/drawing/image_utils/TextBlock.py +++ b/src/drawing/image_utils/TextBlock.py @@ -1,6 +1,6 @@ from .DrawText import DrawText - +# texts is array of drawtext class TextBlock: def __init__(self, texts, align=None): self.texts = texts @@ -26,5 +26,5 @@ def draw_on(self, draw, pos=(0, 0)): def draw_text_row(self, draw, x_pos, y_pos, row): for text in row: - text.draw_on(draw, (x_pos, y_pos)) + text.draw_on(draw, pos=(x_pos, y_pos)) x_pos += DrawText.width(text) \ No newline at end of file diff --git a/src/drawing/market_charts/chart_overlay.py b/src/drawing/market_charts/chart_overlay.py index 16a0d95d..f81c9801 100644 --- a/src/drawing/market_charts/chart_overlay.py +++ b/src/drawing/market_charts/chart_overlay.py @@ -14,12 +14,11 @@ class ChartOverlay(): def __init__(self, config, display, chart_data): self.config = config - self.display = display self.chart_data = chart_data - self.title_font = self.display.title_font - self.price_font = self.display.price_font - self.medium_font = self.display.medium_font - self.tiny_font = self.display.tiny_font + self.title_font = display.title_font + self.price_font = display.price_font + self.medium_font = display.medium_font + self.tiny_font = display.tiny_font @info_log def draw_on(self, chart_image):