#!/usr/bin/env python # -*- coding: utf-8 -*- """ This module can be used to create and display Mini-Lycacodes (C) 2022 Louis Heredero louis.heredero@edu.vs.ch """ import pygame import numpy as np import hamming S = 600 class LycacodeError(Exception): pass class LycacodeMini: BLACK = (158,17,26) #BLACK = (0,0,0) WHITE = (255,255,255) OFFSETS = [(0,-1), (1,0), (0,1), (-1,0)] FRAME = True CIRCLES = True DOTS = True DB_SQUARES = False def __init__(self, id_): self.id = id_ self.encode() self.create_matrix() def encode(self): self.bits = f"{self.id:020b}" self.bits = list(map(int, self.bits)) parity = [sum(self.bits[i*5:i*5+5])%2 for i in range(4)] for i in range(4): self.bits.insert((4-i)*5, parity[3-i]) def create_matrix(self): self.matrix = np.zeros([9, 9])-1 self.matrix[4:5, :] = 0 self.matrix[:, 4:5] = 0 self.matrix[1:2, 3:6] = 0 self.matrix[3:6, 1:2] = 0 self.matrix[-2:-1, -6:-3] = 0 self.matrix[-6:-3, -2:-1] = 0 self.matrix[4,4] = -1 for y in range(9): for x in range(9): if self.matrix[y,x] == 0: self.matrix[y,x] = self.bits.pop(0) if len(self.bits) == 0: break if len(self.bits) == 0: break def display(self, surf): S = min(surf.get_size()) s = int(S/12/3)*3 O = (S-s*9)/2 surf.fill(self.WHITE) # Frame if self.FRAME: pygame.draw.rect(surf, self.BLACK, [O-s, O-s, s*11, s*11]) pygame.draw.rect(surf, self.WHITE, [O-s*0.5, O-s*0.5, s*10, s*10]) # Cross for i in range(4): dx, dy = self.OFFSETS[i] X, Y = S/2 + dx*s*3, S/2 + dy*s*3 if self.CIRCLES: for j in range(3): dx2, dy2 = self.OFFSETS[(i+j-1)%4] pygame.draw.circle(surf, self.BLACK, [X+dx2*s, Y+dy2*s], 0.75*s) pygame.draw.rect(surf, self.BLACK, [X-(1.5-abs(dx))*s, Y-(1.5-abs(dy))*s, s*(3-abs(dx)*2), s*(3-abs(dy)*2)]) pygame.draw.rect(surf, self.BLACK, [O, S/2-s/2, 9*s, s]) pygame.draw.rect(surf, self.BLACK, [S/2-s/2, O, s, 9*s]) # Dots if self.DOTS: for y in range(9): for x in range(9): if self.matrix[y, x] == 1: pygame.draw.circle(surf, self.WHITE, [O+(x+0.5)*s, O+(y+0.5)*s], s/3) # Center pygame.draw.circle(surf, self.WHITE, [O+4.5*s, O+4.25*s], s/6) pygame.draw.circle(surf, self.WHITE, [O+4.25*s, O+4.75*s], s/6) def save(self, path): S = 600 s = int(S/12) O = (S-s*9)/2 BLACK = "#9E111A" WHITE = "#FFFFFF" with open(path, "w") as f: f.write(f"\n") # Background f.write(f"\n") # Frame f.write(f"\n") # Cross for i in range(4): dx, dy = self.OFFSETS[i] X, Y = S/2 + dx*s*3, S/2 + dy*s*3 if self.CIRCLES: for j in range(3): dx2, dy2 = self.OFFSETS[(i+j-1)%4] f.write(f"\n") f.write(f"\n") # Cross f.write(f"\n") f.write(f"\n") # Dots if self.DOTS: for y in range(9): for x in range(9): if self.matrix[y, x] == 1: f.write(f"\n") # Center f.write(f"\n") f.write(f"\n") f.write("") def save(self): path = input("Save as (.png or .svg): ") if path.endswith(".svg"): code.save(path) else: pygame.image.save(w, path) if __name__ == "__main__": import base b = base.Base(S, S, "Mini-Lycacode generator") code = LycacodeMini(16048) code.display(b.w) b.save = save b.main()