diff --git a/site_builder/.gitignore b/site_builder/.gitignore new file mode 100644 index 0000000..225fc6f --- /dev/null +++ b/site_builder/.gitignore @@ -0,0 +1 @@ +/__pycache__ diff --git a/site_builder/__pycache__/main.cpython-313.pyc b/site_builder/__pycache__/main.cpython-313.pyc deleted file mode 100644 index 18fe0b8..0000000 Binary files a/site_builder/__pycache__/main.cpython-313.pyc and /dev/null differ diff --git a/site_builder/__pycache__/test_find_extrema.cpython-313-pytest-8.4.0.pyc b/site_builder/__pycache__/test_find_extrema.cpython-313-pytest-8.4.0.pyc deleted file mode 100644 index 311d4cf..0000000 Binary files a/site_builder/__pycache__/test_find_extrema.cpython-313-pytest-8.4.0.pyc and /dev/null differ diff --git a/site_builder/__pycache__/test_find_geo_extrema.cpython-313-pytest-8.4.0.pyc b/site_builder/__pycache__/test_find_geo_extrema.cpython-313-pytest-8.4.0.pyc deleted file mode 100644 index 4cb9a96..0000000 Binary files a/site_builder/__pycache__/test_find_geo_extrema.cpython-313-pytest-8.4.0.pyc and /dev/null differ diff --git a/site_builder/__pycache__/test_main.cpython-313-pytest-8.4.0.pyc b/site_builder/__pycache__/test_main.cpython-313-pytest-8.4.0.pyc deleted file mode 100644 index 1412d2f..0000000 Binary files a/site_builder/__pycache__/test_main.cpython-313-pytest-8.4.0.pyc and /dev/null differ diff --git a/site_builder/__pycache__/test_main.cpython-313.pyc b/site_builder/__pycache__/test_main.cpython-313.pyc deleted file mode 100644 index 29d034f..0000000 Binary files a/site_builder/__pycache__/test_main.cpython-313.pyc and /dev/null differ diff --git a/site_builder/__pycache__/test_main_unittests.cpython-313-pytest-8.4.0.pyc b/site_builder/__pycache__/test_main_unittests.cpython-313-pytest-8.4.0.pyc deleted file mode 100644 index 999de3c..0000000 Binary files a/site_builder/__pycache__/test_main_unittests.cpython-313-pytest-8.4.0.pyc and /dev/null differ diff --git a/site_builder/__pycache__/test_read_csv_to_dict.cpython-313-pytest-8.4.0.pyc b/site_builder/__pycache__/test_read_csv_to_dict.cpython-313-pytest-8.4.0.pyc deleted file mode 100644 index da0b76c..0000000 Binary files a/site_builder/__pycache__/test_read_csv_to_dict.cpython-313-pytest-8.4.0.pyc and /dev/null differ diff --git a/site_builder/__pycache__/test_translate_pos.cpython-313-pytest-8.4.0.pyc b/site_builder/__pycache__/test_translate_pos.cpython-313-pytest-8.4.0.pyc deleted file mode 100644 index 28bf5e3..0000000 Binary files a/site_builder/__pycache__/test_translate_pos.cpython-313-pytest-8.4.0.pyc and /dev/null differ diff --git a/site_builder/constants/__pycache__/fields.cpython-313.pyc b/site_builder/constants/__pycache__/fields.cpython-313.pyc new file mode 100644 index 0000000..fa25e32 Binary files /dev/null and b/site_builder/constants/__pycache__/fields.cpython-313.pyc differ diff --git a/site_builder/constants/fields.py b/site_builder/constants/fields.py new file mode 100644 index 0000000..582abc7 --- /dev/null +++ b/site_builder/constants/fields.py @@ -0,0 +1,9 @@ +# Field position for data items +ID = 0 +FILE = 1 +LON = 2 +LAT = 3 +TITLE = 4 +DESCRIPTION = 5 +POSX = 6 +POSY = 7 \ No newline at end of file diff --git a/site_builder/main.py b/site_builder/main.py index 4a58d27..4b1f515 100644 --- a/site_builder/main.py +++ b/site_builder/main.py @@ -2,15 +2,19 @@ import argparse import csv import os.path as path import re +import constants.fields as F importdir = 'images' datafile = path.join(importdir, 'gps.csv') args = None -# Imported data with appended attributes as list of lists -# Items: +# Based on imported CSV and added with attributes: +# data with appended attributes as list of lists. +# Items ---> See constants/fields.py <--- +# - ID # - Image file name -# - lon, lat +# - lon +# - lat # - title, description # - x, y: Default tile position data = None @@ -47,8 +51,15 @@ def exit_with_error(message): def read_csv_to_dict(csv_file): """ - Reads a CSV file and returns a list of dictionaries, one per row. - Assumes the first row contains headers. + Reads a tab-separated CSV file and returns a list of dictionaries, one per row + in the full data item size. Placeholder for unfilled fields is None. + Fields: + 0: ID (integer), ascending starting with '1' <-- not in CSV + 1: image file name (string) + 2: latitude and longitude (floats), separated by space. + 3. title (string) + 4. description (string) + The items must be sorted chronologically. Assumes the first row contains headers. In error case, returns None """ global message @@ -57,6 +68,7 @@ def read_csv_to_dict(csv_file): reader = csv.reader(f, skipinitialspace=False, delimiter='\t') log(f"Read lines from {csv_file}") + id = 0 for row in reader: logvv(f"Processing row: {row}") @@ -74,9 +86,21 @@ def read_csv_to_dict(csv_file): if len(geo) != 2: message = f'Invalid loc/lon: {row[1]}' - values = [ row[0], float(geo[0]), float(geo[1]), row[2], row[3] ] + id += 1 + # Order and size must match constants.fields + # values = [id, row[0], float(geo[0]), float(geo[1]), row[2], row[3] ] + values = [] + values.insert(F.ID, id) + values.insert(F.FILE, row[0]) + values.insert(F.LON, float(geo[0])) + values.insert(F.LAT, float(geo[1])) + values.insert(F.TITLE, row[2]) + values.insert(F.DESCRIPTION, row[3]) + values.insert(F.POSX, None) + values.insert(F.POSY, None) data.append(values) - logvv(f"Read row : {values}") + + logvv(f"Processed item : {values}") if len(data) == 0: message = f'Empty file: {csv_file}' @@ -117,18 +141,18 @@ def find_geo_extrema(data): if len(data) == 0: return None - lonmin = lonmax = data[0][1] - latmin = latmax = data[0][2] + lonmin = lonmax = data[0][F.LON] + latmin = latmax = data[0][F.LAT] for entry in data[1:]: - if entry[1] < lonmin: - lonmin = entry[1] - if entry[1] > lonmax: - lonmax = entry[1] - if entry[2] < latmin: - latmin = entry[2] - if entry[2] > latmax: - latmax = entry[2] + if entry[F.LON] < lonmin: + lonmin = entry[F.LON] + if entry[F.LON] > lonmax: + lonmax = entry[F.LON] + if entry[F.LAT] < latmin: + latmin = entry[F.LAT] + if entry[F.LAT] > latmax: + latmax = entry[F.LAT] return (lonmin, lonmax, latmin, latmax) @@ -138,6 +162,7 @@ def translate_pos(min, max, pos, size): return round((pos - min) / (max - min) * size) + def append_tile_pos(data, geo_extrema, matrixdims): """ Adds two columns with x and y position (integer) of the tile in the canvas @@ -157,10 +182,73 @@ def append_tile_pos(data, geo_extrema, matrixdims): return ret + +def create_playbook(data): + """ + Returns list of dict [delta1, delta2, ...] with changes (in both direections) for every single tour. + The snapshot holds the complete canvas for the actual step. The playbook contains exclusively + changed values (delta). + Rules to process: + - Loop over all n data items: start with the first (oldest) item (0) + - Copy previous snapshot (to find changes in a later step) + - Run recursively over the the snapshot items: Find an existing item at the position + of the actual image and change its position by the displacement rule. + - Place the image of the actual item (a) at its default position in the snapshot + - Create a item for the following image (a+1) and hide it (for scrolling backwards). + - Store all changes betweeen snapshot and previous snapshot in a new delta (a) and append it + to the return dict. + In error case, None will be returned. + """ + + snapshot = prev_snapshot = [] + ret = [] + + for a in data: + prev_snapshot = snapshot + + (x, y) = (a[F.POSX], a[F.POSY]) + + snapshot = shifting_snapshot_items(x,y, snapshot) + + return ret + +def shifting_snapshot_items(x, y, snapshot): + """ + Recursive change item chain starting with item at position x,y. + Returns updated snapshot + """ + + goon = True + (actx, acty) = (x, y) + ret = snapshot + + while goon: + goon = False + for i, item in enumerate(ret): + if (item[F.POSX], item[F.POSY]) == (actx, acty): + # ret[i][F.POSX], ret[i][F.POSY] = + goon = True + + + + return ret + +def shifting(tup, matrixdims): + """Strategy to shift. Above and on the horizontal middle line, the position + will be shifted to the top. Positions below the horizontal middle line, + the position will be shifted in bottom direction. + Returns the offset as (x, y) tuple, not the new position itself. + """ + + + + + def calculate_orig_pos(): global data geo_extrema = find_geo_extrema(data) data = append_tile_pos(data, geo_extrema, matrixdims) + playbook = create_playbook(data) def main(): diff --git a/site_builder/test_find_geo_extrema.py b/site_builder/test_find_geo_extrema.py index 3596b64..6b0a09c 100644 --- a/site_builder/test_find_geo_extrema.py +++ b/site_builder/test_find_geo_extrema.py @@ -10,11 +10,11 @@ def patch_log(monkeypatch): def test_find_geo_extrama_simpple(): data = [ - ['dummy', 50.1, 8.1 ], - ['dummy', 50.2, 8.2 ], - ['dummy', 50.3, 8.4 ], - ['dummy', 49.3, 8.4 ], - ['dummy', 49.3, 7.4 ] + [0, 'dummy', 50.1, 8.1 ], + [1, 'dummy', 50.2, 8.2 ], + [2, 'dummy', 50.3, 8.4 ], + [3, 'dummy', 49.3, 8.4 ], + [4, 'dummy', 49.3, 7.4 ] ] result = main.find_geo_extrema(data) @@ -24,7 +24,7 @@ def test_find_geo_extrama_simpple(): def test_find_geo_extrama_single(): data = [ - ['dummy', 50.1, 8.1 ] + [0, 'dummy', 50.1, 8.1 ] ] result = main.find_geo_extrema(data) diff --git a/site_builder/test_read_csv_to_dict.py b/site_builder/test_read_csv_to_dict.py index a3732d5..85a3579 100644 --- a/site_builder/test_read_csv_to_dict.py +++ b/site_builder/test_read_csv_to_dict.py @@ -18,8 +18,8 @@ def test_read_csv_to_dict_basic(tmp_path): result = main.read_csv_to_dict(str(file_path)) expected = [ - ['img1', 12.34, 56.78, 'foo', 'bar'], - ['img2', 90.12, 34.56, 'baz', 'qux'], + [1, 'img1', 12.34, 56.78, 'foo', 'bar', None, None], + [2, 'img2', 90.12, 34.56, 'baz', 'qux', None, None], ] assert result == expected @@ -39,7 +39,7 @@ def test_read_csv_to_dict_extra_spaces(tmp_path): file_path.write_text(content, encoding="utf-8") result = main.read_csv_to_dict(str(file_path)) - expected = [['img3', 3.23, 4.56, 'foo', 'bar']] + expected = [[1, 'img3', 3.23, 4.56, 'foo', 'bar', None, None]] assert result == expected