-
-
Notifications
You must be signed in to change notification settings - Fork 306
test(mbtiles): Generate mbtiles dynamically from SQL files to increase debuggability and transparency #1868
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test(mbtiles): Generate mbtiles dynamically from SQL files to increase debuggability and transparency #1868
Conversation
|
@nyurik I created these test .sql files: CREATE TABLE meow (
text TEXT
);
.read init.sql
INSERT INTO meow VALUES ('meow');
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.sqliteSo we should be good with using |
|
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'); |
|
Unfortunately, there isn't one. Will have to do that manually (a small script should do the work) |
…jkl/martin into generate-mbtiles-on-the-fly
for more information, see https://pre-commit.ci
|
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 :) |
|
Should we create a new just recipe for creating .mbtiles from .sql files? We can integrate it in -test: start (test-cargo "--all-targets") test-doc test-int
+test: start prepare-fixtures (test-cargo "--all-targets") test-doc test-int |
|
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 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 Line 135 in a1250b9
|
|
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} |
|
that could be an interim step, agree |
|
the problem though is that users won't be able to run |
I'll look into this more, before I resolve to use files. |
|
Sorry for the delay in getting back to this.
I was wondering whether the goal is to initialize the |
let script = fs::read_to_string("path/to/something.sql").unwrap();
sqlx::raw_sql(script).execute(&mut conn).await.unwrap(); |
|
I updated the |
nyurik
left a comment
There was a problem hiding this 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.
|
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]>
|
sorry, all my other projects use |
CommanderStorm
left a comment
There was a problem hiding this 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/src/config/args/root.rs
Outdated
| "martin", | ||
| "../tests/fixtures/pmtiles/png.pmtiles", | ||
| "../tests/fixtures/mbtiles/json.mbtiles", | ||
| // "../tests/fixtures/mbtiles/json.mbtiles", |
There was a problem hiding this comment.
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?
| // "../tests/fixtures/mbtiles/json.mbtiles", |
There was a problem hiding this comment.
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.
sdf-jkl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self review
| 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()}); |
There was a problem hiding this comment.
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'), |
There was a problem hiding this comment.
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'), |
There was a problem hiding this comment.
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'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huge binary again
|
@sdf-jkl All of the issues that remain can/should be different PRs 😉 This is great work, thank you so much |
|
@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. |
## 🤖 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>
…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]>
## 🤖 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.'
Working on this:
mbtiles/sql/dir, addinit-flat.sql,init-flat-with-hash.sql, etc.{{#include file.rs}}-- Couldn't find where the mbtiles are being updated in tests.sh
sqlitecommand to create a blank .mbtiles file.dumpcommand.-- i am not sure if
.read filename.sqlcan be used from another .sql file?readfile('...')sqlite function can be used to get the file content as part of the insert statement.Related #1846