from pathlib import Path from PIL import Image, ImageDraw, ImageFont, ImageMorph, ImageFilter import numpy as np from Levenshtein import distance as lev import random CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" CHARSET1 = "ABCDEFGHLMNQRT" CHARSET2 = "IJKOPUXVZYWS" LENGTH = 6 LOWERCASE = 3 TEXT_SIZE = 32 TEXT_PADDING = TEXT_SIZE TEXT_FONT = Path(__file__).parent / "assets" / "FreeSansBold.otf" INPUT_TYPE = "text" INPUT_HINT = "Gépeld be az ábrán látható szöveget" def generate_puzzle_fields(): #text_orig = "".join((random.choice(CHARSET) for _ in range(LENGTH))) text_orig1 = "".join((random.choice(CHARSET1) for _ in range(int(LENGTH/2)))) text_orig2 = "".join((random.choice(CHARSET2) for _ in range(int(LENGTH/2)))) text_orig12 = text_orig1 + text_orig2 l = list(text_orig12) random.shuffle(l) text_orig = ''.join(l) ##let's swap some characters in order to make it more difficult change = random.sample(range(6), LOWERCASE) text = str() for i in range(0, len(text_orig)): if i in change: c = text_orig[i].swapcase() else: c = text_orig[i] text += c return dict(text=text, solution=text) def is_correct(response, puzzle): if lev(response, puzzle.solution) == 0: return 1 if lev(response, puzzle.solution) >= 1 and (response != "" and response is not None and len(response) == 6 and response.isalpha()): return lev(response, puzzle.solution)*(-1) if response == "" or response is None or len(response) != 6 or not response.isalpha(): return 0 def is_invalid(response): if response == "" or response is None or len(response) != 6 or not response.isalpha(): return True else: return False def render_image(puzzle): # Create white canvas and get drawing context #w, h = 250, 50 text = puzzle.text font = ImageFont.truetype(str(TEXT_FONT), TEXT_SIZE) w, h = 250, 50 img = Image.new('RGB', (w,h), color='white') w, h = ImageDraw.ImageDraw(img).textsize(text, font) draw = ImageDraw.Draw(img) # Generate a basic random colour, random RGB values 10-245 R, G, B = random.randint(10, 245), random.randint(10, 245), random.randint(10, 245), # Draw a random number of circles between 40-120 cmin = random.randint(50, 70) cmax = random.randint(90, 120) for _ in range(cmin, cmax): # Choose RGB values for this circle, somewhat close (+/-10) to basic RGB r = R + random.randint(-10, 10) g = G + random.randint(-10, 10) b = B + random.randint(-10, 10) diam = random.randint(5, 11) x, y = random.randint(0, w), random.randint(0, h) draw.ellipse([x, y, x + diam, y + diam], fill=(r, g, b)) # Blur the background a bit res = img.filter(ImageFilter.BoxBlur(3)) # Load font and draw text draw = ImageDraw.Draw(res) #font = ImageFont.truetype('/Library/Fonts/Arial.ttf', 36) draw.text((62,5), text, font=font, fill=(0,0,0)) img = res img = img.convert("L") distortions = [ #ImageMorph.MorphOp(op_name="edge"), #ImageMorph.MorphOp(op_name="corner"), ImageMorph.MorphOp(op_name="dilation4"), ImageMorph.MorphOp(op_name="erosion4") ] for op in distortions: _, img = op.apply(img) # Save result #img.save('_static/images/example.png') return img