Skip to content
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

Improvements! #2

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.pyc
*.pdf
stocks/*
.idea/*
21 changes: 0 additions & 21 deletions README

This file was deleted.

37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Wordsearch generator
====================

(o Generador de sopas de letras)

Based on https://github.com/rboulton/wordsearch

Currently, this is a simple command-line script which generates a wordsearch
grid.

Usage:

python wordsearch.py <difficulty> [word...]

Example:

python wordsearch.py easy duck "polar bear" dog horse rabbit

The grid size, and permissible directions for words, is controlled by the
difficulty setting, which is one of `easy`, `normal` and `hard`.

The output grid is displayed on stdout, and written to a pdf file called with the same name of the first word.

Example of the generated pdf: https://github.com/jjconti/sopa-de-letras/blob/master/output_example.pdf

Requirements
============

* Reportlab (https://pypi.python.org/pypi/reportlab)

Improvements from the original version
======================================

* Better pdf layout
* Configurable header and footer
* Allow words with spaces (using quotes). Example: `python wordsearch.py hard word1 "word with spaces" word3`
* Allow not only ascii input (for example, words with ñ or á é í ó ú are fine)
4 changes: 4 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-

FIND_THE_WORDS = "Find the words: "
BOTTOM_TEXT = "Generated with ❤"
Binary file added output_example.pdf
Binary file not shown.
128 changes: 60 additions & 68 deletions wordsearch.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,22 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import random

from config import *

# Directions are:
# +. left to right
# -. right to left
# .+ top to bottom
# .- bottom to top

def read_words(filename):
words = set()
fd = open(filename)
try:
for line in fd.readlines():
if "'" in line:
continue
line = line.strip().lower()
if len(line) > 3 and len(line) < 7:
words.add(line)
finally:
fd.close()
return words

all_words = read_words('/usr/share/dict/words')
explicit_words = ('fuck', 'cunt', 'piss', 'bloody', 'shit', 'boob')
for word in explicit_words:
all_words.add(word)

all_directions = ('+-', '+.', '++', '.+', '.-', '--', '-.', '-+')

styles = {
'easy': ('10x10', ('+.', '.+')),
'standard': ('15x15', ('+-', '+.', '++', '.+', '.-', '-.')),
'hard': ('20x20', all_directions),
'hard': ('15x15', all_directions)
}

dirconv = {
Expand All @@ -41,52 +25,67 @@ def read_words(filename):
'+': 1,
}

letters = "abcdefghijklmnopqrstuvwxyz"
letters = u"abcdefghijklmnñopqrstuvwxyz"

class Grid(object):
def __init__(self, wid, hgt):
self.wid = wid
self.hgt = hgt
self.data = ['.'] * (wid * hgt)
self.used = [' '] * (wid * hgt)
self.hgt = hgt
self.data = ['.'] * (wid * hgt)
self.used = [' '] * (wid * hgt)
self.words = []

def to_text(self):
result = []
for row in xrange(self.hgt):
result.append(''.join(self.data[row * self.wid :
for row in xrange(self.hgt):
result.append(''.join(self.data[row * self.wid :
(row + 1) * self.wid]))
return '\n'.join(result)
return '\n'.join(result)

def used_to_text(self):
result = []
for row in xrange(self.hgt):
result.append(''.join(self.used[row * self.wid :
for row in xrange(self.hgt):
result.append(''.join(self.used[row * self.wid :
(row + 1) * self.wid]))
return '\n'.join(result)
return '\n'.join(result)

def to_pdf(self, filename):
def to_pdf(self, filename, words):
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4

pagesize = A4
paper = canvas.Canvas(filename, pagesize=pagesize)
margin = 50
printwid, printhgt = map(lambda x: x - margin * 2, pagesize)
from reportlab.lib.pagesizes import cm, A4
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib import colors
from reportlab.platypus.paragraph import Paragraph
from reportlab.lib.styles import ParagraphStyle
from reportlab.platypus.flowables import Spacer

gx = margin
gy = printhgt - margin
gdx = printwid / self.wid
gdy = printhgt / self.hgt
for y in xrange(self.hgt):
cy = gy - y * gdy
for x in xrange(self.wid):
cx = gx + x * gdx
p = x + self.wid * y
c = self.data[p]
paper.drawString(cx, cy, c)
paper.showPage()
paper.save()
doc = SimpleDocTemplate(filename, pagesize=A4)
data = [self.data[x: x + self.wid] for x in range(0, len(self.data), self.wid)]
l = cm * 1.25
t=Table(data, len(data[0]) * [l], len(data) * [l])
t.setStyle(TableStyle([('ALIGN',(0,0),(-1,-1),'CENTER'),
('VALIGN',(0,0),(-1,-1),'TOP'),
('BOX', (0,0), (-1,-1), 1, colors.black),
('FONTSIZE', (0,0), (-1,-1), 20)
]))
style = ParagraphStyle(
'default',
fontName='Times-Roman',
fontSize=18,
leading=18,
spaceBefore=10,
spaceAfter=10,
bulletFontName='Times-Roman',
bulletFontSize=18,
bulletIndent=0,
)
elements = [Paragraph(FIND_THE_WORDS, style, None)]
elements.append(Paragraph(", ".join(words), style))
elements.append(Spacer(1, 0.5 * cm))
elements.append(t)
style.fontSize = 12
elements.append(Spacer(1, 0.5 * cm))
elements.append(Paragraph(BOTTOM_TEXT, style, None))
doc.build(elements)

def pick_word_pos(self, wordlen, directions):
xd, yd = random.choice(directions)
Expand Down Expand Up @@ -140,9 +139,6 @@ def fill_in_letters(self):
if self.data[p] == '.':
self.data[p] = random.choice(letters)

def remove_bad_words(self):
return True

def make_grid(stylep="standard", words=[], tries=100):
# Parse and validate the style parameter.
size, directions = styles.get(stylep, (stylep, all_directions))
Expand All @@ -158,30 +154,26 @@ def make_grid(stylep="standard", words=[], tries=100):
for direction in directions]

while True:
while True:
grid = Grid(wid, hgt)
if grid.place_words(words, directions):
break
tries -= 1
if tries <= 0:
return None

grid.fill_in_letters()
if grid.remove_bad_words():
return grid

grid = Grid(wid, hgt)
if grid.place_words(words, directions):
break
tries -= 1
if tries <= 0:
return None

grid.fill_in_letters()
return grid

if __name__ == '__main__':
import sys
random.seed()
grid = make_grid(sys.argv[1], sys.argv[2:])
words = sys.argv[2:]
words_to_use = [unicode("".join(w.lower().split()), 'utf-8') for w in words]
grid = make_grid(sys.argv[1], words_to_use)
if grid is None:
print "Can't make a grid"
else:
print grid.to_text()
print
print grid.used_to_text()
grid.to_pdf("ws.pdf")
grid.to_pdf(words_to_use[0] + ".pdf", words)