Skip to content

Conversation

@sdf-jkl
Copy link
Contributor

@sdf-jkl sdf-jkl commented Jun 2, 2025

Working on this:

  • Create several schema initialization .sql files, e.g. in mbtiles/sql/ dir, add init-flat.sql, init-flat-with-hash.sql, etc.
    • Use content of these files directly in the docs, rather than copy/paste it. See {{#include file.rs}}
    • Use these files in the test.sh before populating them with data
      -- Couldn't find where the mbtiles are being updated in tests.sh
    • Use these files in the unit tests
    • Update docs to use these files with the sqlite command to create a blank .mbtiles file
  • Export all existing .mbtiles test files as .sql files, e.g. by using sqlite3's .dump command.
    • Remove any schema creation - and reuse the above ones. We may need to include the schema name in the file name to ensure the right schema is used... unless we can somehow transclude one file inside the other
      -- i am not sure if .read filename.sql can be used from another .sql file?
    • For image content, each tile content should be stored as an individual image file in a subdir - this way they can also be easily inspected. I think the readfile('...') sqlite function can be used to get the file content as part of the insert statement.
    • Same goes for the .mvt / .mlt content, except that sadly we have no way to store it in a viewable format - until someday we may have some simple json-mvt-mlt debug converter, or we could use ogr2ogr or another utility to store geojson - but this is not great because the output is less guaranteed.

Related #1846

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Jun 3, 2025

@nyurik
I tested including .read in .sql files and it worked.

I created these test .sql files:
init.sql

CREATE TABLE meow (
    text TEXT
);

read.sql

.read init.sql

INSERT INTO meow VALUES ('meow');

rightaway.sql

CREATE TABLE meow (
    text TEXT
);

INSERT INTO meow VALUES ('meow');

Created .sqlite files to check their difference and there was no output:

sqlite3 read.sqlite < read.sql
sqlite3 rightaway.sqlite < rightaway.sql
sqldiff read.sqlite rightaway.sqlite

So we should be good with using .read inside .sql files.

@nyurik
Copy link
Member

nyurik commented Jun 3, 2025

awesome work!! I noticed that all .sql files have tons of individual inserts. Is there a sqlite command to dump the entire table as a single insert? Something like this. We could of course modify the sql files by hand later, but if sqlite .dump can do it automatically, it will save some time.

INSERT INTO 'tablename' ('column1', 'column2') VALUES
    ('data1', 'data2'),
    ('data1', 'data2'),
    ('data1', 'data2'),
    ('data1', 'data2');

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Jun 4, 2025

Unfortunately, there isn't one. Will have to do that manually (a small script should do the work)

@nyurik
Copy link
Member

nyurik commented Jun 4, 2025

i don't think you want to do a script for this :) A simple search/replace, or a multi-cursor editor would do all this in a few minutes :)

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Jun 6, 2025

Should we create a new just recipe for creating .mbtiles from .sql files?

We can integrate it in just test:

-test: start (test-cargo "--all-targets") test-doc test-int
+test: start prepare-fixtures (test-cargo "--all-targets") test-doc test-int

@nyurik
Copy link
Member

nyurik commented Jun 6, 2025

I think it would make sense to have a recipe for mbtiles generation, yes. Just make sure it gets created in some directory in the .gitignore list (or add a new entry there).... I will have to think of a good dir structure.

One hope I had though was to avoid using the actual disk files in the unit tests. Instead, it would be good to use in-memory sqlite dbs, populate them with data, and pass them to martin components. See

let file = format!("file:{}_{}{}?mode=memory&cache=shared", stringify!($function), format_args!($($arg)*), $extra);
for an example how in-memory sqlite db can be created, and then opened as if it was a regular file. This method might not work from the start - we may rely on temp files at first.

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Jun 6, 2025

I was thinking about generating them in the same folders the original mbtiles were and the new sql files are now ( tests/fixtures/{files, mbtiles}
And adding *.mbtiles to .gitignore

@nyurik
Copy link
Member

nyurik commented Jun 6, 2025

that could be an interim step, agree

@nyurik
Copy link
Member

nyurik commented Jun 6, 2025

the problem though is that users won't be able to run cargo test without doing an additional step first -- that's why I was hoping we won't rely on the files

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Jun 6, 2025

I think it would make sense to have a recipe for mbtiles generation, yes. Just make sure it gets created in some directory in the .gitignore list (or add a new entry there).... I will have to think of a good dir structure.

One hope I had though was to avoid using the actual disk files in the unit tests. Instead, it would be good to use in-memory sqlite dbs, populate them with data, and pass them to martin components. See

let file = format!("file:{}_{}{}?mode=memory&cache=shared", stringify!($function), format_args!($($arg)*), $extra);

for an example how in-memory sqlite db can be created, and then opened as if it was a regular file. This method might not work from the start - we may rely on temp files at first.

I'll look into this more, before I resolve to use files.

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Jun 16, 2025

Sorry for the delay in getting back to this.
From what I understand, the process for the unit tests should be:

  1. Create the in-memory SQLite databases.
  2. Use sqlx to populate them by reading the fixture files.
  3. Access these databases within the unit tests.

I was wondering whether the goal is to initialize the .mbtiles databases once and reuse them across all unit tests, or if we should initialize the required .mbtiles databases fresh within each unit test?

@nyurik
Copy link
Member

nyurik commented Jun 16, 2025

  1. Create the in-memory SQLite databases.
  2. Use sqlx to populate them by reading the fixture files.
  3. Access these databases within the unit tests.

I was wondering whether the goal is to initialize the .mbtiles databases once and reuse them across all unit tests, or if we should initialize the required .mbtiles databases fresh within each unit test?

  • Per test is much better -- each test should run independently, possibly even at the same time, so each in-memory file should either be anonymous :memory:, or when this is not possible (e.g. when a filename must be passed as input), use some temporary filename that is unique per test (it is still in memory, but uses some extra ? params like some other tests already)

  • For (2 - populating data) - you can just read the whole script file and pass it to sqlite:

let script = fs::read_to_string("path/to/something.sql").unwrap();
sqlx::raw_sql(script).execute(&mut conn).await.unwrap();

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Jun 16, 2025

I updated the summary::tests::summary unit test and it seems like the in-memory dbs do not have file_size.
The page_count was also different.

────────────┬───────────────────────────────────────────────────────────────────
    0       │-file_size: 49152
          0 │+file_size: ~
    1     1 │ mbt_type: Flat
    2     2 │ page_size: 4096
    3       │-page_count: 12
          3 │+page_count: 11
    4     4 │ tile_count: 196
    5     5 │ min_tile_size: 64
    6     6 │ max_tile_size: 1107
    7     7 │ avg_tile_size: 96.2295918367347
────────────┴───────────────────────────────────────────────────────────────────
Stopped on the first failure. Run `cargo insta test` to run all snapshots.

Copy link
Member

@nyurik nyurik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good progress, thanks! I think this approach is workable, and moreover, we may want to greatly reduce the size of those .sql files by removing things we don't care about (i.e. we do not need to store detalied tilestats and possibly other things for at least some of the files. The rule of thumb: remove anything that is not tested for, but keep anything related to the core functionality of the .mbtiles files.

@nyurik
Copy link
Member

nyurik commented Jun 17, 2025

I think its ok to modify the test with the new page_count and remove file_size - not that critical

Co-authored-by: Yuri Astrakhan <[email protected]>
@nyurik
Copy link
Member

nyurik commented Oct 1, 2025

sorry, all my other projects use ci-test for all testing, making things more consistent in ci and for local dev. For now, just add it to that workflow, but for the future I think we should make CI and local dev to have the same recipe

@sdf-jkl sdf-jkl requested a review from nyurik October 3, 2025 16:09
@CommanderStorm CommanderStorm changed the title Generate mbtiles dynamically from SQL files tests(mbtiles): Generate mbtiles dynamically from SQL files to increase debuggability and transparency Oct 3, 2025
@CommanderStorm CommanderStorm changed the title tests(mbtiles): Generate mbtiles dynamically from SQL files to increase debuggability and transparency test(mbtiles): Generate mbtiles dynamically from SQL files to increase debuggability and transparency Oct 3, 2025
Copy link
Member

@CommanderStorm CommanderStorm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, you actually did it 🚀

I have a few minor things which I am just going to apply and one question about a code comment

"martin",
"../tests/fixtures/pmtiles/png.pmtiles",
"../tests/fixtures/mbtiles/json.mbtiles",
// "../tests/fixtures/mbtiles/json.mbtiles",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is going on here? Should we remove this line instead?

Suggested change
// "../tests/fixtures/mbtiles/json.mbtiles",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! I'm pretty sure I commented it out since the mbtiles were not there anymore.
I think it makes sense to generate an in-memory db for this test to keep it exhaustive.

Copy link
Contributor Author

@sdf-jkl sdf-jkl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self review

Comment on lines +51 to +59
let script = include_str!("../../tests/fixtures/mbtiles/world_cities.sql");
let (_mbt, _conn, file) = temp_named_mbtiles("test_cors_explicit_disabled", script).await;

let app = create_app!(&formatdoc! {"
cors: false
mbtiles:
sources:
test: ../tests/fixtures/mbtiles/world_cities.mbtiles
"});
test: {}
", file.display()});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of boilerplate code in this file, could be shrinked into a function/macro

tile_data blob,
tile_id text
);
INSERT INTO images VALUES(X'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c120c0cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c030affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff142100ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b04010009ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b1b010100ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c220b0a00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14020113ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff','b0a559d767b45de037d4aefe483d3a274dff23e8'),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have to be wall of text?

);
INSERT INTO images VALUES
(NULL,NULL),
(X'ffd8ffe000104a46494600010100000100010000ffdb0043000302020302020303030304030304050805050404050a070706080c0a0c0c0b0a0b0b0d0e12100d0e110e0b0b1016101113141515150c0f171816141812141514ffdb00430103040405040509050509140d0b0d1414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414ffc00011080100010003012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00fbb8f8774f7b7216ce0858a1512c51aabae4632081c1ae1bc57f0de2d36ff4ed6fc3fa55a3cd630cb0dd59a46164b885b0c5a3c0c79a1874e376f3961815e9d20cae2a3180d5ebd7a30c4d2951aaaf192b33c6b75478ce977da65c5b45a8d9181e4960cc325b5aed0370073b88c71fe3d7a5551a6da6eddf6684b8fe2280b7e78cd74da0f87b4dd3eef5cd27fb3ada182d6f1becf0f96a4ac3222b8c71f77733818e8176ff000d1378592cb4fbb9a4b9795e3432465542e3682707ae73c67a74e315f9f52e21cbf2bc454cb6707070924baf35defd2dbddddf5d2e7d9d083ab42138a56b7dcfaee7371e9d6b11052da24c742a8062b47c3fe1db7915ee258d4e49d9b018ca6198763cf1b79fc2aac6e920cab861d3839ad5d3af1ec6c4dc3e65b66412ec5fbc9c64e327078fa74ef9ad38c2a25828414ad272d177d1dff3eb61fb2ad38bf60b6dedbff5e8477be1bb5d3206b8b7863586252cca5465140e483df0074ebd79ed5a3f057c3763aed9c5e326d920b9f363d3e011855b68c3b46cfef2384193c6d1f28c65b36b30ea364c194490cc85595bb83c107f5ad1f833adc173f0ff004ab37b906ef4eff8964e92208cacb18fb8067e6f93690c3ef290dc6480f83f30af8ca55696225cd285acdef677bfadadf89f1b88c3c69564e2ad7bdd79e9fd5bfc8ed23d26ce170f1db428c3a32a0047e5587e2ad6746f04e9771a94d69e6bdbf964c1651ab4d892411ab051ce327f438c9e2ae681afdd6b126a4973a45d6962d6ea48227b8c6db9456204898e70719e40ea319a9752d22d6ee3be92e9de449635041456f2b67cc0a7ca4e4361875e40c57e8ab47a98bbb8de25a8b4bb481c3c76f1238e855002288ac6d20984915b431c83a32c601149a74b14fa7db490c8f342d1294925cef618e0b67073f5a9f1dea4b491cef8a61f0cdb696f06b8b676967a893a7e64222f34caa57cb0c30412377439c64f6abfa478634bd0acaced2c6c60b782d225861c2e591157681b8e49e075273557c5fe1187c5ba6adbb5ccb6373138920bb802b3c0c083b9430233c6338c8c9c115bb8a6de9b892f79e8558f4cb38a40e96b0238e8eb1283f9d22693628eaeb636cacbd1844b91f4abb81eb49b40a455914d345d350865d3ed55874658541fe55e67f15be0ecbabea5a47893c2705bdaf8834e9235f2b7794934419b8cf41f7db3eaa4f521457ac8031d697f135328c671709aba7a35dd1328a7b687cfde24b7d07c45a549e24d2ca69de21d0c329fb34a8b246f864dacd9da5325886395233d46456bf873c0fe29d0f53bef125cda695a85d6a8e1a7b0b09d2144548e2459212cb8390b26417191b3904b63b4f1ff0080f41f10ae99717aff00d9b756d743ecd736f0a31677c8d8eac8c19589c9c81c8ea39ac2bcf84ba85b1736a74abd85df3f655fb469c8a48e64cc723aef38192235279e7b57c84326faa616a60651957a13d93924e2ae9f2a6da5beb7ba7d1aea75cabcaa568d75684d755b3f3b59fa5acfb997a94775e24bbd37c3afe1dbdd1e6bf9c1ba62b1b44f64bb4cd89a26230eadb3821be6edc67cc3c5fa7e88da74f05c69d6763e285865bab8b8fb3a4a6565bb996e9235271852acca7392a3195eddc43e11f89be11f1225d698f7fa859790c9f6693565bdb6427a00b2b40460743838f7efc0789b5bd474cf11df6a7ad683a45bdedc44cd3585fe8e7c89a447c07da5ce6625caef00a10f9ddd5875e1725c2e16953a38772a76973db7bbb7c2dad1af26de97eaeeb8f118cab51ca75527a72f6d3baf3f92fd09bc55f0675db69f48b35bf1e27d36401ac66dc8a26465567550f701d89f2d3857c6d24afb64e9f6561e0cd22f34af12d9c1a747751797697571a729be89c85225001dca804870433fcd1b8ca9216bd1344d1fe26fc40b4b1961bed3347d12250b6fe55a84589366cf32d64c1973b4b00c76a90700b29c9bfe1ef87fa2f8975ed4a1f1478e74df116b7295b7b04b0bb8967b611fcc4a46388dc6dc1545c61598e4b1dbf4188c3c3194ad393b68d5ac9a6b54ef676edd7d0f3e9de9cf9a9c6dd35d9aedbfdc47f0a3c21a769fe1bb75d17c4e6e2fe201dded8ab4516e51c085d4ed53d72402724e464d5ed3bc6d7ba321bbd4b4ab3b885e32d25f69b1847b71b38658181cff00b58939ec3b56f5ff0086ee06b96775e0e5d16f6d746b11a3b40f7ec9245b1b2619196372c4009b43b02a4b939de6b86f091d6bc6b7ba9e9da5db47a6cda32345763530adba75251625f2e43852c920326081b380d5e165f85ccb0d8cc47b7a8ea527cae2e56d37bad36e96d12ec8efc554a6e9525463cb257bdaf67b5b7f9f99475ef16b68963a45f68fe39d3bc47af5b4f295823b230c5751488aab1b45003970cbf2962a3e739603af67f08be28c1e38befecebcd1edf4ad5a1b73309216ca5c80db19a2e39018382371c118cb738f25d7359d33c1d7d7eda8686b757d35c24f3dade5e4b0c96c0101d1a04654b88c85f94938f98e4b29af45f127867fe17278720d47457b4d07c53a34be42db58ea31c8a111ced47922194e3794e063730e8c6beb5d9c6ed1e5d2a93e66e2f55d35fd7a9ebffd8f6713878eda24907f1041512683671ca9225a44922e76b2ae08cf5c62bc1bc33f133c6ff0e35ab0d13c6886e2c5a4484dd4e3cd9635718463329da40da490c4be039cf0057b6de78db4bb3f1559f86e5998eb3750fda12048db1e58dc3716c63195618ce7db1cd73b8b47a34eb426bb7a8fd47c25a45fd8dd5a4fa7c0f05d44f0cd85c332302ac370f98707b1ae4fc0df0cedfc1ba6dfe9f1eab3eaf1090084ddb0792d90280221e802ede381df0338af422e0f4507dab9bd7744b9b17bcd5f4186dffb55d434b048022dd6c070a580cee3c2827207a75a1376e5b9a4a2aea76d51d32eef262cf2768c9f5e29ae76a9624000649a78c347195fba54631e98a1916452ac321860d41a1c0785776a36d2eb72191e7d59bed20c84fcb0f3e4a01fc20215e3d4b13c935ada84cf6da75cca870e9133027b1009ae6b44d3ff00b0967d11894974ddb0aba12865871fba90e3ae546d27fbc8f8e9563559e7b5b466867951dd82962e5b8f6072074afe62cdf0d5e799d67887eff33bdff0f95b6f2b1f6780c5c250a74211decbe6f4fcf72bcd6ab76eef38f3647fbd210031e31db1e83f2aa71c224b79ac2de65773f20170e54118c155e32781db819fc2b34bc9046732492c3b48742c4fcbec3fa7a1efd2adda9f366b5f2f6bee9508c1ce40604e3f004fe15f699164b4f1b4dcb11579a117a456967ddf6f96fdfa1df9ae65572ec4d3c3c68eb2ebdefd177b75bfddd4d7d060865818bdb4026865285d146491ce7a673cff005e33819d65e19d13c4fe0ff1549ae5edc5969916b6f7369a8dbc8d1b46c22850b4647dfc4a1d71820baf4c8157f48d197c6da96aff00da733e9fa16913b43359432b44f76e6247f36491482230afc28ea47cc70369daf1db694fe0bd13fb3e058d27b8b41a75bc7098c796244948d840daa238cb60818d838ce057eab87a7fd9d85751bbf2c6fdb657d5fc8f9bcd3134f1d5561a11d39bef7b6df3f9b3cefc571cbe20d39276bdd42df4bd12c91ad2f750062b8b9bc8d582de3e7e61b46dc1600e4b13c62bdf6c6f7ed965693b45242f7112c9e53a90c9900e1bd08ce2bcaefec23d72f34bd1e58c4d15fdd22cc8c32a624ccb2061e855367fc0c57a67897c4565e13d1ae355d459d2d20dbbd910b919200e07b915e3f0e63b159a51a98dc468a52b4574492e9eaf7f34639ae168602ac70f47a2d5f56dbebe8b6f534b38a456c9accd0357bad622bd92e74c974d10dd3c30895b2678c018900c0c039231edd48c1ab76df682d319d163fde111ed6dd94ec4fa1f6afad3c54d32cf340a503814b48771319a4cfd69d498140ae262ab69fa645a6aceb134ae2699e76f3642f866392067a0f4038ab7494c0314518e696905c4c9f4acaf14eafa6689a15dddeb1751d958221df2c98383db68c1dcde800249c601ac6d6be2669fa66acda5d9da5debb7d182678f4df2996dce71b646775556ff00673bbbe2b9fd4e7d43c633d8beb1a7dad8d9da33cab6693fda4c92321405c9450308ee303392dd78e54a71a7ac99d787c2d6c534a9c747d6da7dff00a152d3e2078d354b37d534fd374c8ec2419b3d3afb7add3c6570af2caac555b3872814f195dd9f9ab3342f86ba269da2dbda5dd845a8482048a57bb5f337639e012428049c05e076aeb718a2bcf9e2273d1687dae1b2ac3e1f5b733b5b5d7d5f95ce37e12ea3a7f8175ef15daeac6c7c2f6735c45f60b79e5f256551bc1742cdb1b2366769dc0e436005aa9e1abe9fc21a6699e2b881b9b5fb1cada909643e64d1492897ce046559d73230cf50edc8ce6bafd6347b2d76c9ecf50b58af2d9fef452ae454925a42d64d6be5a8b731f95e581f2edc6318f4c56b2c55ecedaf5fbac79f0c9146551395e325a69aa77bfa6965f91db4da9d9c77b6f66f730adddc2bb430971be4098dc5477c6e19f4cd67e91e14d23c3f7da95ee9f6115add6a5379f772a6774afea7278e4938181924f526bce7c0110f0d78becb48d5d12e269adf3a76a5e6b619e2892264f2c8256478c0663bc86f2cb614d7a445e28d26eb53974e82fe19ef627f2a48a26de51f04ed6c74381d0d7768d5e0ee8f9094654e6e1595a49edfd7e8324f09e8d2ebcfad3e9f0bea8f08b76b86192c81830047424150738cf039e2bcc3e3e6bd3f83f5cf07ebb6f68b38b696759a436e1d846c1032ab9c157da5c81919018ff0d7af2adcfdae52c61fb26c5f2c0cefddceecf6c74c63debc2bc55f167c3fe31d064f0c78d34cbaf0fde5c4cd04d22959a2b2990e51cbf5ea07f0f4cf543b8d45bbad4e7aa97234b47b9edf0b249046d0b87899432329c82b8e0e6b9df1778c747f07a4975ab6b69639818456aee373f232c8806f73d3a67e94df02dbea7a2f82b4db2d69a2fb7d9c3e4bc91e02155e17f25c027b904f435e7bf17be0edd7c4ad5ac350d3afadeca6f27ecf3c971117611825d3cb1d8ee6604646437b609149cacde85ca52e4e68ad4f5fd234eb88ad6c659353bab81e4213148b1053f28feea03fad4d6ba6dc413a3c9a9dddc28eb148b0853f5db183fad68f961228c039c2e29a473ed51735b1e71e28d364d37c71a3dc49a8dd5c7da6cee2122548c2928d1b2afca83b339f5f97d335cef88236b1d434e33ea17132b2ca0091620b9f97d101fd7d2bd37c65e1d93c45a1cb15acbf66d4a0ccf6571c7eee60a42e41eaa412a47a31e879af2cb7be7d52dada794bef4428524e191b203ab7fb40ae0fb8af85cd320a98ecc562aebd9b8da5dd3b349ad3d3a9ece5551d1aca51de2eff00d7f5d4a56f69725d0b5ddd9439dcb288871e9f2ae7f5ed42de41e0e99b55b8b8b89618d243322c516e65da5bb283925477feb5a47214e39ab3e1bf0ebf8c75f8ed4b0fecfd3e449eee62818b307568e0f40580cbf070bc606f523dec0e5f43057a3423beadb5d2fb5f4f97dfebed6618da928aad396ab6df7f4bff005e876bf0fbc19a8e897da8eaba8de4a9717ed1e6d0189c0444daa1d9507cd924fca7038e4d33c65e0ebefb0e9f75a7cd79aa4fa7dcf9c2ccf908644656470a76af40e1b0580f9001dabbd14e0bcd7ad5a943114a542a2f7649a7e8d58f8e8d49c6aaac9fbc9defe77bfe6799fc3ff0b6afff00093c9ac6a3f6eb4b5b7b636f6d0de08374c5d81762106540d91e3386ce7803af796ba65c413ac926a9777083398a558429e3bed8c1fc8d696da36d6584c2d2c0d08e1e8ab463b7e7f9955eacf1151d5a8ef26675b69b7104caefaa5ddca8ce6295610a78efb6307f23496da6dc413ac926a97772a3398a55842b71df6c60feb5a5b68db5d7730b19b6da6dc413ac8faa5ddca8ce6295610adc77db183f91a2db4db8827591f54bbb9519cc52ac215b8efb6307f235a5b68db45c2c66db69b7104eb23ea97772a3398a55842b71df6c60fe468b6d32e209d647d52eee5467314ab0853c77db183f91ad2db46da2e1633adb4eb8827591f53bbb9519cc52ac215b8efb6307f5a4b6d36e209d647d52eee5467314ab0856e3bed8c1fc8d696da36d170b19b6da6dc413ac8faa5ddc20ce6295610adc77db183f91a4874eb9b5904afa95e5daa824c2eb080dc7fb28a7f515a7b68db45c2c7847c2f9a6d63c316bab3dc5c2bde4935ccf0b24411e477666604202464e473c74ed8ae9edf4f9e1995df51b99d4758e458829ff00be501fd6a7bab41a3f8b757b251b61b8dba842a4779091201ebf3a963e864f715609af2ebdd5491fa2e5b69e12935d15be6b47f9142df4f9e1995df51b99d4758e458829faed407f5a2dec27866577d46e6751d6391620a7fef9407f5abaf22c48ceec111464b31c003d4d4167a8da6a2aed69750dc8438630c81f69f438358ddf63d0e58a695f5f521b7b09e0995df51b99d4758e458829faed407f5a643a7cf0ca1df50b99d46731c8b1053f5da80feb5a24734c23ad172b912ff87673bacf84575db27b7bbd42ee45ea8fb625789fb3a30405581c1041ed5a3f0b2d24d526d4ef752583fb574dd425b5966b7b78516e19e1859a5388c302c0a646e3f71792055f22acfc3a8863c4372a36c736a242e07ded90c48c7ebb9587fc07eb5dd869cb58f43e573cc3d3518555f15edf2b37f8337a1d3e7b79d5df53bbb841d6295610adc77db183fad735a9fc34d235ad7f4fd675332ea37f607742f288d41c1caeed88bbc29e406ce0e71d4e7ac86f60bc7b85826491a093ca9554e4a3e036d3e870c0fe22aaead6d7377612c569786c6e1b1b6e046b215e413f2b7072323f1aedbb3e4dc535dca0ba75c432a3c9a9dd5ca0ce6395620a78efb501fd6a2b3d2a6827476d4aea7450dfba91620a783fdd407f235aceb9279e698cbb5490376d19c0effe718fc695cab1a36996b4b72c72cd12927dcaf352ed18e053a388085028e146d1f41c0a705e948646ab8af1f83e1a789f4cb9bbb4b4b7b0b9b57b99e782ee7bd75fddbc8ce049f216327cdc9190792581af650b4e5069f4b32a1395397341d99e5367f0b7c4375e5adfeab6161195fde9b189e5933dc233e00ff78ab7fbb5e95a268967e1fd361b1b087c9b78b38192c589392cc4f2589c924f249abd8c9a72a918a3c90a752751de6ee285e94f55e69541e29e0629198ddb46da7d1400cdbed46ca7d1400c298a36d3ea1ba8649847e5c9e595903375f98771c5301fb68db4fa2900cdb46da7d1400cc7346df6a7d1401e71e2ed035483c66dae41a6cfab5bc96296816d248c3c1b5d98e51caee0dbba824f18dbde9b69e18f166a300b873a6e925dbe5b3b88dee2444c7577470bbb3fc2b91fed1af49a2a5c2327ccd6a76d3c6e228d354a9cac976b1c9697f0d746b54864bfb71acdfa805eeafb320671fc4a8495419e800e3eb9350f8efe1e5a789b4b79ac2de0b1f105aaf99a7dfa284649172551d80398c93865208c12719008ece8ad1368e27793e66f5efd7ef3e74d03e22dccbe38bbd175db74d26e78862b332ab3248bb73bb693cb973839c6157192dcfa1915daf88f4087c4ba44d613bbc4ae52449623878e4470e8e3b6432a9c1e0e30722bc87c777faef80af748b6bbbdd365b7bd90a8d465b696084328cf972905c47b864f9992063950b965e4a987f6925ec958fa7c1672a8d36b1926f5d1dbb97bc597f75a7e8b28d3d049a9dcb2dad9a1e86690854cfb027249e300d7a1687a1dbf87746b6d36d9a49228171e64cdba49189cb3b1eeccc4b13ea4d79bfc30bdb2f1f6b335e49aa5c4d7ba1dc798d6b6be49b025d658d1a370a5e40007f9b70048040c115eb6c3835ad3a4e947965b9e663f1d1c75553a7f0a565fabf9fe854750b9c0033d7dea23cd5a74245432ae326b43ce385f8a7e2cd57c19a2d8ea1a5da5b5da9be8a1bafb516544858364ee1f7096d8a18820161906b57c15e2ed3bc71a2a6a5a74a5a3c14962718782503e68dc766191ec720824106b13e31f8a74cf0ff82f53b5bf9a359b52b59ada185c91bc32ed7391d000c39240c95190585703e05d37edbe24d1ff00b02e6f23b5f262bfbe9a2b992385d0ae10b41900bcbb36e48fbaac7a815c15b17ec6bd2a3cadf3df54b456d6edfa3f5d344ee690a4e719d4525eedb47bbbe9a7f56d7568fa26d8ef8723eb8faf347414969feacfbd3cf7aef32107534f038a6e314e1d280628a72d3453d68249169f59d7f15fcb3d81b39e286149f75cac8993247b48daa7b1c9073ed5a34c028a64f08b885e32ce8186098d8ab7e04723f0a8ac2da5b4b6114d72f74e198f9b20018824900e38e3a7e1401628a28a4014564e91e2cd1b5fbdbdb3d3f52b6bbbbb291a2b88239079913038395eb8c8233d320f3c56b53d849a7aa0a28a290c28a28a0028a28a0028a28a0028a28a002b95f88fa1deeb3a145269b12cfa9585c25dc10338413632af1ee3c02d1bba8ce0648c90326baaa6b75a634dc5a69d9a3cfbe1d787b57b2d535bd6356b45d37edc905b5bd86f479228a132e19d9095cb79a4e013803af61db3f1533f4a85e97a15294a727293bb7a9139e6b03c57e2bb1f0ad94735df992cd3c9e55bdac0a1a59df19daa0903a02492400064915bd20af34f8b3e1ad6b5bbfd02e7c3cabfdab6cd326fb903eccb0b84dfbced2436e48f18c12bbfa9c56555d454e4e8a4e5676be8afd2e34e2a4b9ef6babdb576f2384d66f357f10eb4915e4025d7755096f1dbd9c2f343a5da19002ecd8c12b9dccc768665000000af5bf0ef85f4cf0969c2cf4c80c108f998bc8d23b100004b3124e000073c0000c0aade13f06b786a4bdbcbbbdfb7ea57a11659963f2e35442db111373600dec492492589e98037539703debcecbb0952841d5c4bbd69eb27d3c92f24b4fc4eac4d58d4928d25684748aebeafcdeefee36ad0feed7bf14f3dfeb54924991ad922883c2dbbcc72d8d981c6077c9ab63a1f5af5ce31e69474a6d3874a40c51d69eb4c1522d048f5a7d3169f4005145140051451401ca683f0df4cf0ef8a6ff5eb79eee5baba12288669018a01249e648100507e67e7e6271d060122baba82faca2d46cae2d27dfe4cf1b44fe5bb236d618386520a9c1ea0823b556f0f6856fe19d16d34bb4699edad536466790bbe339e49faf4e80600c0142492d094acecb63428a28a0a0a28a2800a28a2800a28a2800a28a2800a6b75a752350042fd2a27a99aa16e4503207ef5cfdd1d797c570b2369ebe195b5266de1bed3e7e4f4fe10b8dbff008f7b56969979797ab786f74f3a798ee648a1065593ce881f965e3eeeee7e53c8a9e68d64474750eac30cac3208fa53d83e24528aee0bf8127b69e3b881feec9138753ce38238eb55a6b65ba78c396c230701588e47ae3ad59b6b1b6d36d56ded2de2b5b74ced8a14088b939380381c927f1a6db8dd738ff64d03e9a9ab6dc443e9c54dda9907dd1f4a95970290c0528e940e94b40980eb522d463ad48b4123d69f4c5a7d001451450014514500145145001451450014514500145145001451450014514500148d4b48d401130a89bad4ad511a0081fbd40e4739ab320ef559c753416559880393505b301719cf3b4d4d71d2a0b6c79e7e98a00d88012a39ab0e726ab5bcc8bb01655246704faf35334a81882caa4762698878e940e94c32a29c17507d09a532a29c33a83e84d0263c75a916a1f3515b05d41f4269fe6a29c17504762681132f6a7d442545382ea0fa134f69514e0ba83e84d003a8aaf7ba85b69d6d2cf733a43144a59d98f415987c4576606b94f0e6acf68177f9a561472bd72227904bd3f84a06f404f14bd45736e8aa961abd96a9691dcda5d453c0f9daeaddc1c107d0820820f208c1ab2d2a29c17507d09a63b8ea29ad2a29c17507d09a1a545382ea0fa13400ea29ad2a29c17507d09a1a545382ea0fa13400ea2b1aefc6de1db09258ee75ed32dde13b64596f235287d1816e3f1ac3f13fc52d134ed266934ad6b4ad4751054476b05d4534af9233b23122991b6e4840416c6053516fa10e715d4ed68ae76dfc53776567049afe857fa24863532bb79771123e3e605a1772a07f79828c77a9dfc5fa7ccb69fd9b22eb72ddeff222d3e689f784c6f6dccc1005c80496ea40ea714bccae65b1b7456569fe2186e750b9d36e93fb3f56b701e4b29a452fb0fdd914824329f51d0f0706b4a49e288317911028c9dcc06281dc7d158d61e32d0f54bc7b5b4d56d6e6648cca7ca90329518c90dd0e323383c646719aa9278ff4b4b492e843aa496b1a79af3ae9573b367f7d498fe718e7e5ce473d29d993cd1ee74948dd2b06cfc79a1dd4f1c0f7bf60ba91b625b6a31bda4aedc70a92852dd474cf51ea2b71e5453867507d09a566869a7b31ad51377a7c92a2920ba83ee6a2925443867507b826818d907155e518152c9222f05d41f426a09e545e0ba83e84d059525e841e9cd436c333f3daa49e54424175047504d436f2a25ce0baa903904d202eae8da7ddcbbe7b1b69a560a0bc90ab31c003a91535ce8fa7dd4af2cf636d34ad8cbc90ab31e31d48ac8f0ef8d2c354d3f51be9836996b6170d6d24b7e56342caaa4b06ce31f360e7a1561daab7fc2cbd2e6b9730457575a6260c9ac408af648090a18c81ba6e6009038e49c282d5769197340e827d1b4fbb99e59ec6da695bef3c90ab31e31d48a75c68da7ddccd2cf636d34add5e485598f6ea4562e9fe375d4eddae2d744d5ee2dd8b7d9e686d43c772818a8747ceddadb720b119520f4229969f11b4abb85e4486fd78431c7259c8b2cdb999709191bc90637c8207dc24640cd2d41b89bb3e8da7ddccd2cf636d34add5e485598f18e4914cd4acb478926bdd46dec91140325cdd2200074cb337e039ac29be286809258086ebed51de4a2249a3215065d1036588dca4b8c15dd901cf45622efdb1fc5b73a5b68f693dddbc17d0cffda0d1816bb15ff7841623ccca6e0a5030dc54e78c81de2aec49c65a47566ac7a7e91ac225e8b6b2be598065b811a481c7621b9c8c565dddc5aebba95c5be8fa1dbebd7c9913ddba22db42c085d8f31072e39f914311b7e6db9196eade03f13e8d67aa41e17d474efb05c33bdbd9df4133cb03385de44de773f39924e57396c67a63d0f44d2a2d0f47b2d3e008b15b42912ec4080e0019c0e066b095651578bb9b428ca4ed256feba1e673fc13b8f116bb05df89f528756b33049e75ac36cb0059cba98da375f9f08aaa06e25b83c80483e9375a069d7aef24f636d34ce30669204673c601c915a145724eace7bb3b214614ef65b9e732fc14d36d75092f348bc9ac9a5526686ed7edd14b26410e44c4b2ff001021197391cf02ac4fe05d5de569e77d03559dc7cde6e9ad0127a0f9fcc90e318e083d3af61df5213819aa55ea2ea4bc3d2e88f3682d9ae3c457563aee8da5c77bf678eea39207fb40914b3a1059e34395d8bdbf8c0ed57b5cb7d1ecad2eb53d46ced9d214324b2bc01dc803a0e0927a003a9e00ae62cfc5a6f755f147899ac2ead5f6dae9d6b617f09b59dca86281836701a49c80d8e83a71cf5161e0bd5758d4a39bc512dab59da98a5b7b1d3a57f2a5995b7f992ee504ed2136ae4ae416233b42f739f224e470463ceda82b94ee3c19aaf8aa512dc59d86856d21532b4b0a5cdf3a7195c8f9226c0c6732f1e8456b2fc21f08c92bcb7ba2c3accce73e6eb05af987a6d3316dbc71c63a0cf4aec68ae19569cbad8f423429add5fd4c7ff843b40db12ff61e9bb6250b18fb24784006001c7000e3e952cbe17d1a79d669749b19265e048f6c85870075c7a003f0ad3a2b2e67dcd7963d8a373a1e9b79334d71a7dacf2b63749242acc78c7248aa1ff082786ffb66eb573a0e9a754ba004f78d6a865900f56c64f41f90f4adda28526b660e317ba38cf12fc2ad1bc63ab35f6b2d7173b71e4c5049f66f28ed0a4ef8b6c8c4803ef31030300553d33e07f85acefe6bbbd86eb5f9642485d6ee5ef11076016424363a066c91d88aefe8ab55669593d0cdd0a6df338ab9ca7893e167857c576e90ea1a3404233306b62d6eff0037de05a32a486ee09c1ef5b93e83a65cc8649b4eb49642002f240ac4e0607247a0157e8a8e693566cb50827748cdd47c35a46ae6437fa5595e99061fed16e926f18c739073c5711e28f835a6dc3d94de1ab0d2b42bc8ee56596736a5a33185394f255955831da0838e327ef608f49a43d2aa35250778b14e942a2b491e343c51a5a5b492f8a3419ec353837adecafa35c496ebb0953209fca29e590bb8316c0523278ad1b1d5fc31e29d52e21b75b3d42e5416337921d650a1431493187dbb901c13b772e71915e9d3c31dc46d1ca8b246c30c8e3208f422b9fd7bc0da27886da386eac96368a469a29ed1dade68646e19d248cab293939c1e73ce6ba9621754723c3496cd331ae746d3eee56966b1b69a56eaf242acc7b7248aaf79a3d85dca659ec6da695bef3c912b31e303923d2b3f59f37e1cdfdac724ba8ea9a15e968a269035d4f6d381b963c80647465590ee7c952a064861b5f61e35f0f6ad7105bd9eb7a7dcdcdc2968a04b943248319caae72460139c74ae84f995d6c62ec9f2cb71d7da369f772bcb3d95b4d2b7579225663db9245565d22c2eaf5a59ecada6958105e485598f4c6491ed5b0e01cd516fdd4a4f6028bb2ac8ded17c07a469b7105e4d6cba9ea910e351bf512ce09032549184071f75028f6ae99807521b0c08c107bd436e0aa0cf627f9d4fdabcb7272776cf4a315156486450c76f0471448b144802aa20c2a81d001d8553b9f0de9579abc3aadc69b6b36a50a7971ddc912b488b86180c46470ee3fe04dea6aff518a502926d6c0d27b98177f0ff00c397f776f3cfa3dab3c0b1a2284da9b50968c1418560a492a08383c8c57468a14600000e001da9a3ad3d686dbdd828c63b2245ed4fa8d2a4a45051451400948ee23466638551927d052d67f88b4fb9d5b41d42cacee56cae6e607863b878cc8232c08ddb4119c67d69adc4f45a1e57f0f6e26f1df8b6df589234b882179353b893236dbdc4912c76d028e4ef4b6625c6701a4c8ce481ecb59be1bd0e1f0d681a769506cf2acede3803246230db540ddb470338cd6956b567cf2d3630a34dd38d9eef70a28a2b13a028a28a0028a28a0028a28a0028a28a00290f4a5a280236a89aa56a89e802a5e59c37cb189a31279722ca99fe1653904564f88fc37a7f897499b4fbf8035bc8320a1d8f1b767461cab0ea08e456f30e2bcf3c77e3d97499c691a3409a8f886472b1d83e7698f6a932c847fab41bd7e6390482a32c40ad20a529251dccaa4a118b73d8c3f0c5ddfc1ad6bfa3de6a2dad269b2c6aba83c0223b9d771858280acc8be5b161c132f418c0db917ccf317d57afa567f873469748b4b96b95856f2f6e1ee664b67668909c2a226ec615515178001da4e066b42162b3ae475af48f3e3a23bd839889f7a979c532c8892307a02335263ad7927aa03ad3a994f1d2801475a7ad3075a7ad0048bda9f51ad49400514514005145140051451400514514005145140051451400514514005145140051451400c3d2a26ed529a8db9a00c1f18788e1f0af87eff519590341049246b21203b2a9201c0270481ce2b85f0f68baa41aadf6b1ac5edadddf5edadb5bb8b6b43063caf30e5b323866cca4646de00e2bb8f1bda0bef07eb76e63497cdb299764919901ca1fe11cb7d0726b9cd226373a2e9f31766325bc6e599b713950793dfeb5db42dcad9c35aee6ae4928e2a9e712afb55c93bd52230fc1e40ce6ba0c8f41b024c2a7daa4c726a3b06cdbae0740054a7bd7947a607ee8a70a4ef4b400a3ad3d7ad3053d6801eb52546b5250014514500145145001451450014514500145145001451450014514500145145001451450030f7a89ea5351b50054bdb586fada6b6b88927b7990c724522865752305483d410718af9d6ebc676da1ebda6f862eb53bad32ff004f7b8b282d2d4ac924856587c8f303b00c1ad9d4827392cf8219403edbe39f1a5978234fb5bbbc7044d731c0b027334bb8e0f96b9cb119dc40c9c03804e0579a5ef876f7c4fae59eac7404d0a27bb1753426f14cb31040dd70aa84676af012423a06c8c81dd874d5dbd8f3714d36945eabf23a7d2a4be974a81f518d22bd65cc891f0073c7193838c64024039c1239a5c812f27031575c64d67dc021811d6ba095a1e81a71ff004588ff007941a9b71154b48ff8f0b7cf5083f5e7fad5a2dcd7927a84818e69dbaa10def4f0f4012034e56a629c8a50680250d52839aafbbde9ea68026a2999f7a33400ecd2d47ba8c8a007e696a3dd46ea007e68cd33751ba801f9a334cdd464500494547b852eea007d14cdd49ba8024a2a3dd46ea0079e05216a696a6e4500292698c4d0c69acd401e69e3dbdbb5f891e14852266b458a77630942f965dbf3aeedde58c024e31b820c92401b52371e95cb78b3464f0efc46d0af6ca4bb8e4d66f2417a5a67749f6db4a42e0c9b542ed42311f6fbdce0f4f21ea3b57a70b7246c796efcf2bf7fd1159db83eb54ee00d8debb4f357243daa8cb200493f5ffeb550cedb4e902db440740800fa55add9aced29b3a7db918c18971ebd2aeeec8fc6bca3d324079a717e6a20dcfe14b9c9a00995b8a7ab5560dcd3c37e7401601cd395b9e950ab74a786e68025dd46ea6139a33400fdd46ea66e34668112668c8a8f77346ea063f751ba99b8d193400fcd1ba99b8d1ba801fba8dd519273464d0049ba8dd51eea3340126ea375479cd2e4d003f752679a6e69377bd002934d7348c7069acc680389f8a1a44f35ae9baf5a4725cdd6813bde0b546e668cc6c92aa8c1cbec66da38cb6064034b697d6fa9d9dbdddacab3dace8b2c52a1caba30c820fa1041ad4f18eb3aa68da5b4ba468337886f18ed16d1dc4502818eacd230e3e818fb570be0f8af7c309078735616d15cac26e6d56da4668c44d23fee537007110d8a3fd9dbd2bbe8bbc6ccf3eaa4a775d4e8a53dcd67dc7391f5cd5e95b2318aa13e0e47a9ad883b0d206dd32d31ce2202adeea86cc0fb2276e3fad3c9c1eb5e51e9936ee0f14a18678aafbfdf34be674f4a009f3cf1de9c1862a057e99e697ccf7a00b21c0c53c48077aabbb34e0fcd005bf329c1c13553cc1c51e70a00b991464554136d3d4d48b30614089f3464543bc5064a064db851b8541bfde977fbd004d914161506fcff00fae832e703f5a009b7504822a1df8340933c7eb4012e714bbb8a84bf349be8027dfc51bea0dfd28f339a009f7d337f19a8c3e7a5377fbd004acd4d635196e6985f8ed400e73f8d723f11ecad6ebc3af757178ba59d3e54bd4d43c8f35adc46c19c81d814de84ff0075cf635d4b37e3f4aaf211c83cfa8aa8be5699128f345c59e7de16f1045e28f0d69baac524520ba81247f25b72abe3e75faab6411d41041ab472587154fc5de199349bc9bc43e1fb6845eac4e6eac638403a87ddc0dc318906cc2b3640c9181b8910e95afdb6b493f924c7716f2986e2de423cc85c1e55c02707b8ec4104641af46325357479ed383e597fc39e936d228b403be3fad35e519f6aa969a8db4d06639a33ff00021486653c89108f6615e61e99619c67839a76fe3dea9b5c20cfef149f453935223b4c06324fa77ff3f8500590f4e593dfbd532db18eff0093fdea55ba8b68ccb1e3b1dd8cd005f0d4e0fcf35556642bfeb14fd1a8f3467e56cfbe7fc8a00b41c62937d44a4e0753f85381249c03c75e28024dfcf5a0b91de9a3040191cd21818763f85004b1dc0ce0f5a91a504553747887dd3cfa8a8beda81b61601bfbbdcd005d2f4071eb5514c8c3215b1ea41a70de79e481d71da802c990628f3463ad55dcedc282ff00414d6f357aa3003d01a00bbe60a4f378e0d51124b9e87143dc94383d4fa734017fcda4f347d2b38de331c2abb1ef85a512499e87e8680347cd18a6f9a327f9550f35b772403e99a559c8ec6802f890669038f5aa8276c127f9537cc90f446c7a906802db4b8efc530cc09c66aa492499fbadf9540f77b4728c39ea54d00681973dea0924f949cf4aa8672e01dae7d30a6a296ed9464a38faa1a0092560467ad729e28f0d43ae859e276b2d5601fe8f7b01daea7aed6e3e64271953907af5008dbbbd41635cbe573d3e5359eda9c67048723b9da69a938bba2651525667ffd9','d8018fba714e93c29500adb778b587a5'),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huge Binary in the script

tile_row INT,
tile_data
);
INSERT INTO tiles VALUES(0,0,0,X'524946463a2d000057454250565038580a00000010000000ff0100ff0100414c504821000000010f30ff11118220db067de807384023fa3f017b8ffff88ffff88ffff88fff180f0056503820f22c0000b01b019d012a000200023e6d349447a4232221291589e8800d896909fc0c71957115da518b7d075b4f13ddd12a8ea377f5204fabffe5f834eca6c7bb6f76f3347866b313fabda113c4fff3e0fdffcc57146be48e8a910d7c91d15221af923a2a4435f247410e32e3c7d67961d0de60fd5ff76600408d95896c4a8a2b812d89514570196695d9330069e8352120c2a23d6d1b0b6351c64b685b05a97b14ff5d4561791aff8438f8e3cc34a781ab2cb6b40d8951457025a8f3023dda92bf413dfb883f8d51b4230c17ab88217f186171ce999406a943a2027669192bfe7cf2a7c6cd9ae8e9f5fc5dcc39125d8e625aa7ad030060f6bf967a9e486562c78b3f8f692b12d89179ab9b68f69820486a13f8f5e311eff28e392ed7d24ea5453f10b0a09c2d0a61209fc00a8bbdf22965379015d145795ebbc67042b0a89e1e1cecc6c64d13f34887c77ad8bae0d8933cd894d9fcfb3c9af880f20939d82494d31fc7fca7878046b51786c4c64b0d3b1f41cb3ea670f5df76008d224b0459943261201a31f8b78c1cd81231633777f95db0c4d0bde8ae0517a602411416c062bcba5fbccf14a44c976559803f20f54ac2ab9b7cd9c8f1e1ccee10650d0580bcb51574e0ad41223c2f107e65ee0bc2d435eb0c5ce4d6297e8b9be05f00c42df120c1630576852347888cdce0f264dd4b6917ead593d924542b52d60b2a47dc92e1475f579cca1186c17ada4a4c36f6179653a639075db0ba9c2ea164273588652bbf4ed1e38e774f1919598d572741fc4d15252ea25398447760bdead87434e29b0ffbc0fad648214f8e5dd219d587ecf39f43dc4a6045e6ce55ca97bfbd19edfa69000024957a755095762af855a9e2b0bee629cac6127bfe363343f1ee9c92002a6e894330c38135d31492ffb5966a6eb1b41073ee57a8e77b6d168a1a13f9aae1f4c8020c4d53d8f5e47527fb3f1d1b6475aadf6b04e5174a4be2077abb2233541957d61758bfbfc7a6d0ff0c7b84c634c6f019c40def56e25cd0d688612bf8b81cb83ddb931e06fc0e0c170f30b7098994a2366ce85ebae857e094f9dafb636be7d8088e40c5e480f264b9cf714a2f659dbf7564b716992b7f6854e0b781dd70a550085c62ba7feb424f7924ffd5478e29a89df5bbde5c81159e05477d055a3d9b3c3a44c3550450982317eb7f5516b0ec834ac6ba644139cc2263d73ae4f444fba56172371f97467bbc23475f90a348056d5586e3555b68170068931bf95b3b03d83fa9e8835de8971f5a32dee091a55e33435c74c56498805f1f2b1245becb42952d25b32930d1a3fdbebab9a283a860c67407f4016fc1a42c94098294e480ae521d3a55bd1ed2423776f429c37814e9a6e36df41ad339cdbcfe4f05c8826f5cd889d0e29d78ce144b545681d077beb8df1075c7062e866a754d4f13d327f34fab5375df93963af010933d7064c92c3fc8ce4500c9158d0534b844a02fcaa0840fd6f42379f7bcc1d575ef8c167e74760d7beebcfcf245a2b0291a79a574fa11d6e2619ab8ad6acf20991aef238ba62fe06017242e89dda0f11734e0b694172624d684192ffea2fdf346bda17d27566ad11496cc9fbd9a1dccf06a51d1a904ade8896f450d95e87727736c12af558146c3e85dc465ee22af9fd28c33ca92c21fd9430ab34758928b25f760c64d8fd92624578594a9805cd7529f87e32828e805c40e7257954d55516a2454e70639ff306f2816b1aff9b1fcade1ccb0a623609d0b243203cdbc36803411383c7b1f4b4d5c2f2e45b99096c7b53709da0182fde00a51d06409903866eaba81bf1d9c06f22f62e96e3a56e4da0de5008fc9ffee668fecf23c295e08d24286d444fc74563b41271ee5b686a7e1d5d919753a297a712955a1b52a946adc72ac43c800c99d660d406e3ec5b8ae25ffb67d1dfbe852adadd6a8869d24bbf955f4da402882767eecc6832b63b97a018b8c8abf34268fceabd85a510c77c2560c2374ddcf218c3782b0e3f73837aa53a12796f674fc756fa0b7c522e19a8a4faa4e89e40f75c1e6f621e9a0488f8d660bd75148625eb6315211c14b3293af534346fea2ba69f138da56a6c68b1521a6e1e3c375e7dff5c60da3a27a7b64f4133ff20b065519b5b3e0e727a189a6b29b3e4548e249dba86a4f2f1d2bbf20d56b902bdffa0a06ed470aefade37644061f47b0b49e350050ff3b4546e622f6102b597c355edafdcc5d3cd8da1aa5d8870260d2dbbccace1f5c350a9e96d830173141861b06168b9734ee6d1259239fc0a544b4db819e2e936cd69254db5e4b71162b158f4d6855011370127821b6d8cf8d937650c66a913c2ad4125923a2a436b3814a567d4879c82cefe935755f0396a814b1c91d13ce043b55ca816d16886382f34c08f9600f0540f36333a2ff748d52a28adde50cc295b8894c5b451af92184f96bba49df7557b87720932e34c8b95daaf28d7c91cfacb1c60348a2f4ab2e2f5772e4fd8a2b812d46ac6c4a89bcd54096c4a8a1bd6c3e4310b0ce8a8ae04b6254515c096c4a8a2b8126dd7d1321115c096af6f4641e9a33a2b4c689c886be48e8a497e19a57ede7d298cc2d4b064f012311e0a19f4d235ee94cfdd8f0a77fd8cf52e4da24cd5a8224a162b23d76c74515964c2498e94ee4c4b6250c3deb44b64c8a23f01aff25a89fc4e2f35cf489c23c3cb57232e151f125faa1fa4e403f1f922d0a462eb452527b71a940bd44eae389cb18d4bcbfc0a0a0c03e0a32382d42c320e38f881aa3e10e07c3da0a07dfa73d480b1b07bc85aba8b9e4a04d80acf0aee52360203e6b21cb91c5f296ac7c4058fcc31611607a49ba82af6f48956f4261df1026cb6db5c3f146ac03ef9656a3b057c5377d0deadced423cf2475d0cdab812d72db8a04591086a229de0a30a174b5564b43c570f52573198f8f8ed55c6470526ccc5191fc24a89c4b122ecd04fc3237bd739c2fa8ce7804e308504b6265d7546aae40ed2de74d18d1411c68cb951bea85a418f6b8b2f32578a809ce3959f28530b42e1320b7426b0c31071e1515c076f623688dabcc019d435a0cd1be030b38870d1814905fe867d03d4b715f7dbb60d91cf39778435a896ebfb2b8744bc6d99e451a3d258901ef33a67032797edbef2034f9f64fc3248ba76874e041fe5816aaa42ce18de6aef433c73b0496016ca89055882dc731eff3813368ec000feeab100000000000095bdd55fd191851e5b4c4ef5faec41ee20de55394b92eda3f424aad15ccd796b73b56aab4f5bac221a371922f30de2f710e0492f2dfb302eeebf7fe418b7c90231d16be298a44716ffc6f6cd6aa60642f393ebfd190bf6a4f068022db1cc4ba18a4360000000beae958ad54a8b91ac44c7d3483a9055ef2abf49f2ef328fe12b368d5fcb569d63b67c17aef1a0a74bf9b0f980297d4406cb623d03a45302dadf8614b37e2fd18c16e957184fe1d577eccc056716f1dba8efe67db0aae92d2ed658070d3513ff7bdafcde0d22b0dd132e37388b932df1a1d9b4d78f9f159d9648b2d6b3e664f840df6e9c18534add244b55fbb343f36903af92d31919eb184199cb11e5bed5a92230b38b8a0a9a17ae130dcc5d251b14821183791a3c31fc3689ae1899a7bc10e144a721c1b316560dfa7359a566a0e7a05da770fc77c1e8b47ae7f9db434c6ba5d2f21a5bd42c000047aa5db88ce13aa2dd3a6cbb6f7fb5ea4784bb23bdb4f42dcd184ad8c5b1d832c708bcdbadd76063affa9b1403bdcb5271d7e229299cdbd2bc0cae8e23f59661c65f9726d8b42eb7aa83feb3fffc615050d9909388837ec80b55abc12dc5e10b2118c72f0b7eef221236d9a325dbc175849adb0358b0a6a4849072e1f96d33b682a29322e998fae890de58ad196d09338f170aec62122d703d95783c052dea1c3d1bd486cadf4701bf5544e3b687b249d41f8de83df689d160a8a9daa1d539833d7a3c4d301ccb5ad81f30387ad201c340337d5b01c7db1f6e95037b122ddadc561ce4d89bc85f0137aeb81e19140d7d213856430bc4112f7d6c0f6158ac8e82f61d1503edd29c7b45825dfe150d99c27159320d116eb56d0f01a34fdf3e71f47dccd930eb90011717e6df76175ff9ba374ae4427fee420205549ea4631f19e9b6e95bb334f68a308946d38554717b51d95644272c4ab5853f399ad0c27ebd293db393dee513b00c132bdcd601d41cad4bb8ee094e40ea3b6a9bcc1fee135818ad8522a442eebff8777da04370c51a256941bc06e8d1767c608fb7c2421951f009a93eac96e654df390f988a768a61de688c4eb513c59fbb6cad41431e27648a9809b11cf8c986a152575dd4b10f8b596eb0766ce7ae895dc91ce5f9a497f035020ff275399d8de4ff8f3c78f9b154c1b80d244debb38538970c505e0628774c327570c69e04cb2177f506482ac8e26367ef54e9d8a867f6a3f259819f8627115cee2b203ae4905ada5be0408f704724e815f330d80cd8492e7a1a59e8b8770f46f22f8e2630b5376159bc2dd319011425c60d382d7760503004bceb4fa84db6a23a895b501a2207e06f231511b7f3b92bf77f1a978e613305262516b7d64238f05f85ede1dbc6b596d31a9fc9fbe691b2a98af2bb2f15d7641d3c0dea199b49e9deca5776114a1b01612acf12a6921f74e2e6339703bc36c410f5f5c3b2b668daa4c84c246ee93875f17ada4b0f0b2d9e84695c96f5f471a11fdc6a47290bf567e1269daa0899f4a0c81ae44285946519e675441f5620ce92952c8a6a8e68f39760d00ca81eb753967b040e6629e8048ec4dc062be3722e93a33b6107b4b8f1f6392cd50a413b577c91803e8d9c79913862f56242e83b1c8414a7cf9d5f22ed6da06fec9c22500d1a6862354a48eeacaf04b2b7cfe968eec953ffa76b2013ef0287b8c49e66fa4af0bbf5b09bc14b233512ec649fa21b6736152760480de7a81f95ff082dac7ea79a8c32ee4e4f5004d0e2b96ee458ab47bf680ace618a14542917fa68d6506a78242d7d2bb47de6d904de0b3500de3f69717d5642d304674fd5cc6dc255c5ac5b81a5ad563c33ae1677f5bedc5ecff79b7386832b97035cfd1a1313772831fb4ec072b99d42d34241d19ac0f1287c49a701de1520dd4860288c4ca496ddda079356b2a0029b62369fd8a49a82e3eaf8e512c6d827395b41267dc68451c7ca293c9690e9ea05174988fdf4d95d566f0f37bfbb7d8a27b2e7b94dc3adfd7aad8d20b3dbf7d95ae82bd42312ff59561a32387176592cfa0b7f70e62122094da2ab13e86f0543f1677f6ebda30688d8cac147a6b2873f35c536e73270d3c3ec63ee626f2f8964f7bfaf9cef3574f945b13c36130e31dba3551d8dc7072e3cf1783d947a33251d8de82175e46316db401491946704a13ac12fcc76660257755c780d855985d843ca7c51deacb0c1ceb5849694cbf4a1ecf7b5df4cc8a926cc24f4307952b7084a4621c6b1785d926a6fb4ba8f25aff25630e3c2d44609552121f21536642f164190658c8721683cbe1a911fb404147336a1c2d3434cc5a0aeec9cbb56371b374ec0de6e20dea2a566369412c58ec55aa557300da49048420f65cca5ed3c8eb3c1ab3a6b3168c92b7dd4c45f2bd19f1b6de7882c1ba6d2d4cbe93f18910b8f7b8ad2cfdea6850ebec62985cf1fd071ba2af34a4fb10d4f0d051db25b3325e8e7d6b6f7260196feed0d640b5bbe5da05df858f17d7bfdb5fd05c0e335a5dcdf064797734a50b1441c9dd27028f2a8d610ef372fa828206618fe54df709c37153fb3185376b98b0ae705088d6f73907fa29d9856fa28ce9ede86f1a7c8ea2bcfa32c5a6db6b6cf3beb710ec408259fbd0b7af5c604a155d266f57904f672b52fe0dfdecb0653b29990a085d154a04bd048af8a36175745b8c64f3c67df40141385d364233b2d3b90d7c1b401b70b7fef70d441a9b4bfe197ef8f77411004b109e5cc24c0324f1c27234be0a27f2fbeeee6523aadabbc1505d65d7b3aa4f72571a9d5ebf497010a06a233d174731db7a1b9ce32de95ad9145048e155e49dce7eec14d4204b79a39161edd3bc51b11a611b2337f74dd3356443de639e19b118527cb87d34adbef6c33ddf5a4769680d67906c120c2f7d99eb174b4c8038f977cf0d47b6acfd3d9b41db7e081ce307a9e4c91f034b3827f5a647202ff4363de0361aa1c0d81697f2fe0f6414ab0e74661b8b99206b87c76118840259540b89c25014ab78ad3bc9858af1700cfb089baf1abbf4dda060aaa63b6c990ea7fe0d0659d548b03621e6f5f9391973a95dad0ce4e4f7904fff4ee515c4a918aca1b583bde471fd8eb68361d4bf0d0d1079356631a249b8096a1a68f31be0af8078ec93a8dd3b5837737722b33536366e5dceeb0b2b2e7f9ffda76ccf6cba63892376f143dd81f8b480ab2da0d99cf9632da09595f7152e9c9b4b174106d1ba9a9b136e90853e4ae8f358c90231445f4b722b03115ed0b48cba7f5153c34151ae534b383f5c17bc0e3d15c415a53754ab20b987fee3ad134cfc00bdf0b79f49e286304d42c6bc4052f37a51b13d3e6a8a0508902efb92ce62561eed3148464af5107e0668b205296996c9523713b40f21f79477e9c2569f88da64bbb93033185897402552ecf1a2d9200740f2d9283eb6cf29b2e5346f3e534b473ec16d0dd6407f4d060509ec57f68f2a00a50b40234891d1ebf66979fc56db845873baba519c00373899b9a9db087579d470d664c325014acb3b32e6f0369477bf47e5c9d3e1e5b6a723858a73a8f40933de2539ef6929bafa455d9cddcc52b048b0e3faf7968bc236d355937c860661f6d7d32f3f8c74a289454667023e153aa66635d3dacb88ccbe0558f8ed03783ba0f189e9cf71225c1043249a247c25fc48f7d3d0f756893e8b460ff77b7ebd200f431066685f6751144fb4348fc4ac23b53946afb0276067a6105204c3e0959dc9d2270e01701160da02cf4e102460828442cf20742a76b55085456ae11c37e4d15cddb60b2cb2e718d1573fa6a025b2171599af70f0a0e6f23c694fdc2b33548892a224d4469f292ba92d04f3ad2a44525d7c4e62e0fc3e0417c04dabfbe0a433781cd085985b1230eabe4c7b8938553cc6c4800b5451719870846ccd83e05994b3e800a810aa5f8e5c8e0c04d93ade9996c17af9f7a340c8bae1987507409574fbc1f88b6f8761b6622fa37814d6d3db75103aba01a45098ce9e38d9d55eb6a6b342cb7e08c014863b51f34ec76e75427c17d665db7270bf2ec40613742bf14d683499301c7b8506d8df13e313088031a9c3cb6715e37a9dfe684a0435ff4e03b318ad8e602996bee7a2dab5dd2859318de1d581c2f24aa48e4a4e7013563d1131140cdad8d64053f179cfd638d53243880885628cc1063634b8b4886be684fa53a3e2e914121dadbe616803616a633babcf95878035be33cd95a365d785d362553985b4941655706caa311044bbc8bc766084a0a1edf475470f57a4e7b0147dc4bb7b8e1cc89df97487471088728d62a561c327c4992bd0c2199daf41b5ee22ecefc0cbf195d179289c03b6f589061239954b00465f06095c8a6409ae4b6c140c7cfb0842e183c60e43df71d32fc9f80c143e15d671341e638f2f142a6fd6ecda2b525047f1ec0b685ee41ebf35b24a6e126055f1fa4591af2729e1746dd38861580617cd6c4fb4e9a4e8e057eb5edcc3a381067edcad586a2edcc2235decab8bc6bb5785033d1b13f33bd88134d25f53e975ea2164e278847c3d29e1ba880cdfa67096328db1aa20885aa821e97420055e33cd98568f7f2ecc59f5364f1ccd17919114e2f7b8ebbe8c865e8cd355a8dd12b5bbd0e0ddb1ce51b6b4ea3687ce1b5aa6b6b0e91a490d3ee7a91b66515e8476dbcfbea085b6cf46cfb62e1d3a1f7e51332a14805bccb4338ae60474f19ed26f597d7ef86751327f0b558cb12947eb09173fd2b363d54d7fd23ad2d26e02ccb3b7368598e38c38cd8f14ba7ff99bff83308e8f3126a09c74bdc4c718b9b4d126eb521c8086fbf2b15047fc72dce5f50a187aff98a8f5f994ca25e934c6395fb87fceebb220ccfa6c6b676aba86003533335c30ba40d35e0406e4ab918d95e1d06be94341ffcbb466feb718b2d7af8dd70ba9131881cfbb8085a90cc8707e8d7417906eef2aecd62e1db68e78e9098c7f219511f19c177895052534452655bb9f594d9cc34b7b1218663a9e2e49604bf7a4dbd7b70b452ff841399c19f72f0c5cd70077c25ab17592da61800ab9c5cbeb49e210f3a2e4f19adec961ec7dae8c91f2e2ad952412743618b1cb7aa99489f495bf0107f1f85c12861aee79c3426daff54b701100bafcf8bf65655753910dfd2a5fc1138d8e45ca478f10b714b3929262feb04e735a0b90e57668ed807ab5363c341ca6ada00146d1dabbcfd763a33bfe6473b39395547c873624d28e1a457d26475a6a626c2cf22200aa058491ae2c7709b39ed9407977a62f438d171b76d2c0fca8be47f55c45e9c513621936cef8c692b2348ff60631523453a8eee20c0fcd85af5ad748377e98f6516fbfcb4765a4c42f760e984a458b38be001cde5d9778c10e8b80cb18a797035046bc5a9817e42a80d39c346e41046cf15767618a2b9ec7347023ea9d3b2a7b0377842c9b9bc89f3411599fbeb58b25977526ca415b6f9ba799890aceb7ac91fade196d40bd8484977e85f3956aa31a837d828d09dd9990cfddd8c332e46bc44efa9977612fa8f5d94d227d84378d3a0b285684b1f0993498a2e2ca29084848c41cc5776eecc3834b16422a8b403a0ecb4ab2f658f75c4e6a18a24dae1ef938a7cd1a1ce3003d96672d536040af2b2b1dfad1dac7a293fa6fea4e9e09685b570be4eb25e8df2bdb861d259f65aae5651f44c05efd59f2ae049f4b4d125c80a03f40b5b8151b38907c9c7d39eb64543d896cc0aab8a301af020e09c5af88fcc5c091a0bb695afa137ea0a8845e8cca9f33f44eaa396bef0e629fb2745f23d765661b36509c32dbffef481d85d30d2fb076e65e51d9b8424a60a5ba15eee4181dd21c0ed59e6e45be53aa56c1bfa338b984678a01590d065bb5df163c259068722017eab3988fa279a0565cbf32ff3e0229629ded15e814aca11a841303a3a08bd5ca9cf11ff76d8c5d55568de5ca4b73e7ab1c6649482b48f01fdb976faf49263b3091b657af5a44bb9733fcc3ab34da8452b02c75aaf0346398b69146cc2be94b486d247e6076f6bc8b99d912a54d73b81384bbff376b0ea8e345475a0233bbc44635024842e715b5c6318b4d69484d5db5d89dfe16f36e3a576b3c28a5b3f475e67e71f97465a29c9d815c429f001120c5fd7826b1742c00a81f63476e4d15587eff29c2a56713f362f6320cb1e60fb844ac31fc4ca45d4dc984c5aee54bf72bd07e4f0f0d1758d04d1ee4f853faeba23f731c656b6a854b6a3bc7d8e9b64de9d194a8b62cb97e87a0a0f59e6d8fcd365cd028c9d676cd58ce842ffbe1a71097feda22b7fb3a9d44aab054a9a889c55f494627e65c2294fa87ed081cfdf6424af07dec144190b9fec011cb393138e6a410c462136c512fbbaba54bc9f39a9189e3f7931d31a6726ead3a25e1c19c95daf27491e877888cf7416efdd9c85a4d8ee797a27c767b7ea34df1e43a6d194ac1f6937a8683427cea4fc374e06901f0ebeb4dbd2f4ac50eaec57b5f27ebd6b50038eac548be12f8cc4ca30b69a94552a00861ee82e33c739978c6d44f399e5d6a7f36fada3f941d0e06fda693f278256fed5fde53f3dbcc8aaa6afcd8accfad005c30a6d6c375c2ac511e67b24dad0cab3da882154cd7d5ec156612579d695c920fc1623ba8800e03c3e499b093541a21abe1f04e0359a7823dd7fc85940fad7387a66c363e7e93330938341dfefbd6068233887e914389a3860440d3402b051f175accf4e1f4133ae75e219eb478d07f354dcf1207bd10ef5520e743b1eff38f1c5674d857e6238de7ba9e2776ac8e5d4d42b7833252dcc057e52d5ec60f8731953dad820eacc9bd48b64d4103ec6417d9f9f2445436776c51daaebc879ac3c86f5aabda047f3a7b3812371be73cfccbfbebf24bd5178e2ef5142b5a1cff00c6ce9ec578b6110924d952dc1e0b7d7ea8d14e8298505b3d6b27588476424199985dad17a4b5ac04e20608c7ad6c4f6f2c2694cecb82202fea9929dccbafd9407b13ba1b330a21a700232e908f3e281974c1f098c5b9adb7480e5460f7aa7ee901634e2e5c03b5509ac02e2588dba04f15333bdf3ea67e5c413655e1d9ed4b682ac1fff931f6bf2bcf86c5aa5ac7f10c59fa0a85c9f000cbfaba34983b5c9cf3beb68dd873560b77562ecf79ab7cd2b9f1c2347179237e748bc6b90ffb6965049ed39ce5c8341c3963c7053e15469a1731266e3b5d80e7a743ae9d2c33adbc22d821a29b329844d2759f6634dbe95f17e8b3ce45af4ddb02b3b2bb52bb27c76bfea5b294256105e0a56f6b1b7810061853a60b9d35850bc2287099f1074ca9c43cd7c07ed410d576c88f3638d43856f598d547286df4f6243ac789006e66d125896cff7c36a5cfac34e610d3cea060500c6662c12701ce678517114e282e9440b1e40a45f0cbc6e8eff748cd5ac44b21d9581b14e0f3dce32ce9500b03337e3d4e39a521cc131212f43153394c393f4465bbe021f41230399ec4d78b5b339ea6d7bc28bde39599545b43a2d4cc0978954232469370e554cfb27891205b940e26cf956e389fade426fe0a2e1d925a9e58b69a4eac51ae2e2f4e1802167a2971ea882d123fb4f700678e8a4c45586d1f75cbcc40b5528ce399703b32a49a4624fe102da626172063952a8a398071c3414625f2b1887d600e5b7cf1a08ea1454b6a48174251ef299ad9ce4e82d252be3328bdd8209acf59571bfb9af6e451430ba866bca17247ceb3df59620f2182149315f3f94761164450ad8dace6d6a4d42f7a9d8003a517accb98d2ddb5f12335a566156c0a23bacfd559be1f1a7d1a3c6bb821a5afd337583a15eec3e0a3438b311ff4fb2226e31bb0f710e16d36319d5eae8d05615bef9cfc723afdbc41892ee6984a876b4f9b3f908eb45588fe269db8078d4427f8534a54f89fdc26064766e200859c39df60cbbb2e0e5909de738234a4c6472512d83f0ba4faf6b7c2fdcb9e70b476e0f96fb902197c2b16119bcc5890f9905ba43c20f3a429c568dfe5aefc28a99cf8e59b6c7950e46728c01ee62be8c8aa24e8890291185a931e8ffb5e4363c37ce4eaf558d6682dd2f4bb36f459d1f77e023dbc13d2bf730b5d090341092157eb7dee8eb07a7f2828c7cbdf36d68d80387d3190093120bd99a479ba8eac93be3fd391f0cea87c9fb967b4a118ba2d6b87731b770bf6f807ed81efa27ee90034a186851fd3c98a3acd540ef91950593ed2e7dc6df9d50689f0ee38d0fc37b7968b33551554fba7c21e65dd55d1e8331adc7c16acdbf598c6cc5bcdb86d66c464c30844cb6ac9295872fc3f035886e68c029d0ec0cf92841346f4610fdfbb516449aaea78451be30b61633d81a99a0f326e174e571c75477e3082c39caef6041f82dd2663ec05a8e3b3c131d1e8261d9a9a544ac7914d0fa2fe8e8c3b5a7041861fde1c363da640081da29fe345f11b9743aa9a4337e3d6102a1057b5e2a2b5e923dfed85d18c6b7a204c5b7857450b058acc59f43ae4137f34bb7f42e8e05ba9e05854047c7ed0c32d479010fd5bacc978f0e9d53294944d012a835a9670d53a6ff04f3ad6cdb0c62ecf9734f49e978646f13a7665cc6937430a56bebbde56a4cb5dbd7172c796579dc55d71dfd4472c1baf0b78a19e4f3d342445058604376c317264fea3553dcf65405512cb7ba5ec86f465b8c6c623b7e64be749ab184627f01680596a176cea32378f10b49b4486458324f7ab5d11a8c2a4fbdccf1a02ddae702c9f3e2bdd45bf3f40db282cb17c003d8cf0d3b9b75c6dc9f5ad6ff492582a5948a0c551b932022d7d59c750aeeecf01f563c36e1ca025b9a2250bb3162cb9ea946252dbe2aa1664a04c3e9b3cb02d59b448ec4341407cf445e83fad46f459ee901e517050df174b4f4e36099f5a3874e173b03585dc783834d513877a91a74d4c2408ca7bd2f14779d36df3d494dcee4c327d73062b9762fef8e0d9f874182ca3d03a5b2ee711737303a28fd7017d519e523612158b81b7ea3bb4d5ae6e5b627233e54929181a946b53e5c35333c697f314aa4cab63b34b60c60671bfc0de33192390963b57859ecc87e2a4962485378baa641bff7660c2ac870f91a5f84139e5dae0d6bdad9c9e3c22f11229493cedbbf0e42fcc9b784c5b13fad8a2b0b4d012f14fcef5b416c7064e5f22e985d0a9adb36fb1cf755add37b44b8a5be6a951954b0a35c7446cf2ae241504e302680f790031fe4a7100f6a05e7c79f306a99171ca75da0f61444a8998ed1feecf498f7ea4896241e037dc0dba38dda829a01da919feb8c3b81994c9474bc7030121f899280103470e40132253f821996f486949a00130b264743eab77346dfc2f71e13116268a72f18b3deb8be8ea32b5e99c6b5bf9af13f6a0087b01d9a764fd4bfa269f53a0037c8e36cdd159f2a1b862f25b3e619f518dccecb2aa437e96b88485acb39dbfa9ede577422ac041ac93c4735bbd7cfc4218f0739ae7ad73512a95ad8e264110e12d191997740f6dea04ea49d8332861d72d7987036b299eb2c5f7ae205199a41da39fffe79bd60161bee496a6c2d3d00e4042fa23bb0247ad9d6aaf86f900688883fcb65a03233b18e37be57340df332f896a7015c9b8ea1335096b4dd67e899f201f2f5bf3cc81ab50515cae967854c37af412c9576c6dcccfa0c92f8862d87f70f81a4ca0c9a9584ca6ffc8e2048fa0aec354259dd67ef835df173faf873daddbba1a7c88199733c41f2cdf93b8a741be152952216d3386cb094b8365c13f997f1d393832828a1859c482fa4e0381c9bae4720ce56c243a56a7313af08e282166c2826fa8f6b8376fb14c403639b0f5dd95fb241dc08ab83d3de83df022bc26c17664937edbd53f751c1481fb8da0acdb4342a0093200117594ee2b003813ef3e6e58f2f90547fdc07ada18ad4cb76896e7860792a408f1848ea1a7bae30f6f54d8fc48e6547e4d963c968b53d00b014f7d1b7d007f8adac1b3f3c304978a92253939e985700929379c4e804cea6629e52c49b55bc14dfa747dbb47633488e283c0ce469d3b87c00b2e32f29d93c9a52004c4a1ddbbe10d33ef05c4d58a5331dd8a1b4a3ad2cd3a427753b7781fd948926b640894cc021520c0ed8db248195a4eb3fda30987c587efb9de0703abdb12a8a98d82761fce68ba830639d481fbac08542ab7b71b88bae93e87956a95eca6bd72f90292f5974796bf2048137e63f2c97263cd1f8dacd4e178dbd862ffb118adcd59156aa9cb999dbbb68d1ee6a90ba5573c9040ce344a7a67108006a9025a8fde7e75fa00cd81ec35ee7cee469040fac014cf933bf1ae81e0599d1a2af46eb275a562c8f07a9280a9258401800002cb00158e01fabc7a6e50b9f6ae99515e4f1388a7ed4bea2f6a10a23af7df1ce05c446b02efb90000994e3fd741375e914e392e973358e58a6c440784902bb5a0b0dd39cbcbbf18403eab2a26573d558ff200150e21349ba6c2367743563e74590bf5fcf9666ac710e9505066670d61454188d9db03eb0ae4e917332399e506ccfc31ce24f62690a61a12aa796472925c8c13ae7a21d121325816aeca1ea9aa84aea7192018a4a70e5067c137386d888d318d934406f19abeef3427d98b35ac6f866a98bbbddf967c556ffe51ec68b8b9d41cc7d40ca3ee37590a27f64ca63f7471182715c216d7373bb2630c08c6801ea5fcc48d08188f9774804619fd4eb28a618aafe5405e03be53a7b9f3feec831f2504aa2d2e7004f56e69bbe07ce722006e864d20b79c299e9cd6e87b2e8637dc0d8f65abd46cd6a40863f21167c832e853f3329a8ef10bd6810783b2acf87c6a1c4f5bf2a9dedfbf1f3330c032921083591909d7ba553cf0cf0ac5f60b217fd042296b4cdbf58a3f37f68b6135a56f19099acd32aa649a4d80c431387d1ab510497a0e525249fcd5ef49af13a84b2b8626f075df8774e591db67d459e34fa3e3bd6e9c1df0faa61087affc96cddd8cd257515ca8ede57a0a61b4e3a1dd7774918e702a3408c3a8a4324452e38b7d1808ef435f6346db775e0359e49415928eff8b593fabd315edccc27c5d85c692ddc9ecf67133cd449ea15798326dab2ccd505523ed2bf2cd08cccb379b86fe6234234c4a9202cffeab6b45ad13253af181fb2abdd4843d0d6a3434e661015ed0e6fcd70b911da4d58f22a1057725f4fd50e321f324c307ea49711fdefaaf68db2fcb65e45bb1b0189008ea26f755ab919de88c879d1170fa7fcce3190bdb6d632178dc24bf3886946b446b22904c0b698335a07076de701d7370ffb1a0e240bb16c8957d0b8acdb6d6d40dc148cce2f67669bcb2df3bf1516838554cb5d9b6e5d453688d31a7ed791556fc3ff532c6368ecc3e76e62100dd2b81c2809bec72c3a36f154cfa887d40f4e2d79a6916250ee02b48f44b2fd045c983034540702a19a3e541e71ceda92f4346bb8d8c518d09e4cc55f2e4dc3e890be849397b9797f92aa0d71227cae88bcfdf2c1a886d66572118d9607a4238d0e5c21acb01f9f0e18e81b72b91c38feab7d73c02bf2c45c8da6ddfb5115b3d3123cb97678974c7d15fee8d49f767938494564343028870fa43218d6309b7351daffd91eea3306ad2d4e1ff7173ef781bfe0dc511823eba9a45d75782f729682f229790927d7047150c03f29965e7902705b6067727beb5aa387f2f27304cff4690eb7dd980922d8c18d7c0c4feb5914f077069f25c8257cf1ae0618d97d0fc73812f51112aa75622de91aab5399d791ae525d9498145df3f6f0eadc6c03537f24430fe852f5f341dfab96e5066f0fa696cdcb8ed03b95d12a70aaee520a5c6a96887e3af29af415067930ad17e4a0a5f47e7297d92507d6dea07722db87c160849ce6f4d5da41001cdaeea0d437df0e82929ec0b63246e77bac1c292e12be4c04febe34fb56f13cb950395073d1fb94ae48762970f6913bf57ef0ab16911922b80b0b16e8917488520483e1cefc37f75aa896a285be557b8db634998434b5525394781f92c7992b808d1f65386c58806b6b389f504ef2e495f7ffd10bb21e551868b417ffcde5355ce635b5139d38c8a50bea00c13abf3ac2d4e8a3eefff2603f6e9e49bf3242ab8789f9af0cc3dca8a478861d9bcfd8509588f7eea8997febac08f04b3b884e5c1b70c41d878ba6d2d6972c7ae7a39e0bae33214445faecf7274f04a1b00d79a137ea3c143c5a8da2d8f6689efa17902a2ea6bde99eea9f1ddabed0ba52cea6b78d30c60f8cb84180009296d513a596a4f22b3c9038cb16b249df55c87e1a1632f01f3e974acf521095216d083889478e3efe524b48e6883c996c54352946ef673b8d31990389fd634c2f84ab5020a5e6d970bf6794146c6468ef96e3185413835027bd9718fd4b37215ea39590550053a688e8cf5c6435b5d063dfdd5f17e34564e1a867407d2c0eecc90613cb101c73c135a9b9c3a46f1818667408ba00970038575f794bf1f7d1f215e0a424981eadde2f5ac8689d07245af7a52be0c2c166fcb87d4e4a6741a05c14863e818c24a16e04d4022f00cd1dfa1f89344af222c4d95b160c1c67e714eb2c10931f36a98c6a6d2e48bf820bd0ed237c22636c1226c472c8039aa34eda4bdb431057e8a5ec2ab4095867c46ca3656ba6f6ac5cd5176bc99d2f8ff23ed8b7cb1d485472ae5d377a31cf0707556567f83ca4e71ae7c3bc748aa6df58a935bee499502ac0e5681682d23171e4c6bd4748d91680f9046257cc5d0c89162984920643756ca85e731a9cd88d065be0d23899839c6dde066fcf4b7779846a1114192287e0a1bcac8f1e52077952caa2be63311067a5c63d3f5459c9d979e2f977da3459980c3794c56e357aabe7429794a9141019efd7307d0acb0d7d5d656bd067e0a62fdd586c24708baba3ecf54746eb425986c31f6093cd46c33484428710aaff9c0922e9c9756d614d2b46616f378e3f34e7f864f84b4e6ed46363acfcff94f43391160d00d6de25cbacfd9b3e809fe18d1adbb7cc0000');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huge binary again

@CommanderStorm CommanderStorm merged commit 45e0c7b into maplibre:main Oct 5, 2025
33 of 34 checks passed
@CommanderStorm CommanderStorm mentioned this pull request Oct 3, 2025
@CommanderStorm
Copy link
Member

@sdf-jkl All of the issues that remain can/should be different PRs 😉
=> merging as is

This is great work, thank you so much

@sdf-jkl
Copy link
Contributor Author

sdf-jkl commented Oct 6, 2025

@CommanderStorm @nyurik Thanks for your help on this, this was definitely too big of a pr to go through and I should have split the work into smaller PRs way earlier.
Happy to get it done.

@sdf-jkl sdf-jkl deleted the generate-mbtiles-on-the-fly branch October 7, 2025 13:44
@CommanderStorm CommanderStorm added this to the v1.0.0 milestone Oct 14, 2025
@CommanderStorm CommanderStorm mentioned this pull request Oct 29, 2025
CommanderStorm added a commit that referenced this pull request Oct 30, 2025
## 🤖 New release

* `martin-tile-utils`: 0.6.4 -> 0.6.5 (✓ API compatible changes)
* `mbtiles`: 0.13.1 -> 0.14.0 (⚠ API breaking changes)
* `martin-core`: 0.1.3 -> 0.2.0 (⚠ API breaking changes)
* `martin`: 0.19.3 -> 0.20.0

### ⚠ `mbtiles` breaking changes

```text
--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/inherent_method_missing.ron

Failed in:
  MbtilesPool::new, previously in file /tmp/.tmpKSs4So/mbtiles/src/pool.rs:18
```

### ⚠ `martin-core` breaking changes

```text
--- failure constructible_struct_adds_field: externally-constructible struct adds field ---

Description:
A pub struct constructible with a struct literal has a new pub field. Existing struct literals must be updated to include the new field.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field Tile.etag in /tmp/.tmpBzV0yh/martin/martin-core/src/tiles/tile.rs:27

--- failure declarative_macro_missing: macro_rules declaration removed or renamed ---

Description:
A `macro_rules!` declarative macro cannot be invoked by its prior name. The macro may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/declarative_macro_missing.ron

Failed in:
  macro get_cached_value, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:62
  macro from_cache_value, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:48
  macro get_or_insert_cached_value, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:81

--- failure enum_missing: pub enum removed or renamed ---

Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/enum_missing.ron

Failed in:
  enum martin_core::cache::CacheValue, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:27
  enum martin_core::cache::CacheKey, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:15

--- failure enum_variant_missing: pub enum variant removed or renamed ---

Description:
A publicly-visible enum has at least one variant that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/enum_variant_missing.ron

Failed in:
  variant PmtilesError::S3BucketNameNotString, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/error.rs:14
  variant PmtilesError::InvalidUrlMetadata, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/error.rs:26
  variant PmtilesError::IoError, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/error.rs:34

--- failure feature_missing: package feature removed or renamed ---

Description:
A feature has been removed from this package's Cargo.toml. This will break downstream crates which enable that feature.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#cargo-feature-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/feature_missing.ron

Failed in:
  feature cog in the package's Cargo.toml

--- failure function_missing: pub fn removed or renamed ---

Description:
A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/function_missing.ron

Failed in:
  function martin_core::cache::trace_cache, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:37

--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/inherent_method_missing.ron

Failed in:
  Tile::new, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/tile.rs:29

--- failure module_missing: pub module removed or renamed ---

Description:
A publicly-visible module cannot be imported by its prior path. A `pub use` may have been removed, or the module may have been renamed, removed, or made non-public.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/module_missing.ron

Failed in:
  mod martin_core::cache, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:1

--- failure pub_module_level_const_missing: pub module-level const is missing ---

Description:
A public const is missing or renamed
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/pub_module_level_const_missing.ron

Failed in:
  NO_MAIN_CACHE in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:11

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/struct_missing.ron

Failed in:
  struct martin_core::tiles::pmtiles::PmtHttpSource, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/source.rs:218
  struct martin_core::tiles::pmtiles::PmtS3Source, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/source.rs:241
  struct martin_core::tiles::pmtiles::PmtFileSource, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/source.rs:288
```

<details><summary><i><b>Changelog</b></i></summary><p>


## `mbtiles`

<blockquote>

##
[0.14.0](mbtiles-v0.13.1...mbtiles-v0.14.0)
- 2025-10-27

### Added

- *(cache)* implement sprite caching
([#2295](#2295))
- *(pmtiles)* [**breaking**] change pmtiles to base the implementation
on `object_storage` instead
([#2251](#2251))

### Other

- *(lints)* audit all allows, add reasons and remove unnessesary ones
([#2288](#2288))
- *(config)* [**breaking**] remove deprecated `--watch` from the CLI
options and `MbtilesPool::new`
([#2294](#2294))
- *(lints)* migrate a few of our expects to unwraps
([#2284](#2284))
- *(lints)* applly `clippy::panic_in_result_fn` and `clippy::todo` as
warnings ([#2283](#2283))
- *(mbtiles)* Generate mbtiles dynamically from SQL files to increase
debuggability and transparency
([#1868](#1868))
- release ([#2265](#2265))
</blockquote>

## `martin-core`

<blockquote>

##
[0.2.0](martin-core-v0.1.3...martin-core-v0.2.0)
- 2025-10-27

### Added

- unstable style rendering
([#2306](#2306))
- *(cache)* implement sprite caching
([#2295](#2295))
- add font caching
([#2304](#2304))
- *(cache)* [**breaking**] split the cache configuration of tiles and
pmtiles directories
([#2303](#2303))
- *(core)* enable overriding of the automatic hashing for source traits
([#2293](#2293))
- *(pmtiles)* [**breaking**] change pmtiles to base the implementation
on `object_storage` instead
([#2251](#2251))

### Fixed

- *(cog)* [**breaking**] rename `cog` feature to `unstable-cog`
([#2285](#2285))

### Other

- *(lints)* audit all allows, add reasons and remove unnessesary ones
([#2288](#2288))
- *(core)* add a `_tiles` feature to simplify our feature configuration
([#2296](#2296))
- move `MainCache` to be a `TileCache`
([#2297](#2297))
- *(lints)* migrate a few of our expects to unwraps
([#2284](#2284))
</blockquote>

## `martin`

<blockquote>

##
[0.20.0](martin-v0.19.3...martin-v0.20.0)
- 2025-10-27

### Added

- unstable style rendering
([#2306](#2306))
- *(cache)* implement sprite caching
([#2295](#2295))
- add font caching
([#2304](#2304))
- *(cache)* [**breaking**] split the cache configuration of tiles and
pmtiles directories
([#2303](#2303))
- *(core)* enable overriding of the automatic hashing for source traits
([#2293](#2293))
- *(pg)* Add benchmark for source discovery timing
([#2263](#2263))
- *(pmtiles)* [**breaking**] change pmtiles to base the implementation
on `object_storage` instead
([#2251](#2251))

### Fixed

- *(cog)* [**breaking**] rename `cog` feature to `unstable-cog`
([#2285](#2285))

### Other

- *(admin)* move functionality into better modules
([#2315](#2315))
- *(deps-dev)* Bump vite from 7.1.7 to 7.1.11 in /martin/martin-ui in
the all-npm-ui-security-updates group across 1 directory
([#2308](#2308))
- *(lints)* enable `clippy::unimplemented` and `clippy::panic`
([#2287](#2287))
- *(lints)* audit all allows, add reasons and remove unnessesary ones
([#2288](#2288))
- move config files to new folders
([#2298](#2298))
- *(core)* add a `_tiles` feature to simplify our feature configuration
([#2296](#2296))
- move `MainCache` to be a `TileCache`
([#2297](#2297))
- *(config)* [**breaking**] remove deprecated `--watch` from the CLI
options and `MbtilesPool::new`
([#2294](#2294))
- Make mbtiles dependency properly optional again
([#2292](#2292))
- *(config)* refactor the livecycle hooks to be cleaner and better
documented ([#2282](#2282))
- *(lints)* migrate a few of our expects to unwraps
([#2284](#2284))
- *(lints)* applly `clippy::panic_in_result_fn` and `clippy::todo` as
warnings ([#2283](#2283))
- *(mbtiles)* Generate mbtiles dynamically from SQL files to increase
debuggability and transparency
([#1868](#1868))
- *(deps-dev)* Bump the all-npm-ui-version-updates group in
/martin/martin-ui with 2 updates
([#2277](#2277))
- release ([#2265](#2265))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
CommanderStorm added a commit to CommanderStorm/martin that referenced this pull request Nov 20, 2025
…e debuggability and transparency (maplibre#1868)

Working on this:

* [x] Create several schema initialization .sql files, e.g. in
`mbtiles/sql/` dir, add `init-flat.sql`, `init-flat-with-hash.sql`, etc.
* [x] Use content of these files directly in the
[docs](https://github.com/maplibre/martin/blob/428265025e0c76ba4a1919e0f9cbe7618137a4d1/docs/src/mbtiles-schema.md?plain=1#L10-L17),
rather than copy/paste it. See [`{{#include
file.rs}}`](https://rust-lang.github.io/mdBook/format/mdbook.html?highlight=include#including-files)
* [x] Use these files in the
[test.sh](https://github.com/maplibre/martin/blob/main/tests/test.sh)
before populating them with data
   -- Couldn't find where the mbtiles are being updated in tests.sh
   * [x] Use these files in the unit tests
* [x] Update docs to use these files with the `sqlite` command to create
a blank .mbtiles file
* [x] Export all existing .mbtiles test files as .sql files, e.g. by
using sqlite3's [`.dump`](https://www.sqlitetutorial.net/sqlite-dump/)
command.
* [x] Remove any schema creation - and reuse the above ones. We may need
to include the schema name in the file name to ensure the right schema
is used... unless we can somehow transclude one file inside the other
-- i am not sure if `.read filename.sql` can be used from another .sql
file?
* [ ] For image content, each tile content should be stored as an
individual image file in a subdir - this way they can also be easily
inspected. I think the `readfile('...')` sqlite function can be used to
get the file content as part of the insert statement.
* [ ] Same goes for the .mvt / .mlt content, except that sadly we have
no way to store it in a viewable format - until someday we may have some
simple json-mvt-mlt debug converter, or we could use ogr2ogr or another
utility to store geojson - but this is not great because the output is
less guaranteed.
   
Related maplibre#1846

---------

Co-authored-by: Konstantin.Tarasov <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Yuri Astrakhan <[email protected]>
Co-authored-by: Frank Elsinga <[email protected]>
Co-authored-by: Frank Elsinga <[email protected]>
CommanderStorm added a commit to CommanderStorm/martin that referenced this pull request Nov 20, 2025
## 🤖 New release

* `martin-tile-utils`: 0.6.4 -> 0.6.5 (✓ API compatible changes)
* `mbtiles`: 0.13.1 -> 0.14.0 (⚠ API breaking changes)
* `martin-core`: 0.1.3 -> 0.2.0 (⚠ API breaking changes)
* `martin`: 0.19.3 -> 0.20.0

### ⚠ `mbtiles` breaking changes

```text
--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/inherent_method_missing.ron

Failed in:
  MbtilesPool::new, previously in file /tmp/.tmpKSs4So/mbtiles/src/pool.rs:18
```

### ⚠ `martin-core` breaking changes

```text
--- failure constructible_struct_adds_field: externally-constructible struct adds field ---

Description:
A pub struct constructible with a struct literal has a new pub field. Existing struct literals must be updated to include the new field.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field Tile.etag in /tmp/.tmpBzV0yh/martin/martin-core/src/tiles/tile.rs:27

--- failure declarative_macro_missing: macro_rules declaration removed or renamed ---

Description:
A `macro_rules!` declarative macro cannot be invoked by its prior name. The macro may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/declarative_macro_missing.ron

Failed in:
  macro get_cached_value, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:62
  macro from_cache_value, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:48
  macro get_or_insert_cached_value, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:81

--- failure enum_missing: pub enum removed or renamed ---

Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/enum_missing.ron

Failed in:
  enum martin_core::cache::CacheValue, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:27
  enum martin_core::cache::CacheKey, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:15

--- failure enum_variant_missing: pub enum variant removed or renamed ---

Description:
A publicly-visible enum has at least one variant that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/enum_variant_missing.ron

Failed in:
  variant PmtilesError::S3BucketNameNotString, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/error.rs:14
  variant PmtilesError::InvalidUrlMetadata, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/error.rs:26
  variant PmtilesError::IoError, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/error.rs:34

--- failure feature_missing: package feature removed or renamed ---

Description:
A feature has been removed from this package's Cargo.toml. This will break downstream crates which enable that feature.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#cargo-feature-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/feature_missing.ron

Failed in:
  feature cog in the package's Cargo.toml

--- failure function_missing: pub fn removed or renamed ---

Description:
A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/function_missing.ron

Failed in:
  function martin_core::cache::trace_cache, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:37

--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/inherent_method_missing.ron

Failed in:
  Tile::new, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/tile.rs:29

--- failure module_missing: pub module removed or renamed ---

Description:
A publicly-visible module cannot be imported by its prior path. A `pub use` may have been removed, or the module may have been renamed, removed, or made non-public.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/module_missing.ron

Failed in:
  mod martin_core::cache, previously in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:1

--- failure pub_module_level_const_missing: pub module-level const is missing ---

Description:
A public const is missing or renamed
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/pub_module_level_const_missing.ron

Failed in:
  NO_MAIN_CACHE in file /tmp/.tmpKSs4So/martin-core/src/cache.rs:11

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.43.0/src/lints/struct_missing.ron

Failed in:
  struct martin_core::tiles::pmtiles::PmtHttpSource, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/source.rs:218
  struct martin_core::tiles::pmtiles::PmtS3Source, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/source.rs:241
  struct martin_core::tiles::pmtiles::PmtFileSource, previously in file /tmp/.tmpKSs4So/martin-core/src/tiles/pmtiles/source.rs:288
```

<details><summary><i><b>Changelog</b></i></summary><p>

## `mbtiles`

<blockquote>

##
[0.14.0](maplibre/martin@mbtiles-v0.13.1...mbtiles-v0.14.0)
- 2025-10-27

### Added

- *(cache)* implement sprite caching
([maplibre#2295](maplibre#2295))
- *(pmtiles)* [**breaking**] change pmtiles to base the implementation
on `object_storage` instead
([maplibre#2251](maplibre#2251))

### Other

- *(lints)* audit all allows, add reasons and remove unnessesary ones
([maplibre#2288](maplibre#2288))
- *(config)* [**breaking**] remove deprecated `--watch` from the CLI
options and `MbtilesPool::new`
([maplibre#2294](maplibre#2294))
- *(lints)* migrate a few of our expects to unwraps
([maplibre#2284](maplibre#2284))
- *(lints)* applly `clippy::panic_in_result_fn` and `clippy::todo` as
warnings ([maplibre#2283](maplibre#2283))
- *(mbtiles)* Generate mbtiles dynamically from SQL files to increase
debuggability and transparency
([maplibre#1868](maplibre#1868))
- release ([maplibre#2265](maplibre#2265))
</blockquote>

## `martin-core`

<blockquote>

##
[0.2.0](maplibre/martin@martin-core-v0.1.3...martin-core-v0.2.0)
- 2025-10-27

### Added

- unstable style rendering
([maplibre#2306](maplibre#2306))
- *(cache)* implement sprite caching
([maplibre#2295](maplibre#2295))
- add font caching
([maplibre#2304](maplibre#2304))
- *(cache)* [**breaking**] split the cache configuration of tiles and
pmtiles directories
([maplibre#2303](maplibre#2303))
- *(core)* enable overriding of the automatic hashing for source traits
([maplibre#2293](maplibre#2293))
- *(pmtiles)* [**breaking**] change pmtiles to base the implementation
on `object_storage` instead
([maplibre#2251](maplibre#2251))

### Fixed

- *(cog)* [**breaking**] rename `cog` feature to `unstable-cog`
([maplibre#2285](maplibre#2285))

### Other

- *(lints)* audit all allows, add reasons and remove unnessesary ones
([maplibre#2288](maplibre#2288))
- *(core)* add a `_tiles` feature to simplify our feature configuration
([maplibre#2296](maplibre#2296))
- move `MainCache` to be a `TileCache`
([maplibre#2297](maplibre#2297))
- *(lints)* migrate a few of our expects to unwraps
([maplibre#2284](maplibre#2284))
</blockquote>

## `martin`

<blockquote>

##
[0.20.0](maplibre/martin@martin-v0.19.3...martin-v0.20.0)
- 2025-10-27

### Added

- unstable style rendering
([maplibre#2306](maplibre#2306))
- *(cache)* implement sprite caching
([maplibre#2295](maplibre#2295))
- add font caching
([maplibre#2304](maplibre#2304))
- *(cache)* [**breaking**] split the cache configuration of tiles and
pmtiles directories
([maplibre#2303](maplibre#2303))
- *(core)* enable overriding of the automatic hashing for source traits
([maplibre#2293](maplibre#2293))
- *(pg)* Add benchmark for source discovery timing
([maplibre#2263](maplibre#2263))
- *(pmtiles)* [**breaking**] change pmtiles to base the implementation
on `object_storage` instead
([maplibre#2251](maplibre#2251))

### Fixed

- *(cog)* [**breaking**] rename `cog` feature to `unstable-cog`
([maplibre#2285](maplibre#2285))

### Other

- *(admin)* move functionality into better modules
([maplibre#2315](maplibre#2315))
- *(deps-dev)* Bump vite from 7.1.7 to 7.1.11 in /martin/martin-ui in
the all-npm-ui-security-updates group across 1 directory
([maplibre#2308](maplibre#2308))
- *(lints)* enable `clippy::unimplemented` and `clippy::panic`
([maplibre#2287](maplibre#2287))
- *(lints)* audit all allows, add reasons and remove unnessesary ones
([maplibre#2288](maplibre#2288))
- move config files to new folders
([maplibre#2298](maplibre#2298))
- *(core)* add a `_tiles` feature to simplify our feature configuration
([maplibre#2296](maplibre#2296))
- move `MainCache` to be a `TileCache`
([maplibre#2297](maplibre#2297))
- *(config)* [**breaking**] remove deprecated `--watch` from the CLI
options and `MbtilesPool::new`
([maplibre#2294](maplibre#2294))
- Make mbtiles dependency properly optional again
([maplibre#2292](maplibre#2292))
- *(config)* refactor the livecycle hooks to be cleaner and better
documented ([maplibre#2282](maplibre#2282))
- *(lints)* migrate a few of our expects to unwraps
([maplibre#2284](maplibre#2284))
- *(lints)* applly `clippy::panic_in_result_fn` and `clippy::todo` as
warnings ([maplibre#2283](maplibre#2283))
- *(mbtiles)* Generate mbtiles dynamically from SQL files to increase
debuggability and transparency
([maplibre#1868](maplibre#1868))
- *(deps-dev)* Bump the all-npm-ui-version-updates group in
/martin/martin-ui with 2 updates
([maplibre#2277](maplibre#2277))
- release ([maplibre#2265](maplibre#2265))
</blockquote>

</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

diff --git c/Cargo.toml i/Cargo.toml
index 59399fa..c5f12d4 100644
--- c/Cargo.toml
+++ i/Cargo.toml
@@ -63,16 +63,16 @@ json-patch = "4"
 lambda-web = { version = "0.2.1", features = ["actix4"] }
 log = "0.4"
 maplibre_native = "0.4.1"
-martin-core = { path = "./martin-core", version = "0.1.3", default-features = false }
-martin-tile-utils = { path = "./martin-tile-utils", version = "0.6.4" }
-mbtiles = { path = "./mbtiles", version = "0.13.1" }
+martin-core = { path = "./martin-core", version = "0.2.0", default-features = false }
+martin-tile-utils = { path = "./martin-tile-utils", version = "0.6.5" }
+mbtiles = { path = "./mbtiles", version = "0.14.0" }
 md5 = "0.8.0"
 moka = { version = "0.12", features = ["future"] }
 num_cpus = "1"
 ogcapi-types = "0.3.0"
 object_store = { version = "0.12.4", features = ["gcp", "aws", "azure", "fs", "http"] }
 pbf_font_tools = { version = "3.0.0", features = ["freetype"] }
-pmtiles = { version = "0.17", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots", "aws-s3-async"] }
+pmtiles = { version = "0.18", features = ["http-async", "mmap-async-tokio", "tilejson", "reqwest-rustls-tls-native-roots", "aws-s3-async"] }
 png = "0.18.0"
 postgis = "0.9"
 postgres = { version = "0.19", features = ["with-time-0_3", "with-uuid-1", "with-serde_json-1"] }
diff --git c/docs/src/sources-styles.md i/docs/src/sources-styles.md
index 88dfc7f..4c42104 100644
--- c/docs/src/sources-styles.md
+++ i/docs/src/sources-styles.md
@@ -35,7 +35,15 @@ A restart of Martin is required to see new styles.
 > - does not support concurrency for this feature.

 We support generating a rasterised image for an XYZ tile of a given style.
-Use the `/style/<style_id>/{z}/{x}/{y}.{filetype}` API to get a `<style_id>`'s rendered png/jpeg content.
+
+To do so, you need to enable the feature in the configuration file:
+
+```yaml
+styles:
+    rendering: true
+```
+
+After doing so, you can use the `/style/<style_id>/{z}/{x}/{y}.{filetype}` API to get a `<style_id>`'s rendered png/jpeg content.

 ### Static image prepraration

diff --git c/martin-core/CHANGELOG.md i/martin-core/CHANGELOG.md
index 2db8bcf..a3c7a29 100644
--- c/martin-core/CHANGELOG.md
+++ i/martin-core/CHANGELOG.md
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

 ## [Unreleased]

+## [0.2.0](maplibre/martin@martin-core-v0.1.3...martin-core-v0.2.0) - 2025-10-27
+
+### Added
+
+- unstable style rendering ([maplibre#2306](maplibre#2306))
+- *(cache)* implement sprite caching ([maplibre#2295](maplibre#2295))
+- add font caching ([maplibre#2304](maplibre#2304))
+- *(cache)* [**breaking**] split the cache configuration of tiles and pmtiles directories ([maplibre#2303](maplibre#2303))
+- *(core)* enable overriding of the automatic hashing for source traits ([maplibre#2293](maplibre#2293))
+- *(pmtiles)* [**breaking**] change pmtiles to base the implementation on `object_storage` instead ([maplibre#2251](maplibre#2251))
+
+### Fixed
+
+- *(cog)* [**breaking**] rename `cog` feature to `unstable-cog` ([maplibre#2285](maplibre#2285))
+
+### Other
+
+- *(lints)* audit all allows, add reasons and remove unnessesary ones ([maplibre#2288](maplibre#2288))
+- *(core)* add a `_tiles` feature  to simplify our feature configuration ([maplibre#2296](maplibre#2296))
+- move `MainCache` to be a `TileCache` ([maplibre#2297](maplibre#2297))
+- *(lints)* migrate a few of our expects to unwraps ([maplibre#2284](maplibre#2284))
+
 ## [0.1.3](maplibre/martin@martin-core-v0.1.2...martin-core-v0.1.3) - 2025-10-01

 ### Added
diff --git c/martin-core/Cargo.toml i/martin-core/Cargo.toml
index 517e757..a49200b 100644
--- c/martin-core/Cargo.toml
+++ i/martin-core/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "martin-core"
-version = "0.1.3"
+version = "0.2.0"
 authors = ["Yuri Astrakhan <[email protected]>", "MapLibre contributors"]
 description = "Basic building blocks of MapLibre's Martin tile server."
 keywords = ["maps", "tiles", "mvt", "tileserver"]
diff --git c/martin-tile-utils/Cargo.toml i/martin-tile-utils/Cargo.toml
index 1bfe8e1..6dfa605 100644
--- c/martin-tile-utils/Cargo.toml
+++ i/martin-tile-utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "martin-tile-utils"
-version = "0.6.4"
+version = "0.6.5"
 authors = ["Yuri Astrakhan <[email protected]>", "MapLibre contributors"]
 description = "Utilities to help with map tile processing, such as type and compression detection. Used by the MapLibre's Martin tile server."
 keywords = ["maps", "tiles", "mvt", "tileserver"]
diff --git c/martin/CHANGELOG.md i/martin/CHANGELOG.md
index 7015793..ff2c087 100644
--- c/martin/CHANGELOG.md
+++ i/martin/CHANGELOG.md
@@ -7,6 +7,102 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

 ## [Unreleased]

+## [0.20.0](maplibre/martin@martin-v0.19.3...martin-v0.20.0) - 2025-10-27
+
+
+> [!NOTE]
+> This release can be considered the last beta of the v1.0 release.
+> We have locked down key parts of the architecture.
+>
+> We will republish this release as v1.0 in roghly a week, unless we see any bugs in this release.
+
+A big thank you to everyone who contributed to this release - through code, reviews, testing, and feedback.
+Your work and discussions continue to make Martin faster, more reliable, and more welcoming for new users.
+
+We couldn’t have done it without you ❤️
+
+### A better, more configurable cache
+
+In previous versions, the cache was a single monolithic cache.
+We have split this up into different parts and you can now specify how much sprites, fonts, pmtiles directories and tiles martin is allowed in the cache.
+
+> [!TIP]
+> We also now support caching sprites and fonts - speeding up the rendering of vector maps.
+
+See our [documentation here](https://maplibre.org/martin/config-file.html) for further context.
+
+Done in [maplibre#2295](maplibre#2295) [maplibre#2304](maplibre#2304) [maplibre#2303](maplibre#2303), [maplibre#2297](maplibre#2297)
+
+### Pmtiles support for Google Cloud, Azure and much more options
+
+The good news first:
+- [greatly expanded](https://maplibre.org/martin/sources-files.html) options for AWS and HTTP backends
+- New support for Google Cloud and Azure object storage
+- Local files remain unaffected
+
+How did we do this?
+We replaced our entire pmtiles backend with the [`object_storage` crate](http://docs.rs/object_storage).
+
+Most of the options are cleanly migratable, but we deprecated the following:
+
+- AWS specific environment variable usages are deprecated.
+- `pmtiles.allow_http` being unset is currently defaulting to `true`.
+  In v2.0, we will change this to be `false` by default for better security defaults.
+
+The deprecated items will be removed in v2.0 at the earliest.
+
+> [!TIP]
+> Each of the deprecations also has its own warning in the log, so you don't have to guess if you are affected 😉
+
+`AWS_PROFILE` presented a challenge and we had to drop this environment variable.
+We asked for community feedback on Slack (see [here](https://maplibre.org/community)), and it seems this may not be a necessary feature.
+If you depend on `AWS_PROFILE`, we opened the following issue to discuss details:
+- maplibre#2286
+
+For further details on the now avaliable options, please [see our documentation](https://maplibre.org/martin/sources-files.html).
+
+Done in [maplibre#2251](maplibre#2251)
+
+
+### unstable style rendering support
+
+We added an experimental option for server-side style rendering, allowing you to convert your configured styles into images on the server side instead of the client.
+See our [documentation here](https://maplibre.org/martin/sources-styles.html#server-side-raster-tile-rendering) for further context.
+
+Done in [maplibre#2306](maplibre#2306)
+
+### rename `cog` feature to `unstable-cog`
+
+The `cog` feature was renamed to `unstable-cog` and thus removed from the features active by default.
+If you compile martin from source with this feature enabled, experimentation is still possible.
+This change signals that the feature is still evolving and allows us to iterate more freely as we add the missing functionality.
+Currently, our COG support does not support certain projection aspects required for good usability.
+
+Done in [maplibre#2285](maplibre#2285)
+
+### Removal of deprecated functionality
+
+We removed the long-deprecated `--watch` CLI option, which previously only displayed a deprecation warning in the log.
+
+Done in [maplibre#2294](maplibre#2294)
+
+### Fix
+
+- Make mbtiles dependency properly optional again ([maplibre#2292](maplibre#2292))
+
+### Other
+
+- *(core)* enable overriding of the automatic hashing for source traits ([maplibre#2293](maplibre#2293))
+- *(pg)* Add benchmark for source discovery timing ([maplibre#2263](maplibre#2263))
+- *(admin)* move functionality into better modules ([maplibre#2315](maplibre#2315))
+- move config files to new folders ([maplibre#2298](maplibre#2298))
+- *(core)* add a `_tiles` feature  to simplify our feature configuration ([maplibre#2296](maplibre#2296))
+- *(config)* refactor the livecycle hooks to be cleaner and better documented ([maplibre#2282](maplibre#2282))
+- *(lints)* applly tighter clippy lints like `clippy::panic_in_result_fn`, `clippy::todo` or similar [maplibre#2284](maplibre#2284 [maplibre#2283](maplibre#2283), [maplibre#2288](maplibre#2288), [maplibre#2287](maplibre#2287)
+- *(mbtiles)* Generate mbtiles dynamically from SQL files to increase debuggability, transparency and supply chain trust/security ([maplibre#1868](maplibre#1868))
+- A number of dependency updates [maplibre#2277](maplibre#2277), [maplibre#2308](maplibre#2308)
+
+
 ## [0.19.3](maplibre/martin@martin-v0.19.2...martin-v0.19.3) - 2025-10-01

 ### Added
diff --git c/martin/Cargo.toml i/martin/Cargo.toml
index d5d805c..2cf15f1 100644
--- c/martin/Cargo.toml
+++ i/martin/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "martin"
-version = "0.19.3"
+version = "0.20.0"
 authors = [
     "Stepan Kuzmin <[email protected]>",
     "Yuri Astrakhan <[email protected]>",
@@ -95,7 +95,6 @@ default = [
     "postgres",
     "sprites",
     "styles",
-    "unstable-cog",
     "webui",
     "ogcapi",
 ]
diff --git c/martin/src/config/file/resources/styles.rs i/martin/src/config/file/resources/styles.rs
index 73755eb..8608cab 100644
--- c/martin/src/config/file/resources/styles.rs
+++ i/martin/src/config/file/resources/styles.rs
@@ -20,7 +20,7 @@ pub struct InnerStyleConfig {
     /// We are not currently happy with the performance of this endpoint and intend to improve this in the future
     /// Marking this experimental means that we are not stuck with single threaded performance as a default until v2.0
     #[cfg(all(feature = "unstable-rendering", target_os = "linux"))]
-    pub experimental_rendering: OptBoolObj<RendererConfig>,
+    pub rendering: OptBoolObj<RendererConfig>,

     #[serde(flatten, skip_serializing)]
     pub unrecognized: UnrecognizedValues,
@@ -35,12 +35,12 @@ impl ConfigurationLivecycleHooks for InnerStyleConfig {
             .cloned()
             .collect::<UnrecognizedKeys>();
         #[cfg(all(feature = "unstable-rendering", target_os = "linux"))]
-        match &self.experimental_rendering {
+        match &self.rendering {
             OptBoolObj::NoValue | OptBoolObj::Bool(_) => {}
             OptBoolObj::Object(o) => keys.extend(
                 o.get_unrecognized_keys()
                     .iter()
-                    .map(|k| format!("experimental_rendering.{k}")),
+                    .map(|k| format!("rendering.{k}")),
             ),
         }
         keys
@@ -50,7 +50,7 @@ impl ConfigurationLivecycleHooks for InnerStyleConfig {
 #[cfg(all(feature = "unstable-rendering", target_os = "linux"))]
 #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
 pub struct RendererConfig {
-    // Same effect as experimental_rendering: true|false shorthands
+    // Same effect as rendering: true|false shorthands
     enabled: bool,

     #[serde(flatten, skip_serializing)]
@@ -74,7 +74,7 @@ impl StyleConfig {
         let mut results = StyleSources::default();

         #[cfg(all(feature = "unstable-rendering", target_os = "linux"))]
-        match cfg.custom.experimental_rendering {
+        match cfg.custom.rendering {
             OptBoolObj::NoValue | OptBoolObj::Bool(false) => results.set_rendering_enabled(false),
             OptBoolObj::Object(ref o) if !o.enabled => results.set_rendering_enabled(false),
             _ => {
diff --git c/martin/tests/styles_server_test.rs i/martin/tests/styles_server_test.rs
index d5b6b9c..8de8889 100644
--- c/martin/tests/styles_server_test.rs
+++ i/martin/tests/styles_server_test.rs
@@ -39,7 +39,7 @@ fn test_get(path: &str) -> TestRequest {
 #[cfg(all(feature = "unstable-rendering", target_os = "linux"))]
 const CONFIG_STYLES: &str = indoc! {"
         styles:
-            experimental_rendering: true
+            rendering: true
             sources:
                 maplibre_demo: ../tests/fixtures/styles/maplibre_demo.json
     "};
diff --git c/mbtiles/CHANGELOG.md i/mbtiles/CHANGELOG.md
index 138de70..a245de1 100644
--- c/mbtiles/CHANGELOG.md
+++ i/mbtiles/CHANGELOG.md
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

 ## [Unreleased]

+## [0.14.0](maplibre/martin@mbtiles-v0.13.1...mbtiles-v0.14.0) - 2025-10-27
+
+### Other
+
+- *(lints)* audit all allows, add reasons and remove unnessesary ones ([maplibre#2288](maplibre#2288))
+- *(config)* [**breaking**] remove deprecated `MbtilesPool::new` ([maplibre#2294](maplibre#2294))
+- *(lints)* migrate a few of our expects to unwraps ([maplibre#2284](maplibre#2284))
+- *(lints)* applly `clippy::panic_in_result_fn` and `clippy::todo` as warnings ([maplibre#2283](maplibre#2283))
+- *(mbtiles)* Generate mbtiles dynamically from SQL files to increase debuggability and transparency ([maplibre#1868](maplibre#1868))
+
 ## [0.13.1](maplibre/martin@mbtiles-v0.13.0...mbtiles-v0.13.1) - 2025-09-28

 ### Other
diff --git c/mbtiles/Cargo.toml i/mbtiles/Cargo.toml
index ed0cf3e..2955cd4 100644
--- c/mbtiles/Cargo.toml
+++ i/mbtiles/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mbtiles"
-version = "0.13.1"
+version = "0.14.0"
 authors = ["Yuri Astrakhan <[email protected]>", "MapLibre contributors"]
 description = "A simple low-level MbTiles access and processing library, with some tile format detection and other relevant heuristics."
 keywords = ["mbtiles", "maps", "tiles", "mvt", "tilejson"]
diff --git c/tests/expected/auto/catalog_auto.json i/tests/expected/auto/catalog_auto.json
index 6d80fad..ee11ef2 100644
--- c/tests/expected/auto/catalog_auto.json
+++ i/tests/expected/auto/catalog_auto.json
@@ -171,15 +171,6 @@
       "content_type": "application/x-protobuf",
       "description": "public.points_empty_srid.geom"
     },
-    "rgb_u8": {
-      "content_type": "image/png"
-    },
-    "rgba_u8": {
-      "content_type": "image/png"
-    },
-    "rgba_u8_nodata": {
-      "content_type": "image/png"
-    },
     "stamen_toner__raster_CC-BY-ODbL_z3": {
       "content_type": "image/png"
     },
diff --git c/tests/expected/auto/rgb_u8.json i/tests/expected/auto/rgb_u8.json
deleted file mode 100644
index a159d60..00000000
--- c/tests/expected/auto/rgb_u8.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "maxzoom": 3,
-  "minzoom": 0,
-  "tilejson": "3.0.0",
-  "tiles": [
-    "http://localhost:3111/rgb_u8/{z}/{x}/{y}"
-  ]
-}
diff --git c/tests/expected/auto/rgb_u8.json.headers i/tests/expected/auto/rgb_u8.json.headers
deleted file mode 100644
index 0637be8..00000000
--- c/tests/expected/auto/rgb_u8.json.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: br
-content-type: application/json
-etag: W/"61-IE-cuTwRcHu2Y_TNihoCYQ=="
-transfer-encoding: chunked
-vary: accept-encoding, Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgb_u8_0_0_0.png i/tests/expected/auto/rgb_u8_0_0_0.png
deleted file mode 100644
index 936e6ed..00000000
Binary files c/tests/expected/auto/rgb_u8_0_0_0.png and /dev/null differ
diff --git c/tests/expected/auto/rgb_u8_0_0_0.png.headers i/tests/expected/auto/rgb_u8_0_0_0.png.headers
deleted file mode 100644
index 3f3132a..00000000
--- c/tests/expected/auto/rgb_u8_0_0_0.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 1471
-content-type: image/png
-etag: "jCaYbs0XsKhbijmER28YWQ"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgb_u8_0_0_0.png.txt i/tests/expected/auto/rgb_u8_0_0_0.png.txt
deleted file mode 100644
index 6afcdcb..00000000
--- c/tests/expected/auto/rgb_u8_0_0_0.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgb_u8_0_0_0.png: PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/rgb_u8_3_0_0.png i/tests/expected/auto/rgb_u8_3_0_0.png
deleted file mode 100644
index 5cdb1a3..00000000
Binary files c/tests/expected/auto/rgb_u8_3_0_0.png and /dev/null differ
diff --git c/tests/expected/auto/rgb_u8_3_0_0.png.headers i/tests/expected/auto/rgb_u8_3_0_0.png.headers
deleted file mode 100644
index 5b32df4..00000000
--- c/tests/expected/auto/rgb_u8_3_0_0.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 28797
-content-type: image/png
-etag: "RbcKEB9g7lnQXFcfobVWOA"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgb_u8_3_0_0.png.txt i/tests/expected/auto/rgb_u8_3_0_0.png.txt
deleted file mode 100644
index c45d2ef..00000000
--- c/tests/expected/auto/rgb_u8_3_0_0.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgb_u8_3_0_0.png: PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/rgb_u8_3_1_1.png i/tests/expected/auto/rgb_u8_3_1_1.png
deleted file mode 100644
index 62f0de6..00000000
Binary files c/tests/expected/auto/rgb_u8_3_1_1.png and /dev/null differ
diff --git c/tests/expected/auto/rgb_u8_3_1_1.png.headers i/tests/expected/auto/rgb_u8_3_1_1.png.headers
deleted file mode 100644
index 8b3fb1c..00000000
--- c/tests/expected/auto/rgb_u8_3_1_1.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 167
-content-type: image/png
-etag: "QgaAsFxN0X8e2iZO9n7cdA"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgb_u8_3_1_1.png.txt i/tests/expected/auto/rgb_u8_3_1_1.png.txt
deleted file mode 100644
index 8eae127..00000000
--- c/tests/expected/auto/rgb_u8_3_1_1.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgb_u8_3_1_1.png: PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/rgba_u8.json i/tests/expected/auto/rgba_u8.json
deleted file mode 100644
index 75815ef..00000000
--- c/tests/expected/auto/rgba_u8.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "maxzoom": 3,
-  "minzoom": 0,
-  "tilejson": "3.0.0",
-  "tiles": [
-    "http://localhost:3111/rgba_u8/{z}/{x}/{y}"
-  ]
-}
diff --git c/tests/expected/auto/rgba_u8.json.headers i/tests/expected/auto/rgba_u8.json.headers
deleted file mode 100644
index 14faf7f..00000000
--- c/tests/expected/auto/rgba_u8.json.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: br
-content-type: application/json
-etag: W/"62-BrVv6ZXdmCdQ_wrDTr0tSw=="
-transfer-encoding: chunked
-vary: accept-encoding, Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgba_u8_0_0_0.png i/tests/expected/auto/rgba_u8_0_0_0.png
deleted file mode 100644
index 936e6ed..00000000
Binary files c/tests/expected/auto/rgba_u8_0_0_0.png and /dev/null differ
diff --git c/tests/expected/auto/rgba_u8_0_0_0.png.headers i/tests/expected/auto/rgba_u8_0_0_0.png.headers
deleted file mode 100644
index 3f3132a..00000000
--- c/tests/expected/auto/rgba_u8_0_0_0.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 1471
-content-type: image/png
-etag: "jCaYbs0XsKhbijmER28YWQ"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgba_u8_0_0_0.png.txt i/tests/expected/auto/rgba_u8_0_0_0.png.txt
deleted file mode 100644
index 4e6e258..00000000
--- c/tests/expected/auto/rgba_u8_0_0_0.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgba_u8_0_0_0.png: PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/rgba_u8_3_0_0.png i/tests/expected/auto/rgba_u8_3_0_0.png
deleted file mode 100644
index 5cdb1a3..00000000
Binary files c/tests/expected/auto/rgba_u8_3_0_0.png and /dev/null differ
diff --git c/tests/expected/auto/rgba_u8_3_0_0.png.headers i/tests/expected/auto/rgba_u8_3_0_0.png.headers
deleted file mode 100644
index 5b32df4..00000000
--- c/tests/expected/auto/rgba_u8_3_0_0.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 28797
-content-type: image/png
-etag: "RbcKEB9g7lnQXFcfobVWOA"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgba_u8_3_0_0.png.txt i/tests/expected/auto/rgba_u8_3_0_0.png.txt
deleted file mode 100644
index 11598f0..00000000
--- c/tests/expected/auto/rgba_u8_3_0_0.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgba_u8_3_0_0.png: PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/rgba_u8_3_1_1.png i/tests/expected/auto/rgba_u8_3_1_1.png
deleted file mode 100644
index 62f0de6..00000000
Binary files c/tests/expected/auto/rgba_u8_3_1_1.png and /dev/null differ
diff --git c/tests/expected/auto/rgba_u8_3_1_1.png.headers i/tests/expected/auto/rgba_u8_3_1_1.png.headers
deleted file mode 100644
index 8b3fb1c..00000000
--- c/tests/expected/auto/rgba_u8_3_1_1.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 167
-content-type: image/png
-etag: "QgaAsFxN0X8e2iZO9n7cdA"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgba_u8_3_1_1.png.txt i/tests/expected/auto/rgba_u8_3_1_1.png.txt
deleted file mode 100644
index 46ea068..00000000
--- c/tests/expected/auto/rgba_u8_3_1_1.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgba_u8_3_1_1.png: PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/rgba_u8_nodata.json i/tests/expected/auto/rgba_u8_nodata.json
deleted file mode 100644
index 47d2f9b..00000000
--- c/tests/expected/auto/rgba_u8_nodata.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "maxzoom": 2,
-  "minzoom": 0,
-  "tilejson": "3.0.0",
-  "tiles": [
-    "http://localhost:3111/rgba_u8_nodata/{z}/{x}/{y}"
-  ]
-}
diff --git c/tests/expected/auto/rgba_u8_nodata.json.headers i/tests/expected/auto/rgba_u8_nodata.json.headers
deleted file mode 100644
index 4c5a243..00000000
--- c/tests/expected/auto/rgba_u8_nodata.json.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: br
-content-type: application/json
-etag: W/"69-f7ZqJowAoXXdyYxlTrEd6g=="
-transfer-encoding: chunked
-vary: accept-encoding, Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgba_u8_nodata_0_0_0.png i/tests/expected/auto/rgba_u8_nodata_0_0_0.png
deleted file mode 100644
index bc34c1e..00000000
Binary files c/tests/expected/auto/rgba_u8_nodata_0_0_0.png and /dev/null differ
diff --git c/tests/expected/auto/rgba_u8_nodata_0_0_0.png.headers i/tests/expected/auto/rgba_u8_nodata_0_0_0.png.headers
deleted file mode 100644
index c0a1c29..00000000
--- c/tests/expected/auto/rgba_u8_nodata_0_0_0.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 4176
-content-type: image/png
-etag: "bhMDelQFn790zN0hmaCCow"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgba_u8_nodata_0_0_0.png.txt i/tests/expected/auto/rgba_u8_nodata_0_0_0.png.txt
deleted file mode 100644
index 59fb8ac..00000000
--- c/tests/expected/auto/rgba_u8_nodata_0_0_0.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgba_u8_nodata_0_0_0.png: PNG image data, 512 x 512, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/rgba_u8_nodata_1_0_0.png i/tests/expected/auto/rgba_u8_nodata_1_0_0.png
deleted file mode 100644
index 1de89fc..00000000
Binary files c/tests/expected/auto/rgba_u8_nodata_1_0_0.png and /dev/null differ
diff --git c/tests/expected/auto/rgba_u8_nodata_1_0_0.png.headers i/tests/expected/auto/rgba_u8_nodata_1_0_0.png.headers
deleted file mode 100644
index d0022ce..00000000
--- c/tests/expected/auto/rgba_u8_nodata_1_0_0.png.headers
+++ /dev/null
@@ -1,5 +0,0 @@
-content-encoding: gzip
-content-length: 12235
-content-type: image/png
-etag: "UN_QFVGBzgOKpk2d18r27A"
-vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
diff --git c/tests/expected/auto/rgba_u8_nodata_1_0_0.png.txt i/tests/expected/auto/rgba_u8_nodata_1_0_0.png.txt
deleted file mode 100644
index 974c65b..00000000
--- c/tests/expected/auto/rgba_u8_nodata_1_0_0.png.txt
+++ /dev/null
@@ -1 +0,0 @@
-tests/output/auto/rgba_u8_nodata_1_0_0.png: PNG image data, 512 x 512, 8-bit/color RGBA, non-interlaced
diff --git c/tests/expected/auto/save_config.yaml i/tests/expected/auto/save_config.yaml
index 5ddc2df..667af70 100644
--- c/tests/expected/auto/save_config.yaml
+++ i/tests/expected/auto/save_config.yaml
@@ -352,15 +352,6 @@ mbtiles:
     world_cities_diff: tests/fixtures/mbtiles/world_cities_diff.mbtiles
     world_cities_modified: tests/fixtures/mbtiles/world_cities_modified.mbtiles
     zoomed_world_cities: tests/fixtures/mbtiles/zoomed_world_cities.mbtiles
-cog:
-  paths:
-  - tests/fixtures/mbtiles
-  - tests/fixtures/pmtiles
-  - tests/fixtures/cog
-  sources:
-    rgb_u8: tests/fixtures/cog/rgb_u8.tif
-    rgba_u8: tests/fixtures/cog/rgba_u8.tif
-    rgba_u8_nodata: tests/fixtures/cog/rgba_u8_nodata.tiff
 sprites: tests/fixtures/sprites/src1
 styles:
 - tests/fixtures/styles/maplibre_demo.json
diff --git c/tests/expected/auto_mini/save_config.yaml i/tests/expected/auto_mini/save_config.yaml
index 3596660..1dcb159 100644
--- c/tests/expected/auto_mini/save_config.yaml
+++ i/tests/expected/auto_mini/save_config.yaml
@@ -4,4 +4,3 @@ pmtiles:
   sources:
     webp2: tests/fixtures/pmtiles2/webp2.pmtiles
 mbtiles: tests/fixtures/pmtiles2
-cog: tests/fixtures/pmtiles2
diff --git c/tests/expected/configured/catalog_cfg.json i/tests/expected/configured/catalog_cfg.json
index 823a6a3..4923440 100644
--- c/tests/expected/configured/catalog_cfg.json
+++ i/tests/expected/configured/catalog_cfg.json
@@ -53,12 +53,6 @@
       "content_type": "application/x-protobuf",
       "description": "autodetect.bigint_table.geom"
     },
-    "cog-src1": {
-      "content_type": "image/png"
-    },
-    "cog-src2": {
-      "content_type": "image/png"
-    },
     "function_Mixed_Name": {
       "content_type": "application/x-protobuf",
       "description": "a function source with MixedCase name"
@@ -89,9 +83,6 @@
       "content_type": "application/x-protobuf",
       "description": "public.points3857.geom"
     },
-    "rgba_u8_nodata": {
-      "content_type": "image/png"
-    },
     "table_source": {
       "content_type": "application/x-protobuf"
     },
diff --git c/tests/expected/configured/save_config.yaml i/tests/expected/configured/save_config.yaml
index 2f1de90..b795920 100644
--- c/tests/expected/configured/save_config.yaml
+++ i/tests/expected/configured/save_config.yaml
@@ -175,11 +175,6 @@ pmtiles:
     pmt: tests/fixtures/pmtiles/stamen_toner__raster_CC-BY+ODbL_z3.pmtiles
     pmt2: http://localhost:5412/webp2.pmtiles
     webp2: http://localhost:5412/webp2.pmtiles
-cog:
-  sources:
-    cog-src1: tests/fixtures/cog/rgba_u8.tif
-    cog-src2: tests/fixtures/cog/rgb_u8.tif
-    rgba_u8_nodata: tests/fixtures/cog/rgba_u8_nodata.tiff
 sprites:
   paths: tests/fixtures/sprites/src1
   sources:
diff --git c/tests/expected/martin-cp/composite_save_config.yaml i/tests/expected/martin-cp/composite_save_config.yaml
index 61658d5..634d30d 100644
--- c/tests/expected/martin-cp/composite_save_config.yaml
+++ i/tests/expected/martin-cp/composite_save_config.yaml
@@ -349,7 +349,3 @@ mbtiles:
     world_cities_diff: tests/fixtures/mbtiles/world_cities_diff.mbtiles
     world_cities_modified: tests/fixtures/mbtiles/world_cities_modified.mbtiles
     zoomed_world_cities: tests/fixtures/mbtiles/zoomed_world_cities.mbtiles
-cog:
-- tests/fixtures/mbtiles
-- tests/fixtures/pmtiles
-- tests/fixtures/pmtiles2
diff --git c/tests/expected/martin-cp/flat-with-hash_save_config.yaml i/tests/expected/martin-cp/flat-with-hash_save_config.yaml
index 61658d5..634d30d 100644
--- c/tests/expected/martin-cp/flat-with-hash_save_config.yaml
+++ i/tests/expected/martin-cp/flat-with-hash_save_config.yaml
@@ -349,7 +349,3 @@ mbtiles:
     world_cities_diff: tests/fixtures/mbtiles/world_cities_diff.mbtiles
     world_cities_modified: tests/fixtures/mbtiles/world_cities_modified.mbtiles
     zoomed_world_cities: tests/fixtures/mbtiles/zoomed_world_cities.mbtiles
-cog:
-- tests/fixtures/mbtiles
-- tests/fixtures/pmtiles
-- tests/fixtures/pmtiles2
diff --git c/tests/expected/martin-cp/flat_save_config.yaml i/tests/expected/martin-cp/flat_save_config.yaml
index 61658d5..634d30d 100644
--- c/tests/expected/martin-cp/flat_save_config.yaml
+++ i/tests/expected/martin-cp/flat_save_config.yaml
@@ -349,7 +349,3 @@ mbtiles:
     world_cities_diff: tests/fixtures/mbtiles/world_cities_diff.mbtiles
     world_cities_modified: tests/fixtures/mbtiles/world_cities_modified.mbtiles
     zoomed_world_cities: tests/fixtures/mbtiles/zoomed_world_cities.mbtiles
-cog:
-- tests/fixtures/mbtiles
-- tests/fixtures/pmtiles
-- tests/fixtures/pmtiles2
diff --git c/tests/expected/martin-cp/normalized_save_config.yaml i/tests/expected/martin-cp/normalized_save_config.yaml
index 61658d5..634d30d 100644
--- c/tests/expected/martin-cp/normalized_save_config.yaml
+++ i/tests/expected/martin-cp/normalized_save_config.yaml
@@ -349,7 +349,3 @@ mbtiles:
     world_cities_diff: tests/fixtures/mbtiles/world_cities_diff.mbtiles
     world_cities_modified: tests/fixtures/mbtiles/world_cities_modified.mbtiles
     zoomed_world_cities: tests/fixtures/mbtiles/zoomed_world_cities.mbtiles
-cog:
-- tests/fixtures/mbtiles
-- tests/fixtures/pmtiles
-- tests/fixtures/pmtiles2
diff --git c/tests/test.sh i/tests/test.sh
index 00df64b..19a0bc0 100755
--- c/tests/test.sh
+++ i/tests/test.sh
@@ -394,20 +394,21 @@ test_png mb_png_0_0_0 geography-class-png/0/0/0
 test_jsn mb_mvt       world_cities
 test_pbf mb_mvt_2_3_1 world_cities/2/3/1

->&2 echo "***** Test server response for COG(Cloud Optimized GeoTiff) source *****"
-test_jsn rgb_u8       rgb_u8
-test_png rgb_u8_0_0_0 rgb_u8/0/0/0
-test_png rgb_u8_3_0_0 rgb_u8/3/0/0
-test_png rgb_u8_3_1_1 rgb_u8/3/1/1
+# TODO: enable below once unstable-cog is stable
+#>&2 echo "***** Test server response for COG(Cloud Optimized GeoTiff) source *****"
+#test_jsn rgb_u8       rgb_u8
+#test_png rgb_u8_0_0_0 rgb_u8/0/0/0
+#test_png rgb_u8_3_0_0 rgb_u8/3/0/0
+#test_png rgb_u8_3_1_1 rgb_u8/3/1/1

-test_jsn rgba_u8       rgba_u8
-test_png rgba_u8_0_0_0 rgba_u8/0/0/0
-test_png rgba_u8_3_0_0 rgba_u8/3/0/0
-test_png rgba_u8_3_1_1 rgba_u8/3/1/1
+#test_jsn rgba_u8       rgba_u8
+#test_png rgba_u8_0_0_0 rgba_u8/0/0/0
+#test_png rgba_u8_3_0_0 rgba_u8/3/0/0
+#test_png rgba_u8_3_1_1 rgba_u8/3/1/1

-test_jsn rgba_u8_nodata       rgba_u8_nodata
-test_png rgba_u8_nodata_0_0_0 rgba_u8_nodata/0/0/0
-test_png rgba_u8_nodata_1_0_0 rgba_u8_nodata/1/0/0
+#test_jsn rgba_u8_nodata       rgba_u8_nodata
+#test_png rgba_u8_nodata_0_0_0 rgba_u8_nodata/0/0/0
+#test_png rgba_u8_nodata_1_0_0 rgba_u8_nodata/1/0/0

 >&2 echo "***** Test server response for table source with empty SRID *****"
 test_pbf points_empty_srid_0_0_0  points_empty_srid/0/0/0
@@ -566,7 +567,8 @@ test_log_has_str "$LOG_FILE" "WARN  martin::config::file::main] Ignoring unrecog
 test_log_has_str "$LOG_FILE" "WARN  martin::config::file::main] Ignoring unrecognized configuration key 'postgres.functions.function_zxy_query.warning'. Please check your configuration file for typos."
 test_log_has_str "$LOG_FILE" "WARN  martin::config::file::main] Ignoring unrecognized configuration key 'pmtiles.warning'. Please check your configuration file for typos."
 test_log_has_str "$LOG_FILE" "WARN  martin::config::file::main] Ignoring unrecognized configuration key 'sprites.warning'. Please check your configuration file for typos."
-test_log_has_str "$LOG_FILE" "WARN  martin::config::file::main] Ignoring unrecognized configuration key 'cog.warning'. Please check your configuration file for typos."
+# TODO: below should be changed to cog.warning once unstable-cog is made stable
+test_log_has_str "$LOG_FILE" "WARN  martin::config::file::main] Ignoring unrecognized configuration key 'cog'. Please check your configuration file for typos."
 test_log_has_str "$LOG_FILE" "WARN  martin::config::file::main] Ignoring unrecognized configuration key 'styles.warning'. Please check your configuration file for typos."
 test_log_has_str "$LOG_FILE" 'WARN  martin::config::file::tiles::pmtiles] Defaulting `pmtiles.allow_http` to `true`. This is likely to become an error in the future for better security.'
 test_log_has_str "$LOG_FILE" 'WARN  martin::config::file::tiles::pmtiles] Environment variable AWS_SKIP_CREDENTIALS is deprecated. Please use pmtiles.skip_signature in the configuration file instead.'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants