#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""A module to compress and sort legends exports from DF 0.40.09 and later.
- .bmp converted to .png where possible.
- Create an archive for Legends Viewer if possible, or just compress
the (huge) xml.
- Sort files into region folder, with maps subfolders, and move to user
content folder if this folder exists.
"""
import glob
import os
import re
import subprocess
import zipfile
from . import log, paths
from .lnp import lnp
[docs]def get_region_info():
"""Returns a tuple of strings for an available region and date.
Eg: ('region1', '00250-01-01')
"""
files = [f for f in glob.glob(paths.get('df', 'region*-*-??-??-*')) if
os.path.isfile(f)]
if files:
fname = os.path.basename(files[0])
region = re.search(
r'^.*(?=(-\d{5,}-\d{2}-\d{2}))', fname).group()
date = re.search(r'\d{5,}-\d{2}-\d{2}', fname).group()
return region, date
return None
[docs]def compress_bitmaps():
"""Compresses all bitmap maps."""
# pylint: disable=import-error
try:
from PIL import Image
except ImportError:
try:
import Image
except ImportError:
call_optipng()
else:
log.i('Compressing bitmaps with PIL/Pillow')
for fname in glob.glob(paths.get(
'df', '-'.join(get_region_info()) + '-*.bmp')):
f = Image.open(fname)
f.save(fname[:-3] + 'png', format='PNG', optimize=True)
os.remove(fname)
[docs]def call_optipng():
"""Calling optipng can work well, but isn't very portable."""
if os.name == 'nt' and os.path.isfile(paths.get('df', 'optipng.exe')):
log.w('Falling back to optipng for image compression. '
'It is recommended to install PIL.')
for fname in glob.glob(paths.get(
'df', '-'.join(get_region_info()) + '-*.bmp')):
ret = subprocess.call([paths.get('df', 'optipng'), '-zc9', '-zm9',
'-zs0', '-f0', fname],
creationflags=0x00000008)
if ret == 0:
os.remove(fname)
else:
log.e('A PIL-compatible library is required to compress bitmaps.')
[docs]def choose_region_map():
"""Returns the most-preferred region map available, or fallback."""
pattern = paths.get('df', '-'.join(get_region_info()) + '-')
for name in ('detailed', 'world_map'):
for ext in ('.png', '.bmp'):
if os.path.isfile(pattern + name + ext):
return pattern + name + ext
return pattern + 'world_map.bmp'
[docs]def create_archive():
"""Creates a legends archive, or zips the xml if files are missing."""
pattern = paths.get('df', '-'.join(get_region_info()) + '-')
worldgen = paths.get('df', get_region_info()[0] + '-world_gen_param.txt')
filepaths = [pattern + 'legends.xml', pattern + 'world_history.txt', worldgen,
choose_region_map(), pattern + 'world_sites_and_pops.txt']
if os.path.isfile(pattern + 'legends_plus.xml'):
filepaths.append(pattern + 'legends_plus.xml')
if all(os.path.isfile(f) for f in filepaths):
with zipfile.ZipFile(pattern + 'legends_archive.zip',
'w', zipfile.ZIP_DEFLATED, allowZip64=True) as zipped:
for f in filepaths:
zipped.write(f, os.path.basename(f))
os.remove(f)
elif os.path.isfile(pattern + 'legends.xml'):
with zipfile.ZipFile(pattern + 'legends_xml.zip',
'w', zipfile.ZIP_DEFLATED, allowZip64=True) as zipped:
zipped.write(pattern + 'legends.xml',
os.path.basename(pattern + 'legends.xml'))
os.remove(pattern + 'legends.xml')
[docs]def move_files():
"""Moves files to a subdir, and subdir to ../User Generated Content if
that dir exists."""
pattern = paths.get('df', '-'.join(get_region_info()))
region = get_region_info()[0]
dirname = get_region_info()[0] + '_legends_exports'
if os.path.isdir(paths.get('root', 'User Generated Content')):
dirname = paths.get(
'root', 'User Generated Content', 'Legends', dirname)
if not os.path.isdir(dirname):
os.makedirs(dirname)
else:
dirname = paths.get('df', dirname)
for site_map in glob.glob(pattern + '-site_map-*'):
target = os.path.join(dirname, 'site_maps', os.path.basename(site_map))
if os.path.isfile(target):
os.remove(site_map)
continue
os.renames(site_map, target)
maps = ('world_map', 'bm', 'detailed', 'dip', 'drn', 'el', 'elw',
'evil', 'hyd', 'nob', 'rain', 'sal', 'sav', 'str', 'tmp',
'trd', 'veg', 'vol')
for m in maps:
m = glob.glob(pattern + '-' + m + '.???')
if m:
log.d('Found the following region map: ' + str(m[0]))
t = os.path.join(dirname, 'region_maps', os.path.basename(m[0]))
if os.path.isfile(t):
os.remove(m[0])
continue
os.renames(m[0], t)
for f in glob.glob(paths.get('df', region + '-*')):
log.d('Found the following misc files: ' + str(f))
if os.path.isfile(f):
target = os.path.join(dirname, os.path.basename(f))
if os.path.isfile(target):
os.remove(f)
continue
os.renames(f, target)
for f in glob.glob(paths.get('df', '*_color_key.txt')):
os.remove(f)
[docs]def process_legends():
"""Process all legends exports in sets."""
if lnp.df_info.version >= '0.40.09':
i = 0
while get_region_info():
log.i('Processing legends from ' + get_region_info()[0])
compress_bitmaps()
create_archive()
move_files()
i += 1
return i
return None