1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
# -*- coding: utf-8 -*-
"""Art utility module."""
import random
from .params import FONT_MAP
from .params import DECORATION_NAMES, FONT_NAMES, NON_ASCII_FONTS
from .params import RANDOM_FILTERED_FONTS
from .params import XLARGE_WIZARD_FONT, LARGE_WIZARD_FONT, MEDIUM_WIZARD_FONT, SMALL_WIZARD_FONT
from .params import FONT_SMALL_THRESHOLD, FONT_MEDIUM_THRESHOLD, FONT_LARGE_THRESHOLD, TEXT_XLARGE_THRESHOLD
from .params import TEXT_LARGE_THRESHOLD, TEXT_MEDIUM_THRESHOLD
def distance_calc(s1, s2):
"""
Calculate Levenshtein distance between two words.
:param s1: first word
:type s1 : str
:param s2: second word
:type s2 : str
:return: distance between two word
References :
1- https://stackoverflow.com/questions/2460177/edit-distance-in-python
2- https://en.wikipedia.org/wiki/Levenshtein_distance
"""
if len(s1) > len(s2):
s1, s2 = s2, s1
distances = range(len(s1) + 1)
for i2, c2 in enumerate(s2):
distances_ = [i2 + 1]
for i1, c1 in enumerate(s1):
if c1 == c2:
distances_.append(distances[i1])
else:
distances_.append(
1 + min((distances[i1], distances[i1 + 1], distances_[-1])))
distances = distances_
return distances[-1]
def wizard_font(text):
"""
Check input text length for wizard mode.
:param text: input text
:type text:str
:return: font as str
"""
text_length = len(text)
if text_length <= TEXT_XLARGE_THRESHOLD:
font = random.choice(XLARGE_WIZARD_FONT)
elif text_length <= TEXT_LARGE_THRESHOLD:
font = random.choice(LARGE_WIZARD_FONT)
elif text_length <= TEXT_MEDIUM_THRESHOLD:
font = random.choice(MEDIUM_WIZARD_FONT)
else:
font = random.choice(SMALL_WIZARD_FONT)
return font
def indirect_font(font, text):
"""
Check input font for indirect modes.
:param font: input font
:type font : str
:param text: input text
:type text:str
:return: font as str
"""
fonts = FONT_NAMES
if font in ["rnd-small", "random-small", "rand-small"]:
font = random.choice(RND_SIZE_DICT["small_list"])
return font
if font in ["rnd-medium", "random-medium", "rand-medium"]:
font = random.choice(RND_SIZE_DICT["medium_list"])
return font
if font in ["rnd-large", "random-large", "rand-large"]:
font = random.choice(RND_SIZE_DICT["large_list"])
return font
if font in ["rnd-xlarge", "random-xlarge", "rand-xlarge"]:
font = random.choice(RND_SIZE_DICT["xlarge_list"])
return font
if font in ["random", "rand", "rnd"]:
filtered_fonts = list(set(fonts) - set(RANDOM_FILTERED_FONTS))
font = random.choice(filtered_fonts)
return font
if font in ["wizard", "wiz", "magic"]:
font = wizard_font(text)
return font
if font in ["rnd-na", "random-na", "rand-na"]:
font = random.choice(NON_ASCII_FONTS)
return font
if font not in fonts:
font = min(fonts, key=lambda x: distance_calc(font, x))
return font
def indirect_decoration(decoration):
"""
Check input decoration for indirect modes.
:param decoration: input decoration
:type decoration : str
:return: decoration as str
"""
decorations = DECORATION_NAMES
if decoration in ["random", "rand", "rnd"]:
decoration = random.choice(decorations)
return decoration
if decoration not in decorations:
decoration = min(decorations, key=lambda x: distance_calc(decoration, x))
return decoration
def font_size_splitter(font_map):
"""
Split fonts to 4 category (small,medium,large,xlarge) by maximum length of letter in each font.
:param font_map: input fontmap
:type font_map : dict
:return: splitted fonts as dict
"""
small_font, medium_font, large_font, xlarge_font = [], [], [], []
fonts = set(font_map) - set(RANDOM_FILTERED_FONTS)
for font in sorted(fonts):
length = max(len(x) for x in font_map[font][0].values())
if length <= FONT_SMALL_THRESHOLD:
small_font.append(font)
elif length <= FONT_MEDIUM_THRESHOLD:
medium_font.append(font)
elif length <= FONT_LARGE_THRESHOLD:
large_font.append(font)
else:
xlarge_font.append(font)
return {
"small_list": small_font,
"medium_list": medium_font,
"large_list": large_font,
"xlarge_list": xlarge_font}
RND_SIZE_DICT = font_size_splitter(FONT_MAP) # pragma: no cover
|