コード例 #1
0
ファイル: crossword.py プロジェクト: pmaher86/blacksquare
    def to_puz(self, filename: str) -> None:
        """Outputs a .puz file from the Crossword object.

        Args:
            filename (str): The output path.
        """
        puz_black, puz_empty = ".", "-"
        puz_obj = puz.Puzzle()
        puz_obj.height = self.num_rows
        puz_obj.width = self.num_cols

        char_array = np.array([cell.str for cell in self._grid.ravel()])
        puz_obj.solution = ("".join(char_array).replace(
            EMPTY.str, puz_empty).replace(BLACK.str, puz_black))
        fill_grid = char_array.copy()
        fill_grid[fill_grid != BLACK.str] = puz_empty
        fill_grid[fill_grid == BLACK.str] = puz_black
        puz_obj.fill = "".join(fill_grid)
        sorted_words = sorted(list(self.iterwords()),
                              key=lambda w: (w.number, w.direction))
        puz_obj.clues = [w.clue for w in sorted_words]
        puz_obj.cksum_global = puz_obj.global_cksum()
        puz_obj.cksum_hdr = puz_obj.header_cksum()
        puz_obj.cksum_magic = puz_obj.magic_cksum()
        puz_obj.save(filename)
コード例 #2
0
    def parse_xword(self, xword_data):
        xword_metadata = xword_data.get('copy', '')
        xword_data = xword_data.get('grid', '')

        date_string = xword_metadata.get('date-publish-analytics').split()[0]

        self.date = datetime.datetime.strptime(date_string, '%Y/%m/%d')

        fetched = {}
        for field in ['title', 'byline', 'publisher']:
            fetched[field] = html2text(xword_metadata.get(field, ''),
                                       bodywidth=0).strip()

        puzzle = puz.Puzzle()
        puzzle.title = fetched.get('title')
        puzzle.author = fetched.get('byline')
        puzzle.copyright = fetched.get('publisher')
        puzzle.width = int(xword_metadata.get('gridsize').get('cols'))
        puzzle.height = int(xword_metadata.get('gridsize').get('rows'))

        solution = ''
        fill = ''
        markup = b''

        for row in xword_data:
            for cell in row:
                if not cell['Letter']:
                    fill += '.'
                    solution += '.'
                    markup += b'\x00'
                else:
                    fill += '-'
                    solution += cell['Letter']
                    markup += (b'\x80' if (cell.get('style','')
                                           and cell['style']['shapebg']
                                           == 'circle') \
                                       else b'\x00')

        puzzle.fill = fill
        puzzle.solution = solution

        clue_list = xword_metadata['clues'][0]['clues'] + xword_metadata[
            'clues'][1]['clues']
        sorted_clue_list = sorted(clue_list, key=lambda x: int(x['number']))

        clues = [clue['clue'] for clue in sorted_clue_list]
        normalized_clues = [
            html2text(unidecode(clue), bodywidth=0) for clue in clues
        ]

        puzzle.clues = normalized_clues

        has_markup = b'\x80' in markup

        if has_markup:
            puzzle.extensions[b'GEXT'] = markup
            puzzle._extensions_order.append(b'GEXT')
            puzzle.markup()

        return puzzle
コード例 #3
0
ファイル: xword_dl.py プロジェクト: offbyone/xword-dl
    def __init__(self, output=None):
        self.output = output
        if self.output and not self.output.endswith('.puz'):
            self.output = self.output + '.puz'
        self.puzfile = puz.Puzzle()

        self.outlet_prefix = None
        self.date = None
コード例 #4
0
 def test_save_empty_puzzle(self):
     ''' confirm an empty Puzzle() can be saved to a file '''
     p = puz.Puzzle()
     with tempfile.NamedTemporaryFile(suffix='.puz') as tmp:
         p.save(tmp.name)
         p2 = puz.read(tmp.name)
         self.assertEqual(p.puzzletype, p2.puzzletype)
         self.assertEqual(p.version, p2.version)
         self.assertEqual(p.scrambled_cksum, p2.scrambled_cksum)
コード例 #5
0
ファイル: xword_dl.py プロジェクト: divergentdave/xword-dl
def get_amuse_puzzle(url, output):
    res = requests.get(url)

    rawc = next((line.strip()
                 for line in res.text.splitlines() if 'window.rawc' in line),
                None)

    if not rawc:
        sys.exit("Crossword puzzle not found.")

    rawc = rawc.lstrip("window.rawc = '")
    rawc = rawc.rstrip("';")

    xword_data = json.loads(base64.b64decode(rawc))

    p = puz.Puzzle()

    p.title = xword_data.get('title', '')
    p.author = xword_data.get('author', '')
    p.copyright = xword_data.get('copyright', '')
    p.width = xword_data.get('w')
    p.height = xword_data.get('h')

    solution = ''
    fill = ''
    box = xword_data['box']
    for row_num in range(xword_data.get('h')):
        for column in box:
            cell = column[row_num]
            if cell == '\x00':
                solution += '.'
                fill += '.'
            else:
                solution += cell
                fill += '-'
    p.solution = solution
    p.fill = fill

    placed_words = xword_data['placedWords']
    across_words = [word for word in placed_words if word['acrossNotDown']]
    down_words = [word for word in placed_words if not word['acrossNotDown']]

    weirdass_puz_clue_sorting = sorted(
        placed_words,
        key=lambda word: (word['y'], word['x'], not word['acrossNotDown']))

    clues = [word['clue']['clue'] for word in weirdass_puz_clue_sorting]

    normalized_clues = [
        html2text(unidecode(clue), bodywidth=0) for clue in clues
    ]

    p.clues.extend(normalized_clues)

    p.save(output)

    print("Puzzle downloaded and saved as {}.".format(output))
コード例 #6
0
def crossword_to_puz(crossword):
    p = puz.Puzzle()
    p.preamble = b""
    p.title = "PanLex Crossword"
    p.author = "PanLex"
    p.copyright = "n/a"
    p.width = crossword.cols
    p.height = crossword.rows
    p.solution = grid_to_solution(crossword.best_grid)
    p.fill = re.sub(r"[^.]", "-", p.solution)
    p.clues = [w[1] for w in sorted(crossword.best_wordlist, key=lambda x: x[2:])]
    return p
コード例 #7
0
ファイル: xword_dl.py プロジェクト: thisisparker/xword-dl
    def parse_xword(self, xword_data):
        fetched = {}
        for field in ['Title', 'Author', 'Editor', 'Copryight']:
            fetched[field] = urllib.parse.unquote(xword_data.get(field,
                                                                 '')).strip()

        puzzle = puz.Puzzle()
        puzzle.title = fetched.get('Title', '')
        puzzle.author = ''.join(
            [fetched.get('Author', ''), ' / Ed. ',
             fetched.get('Editor', '')])
        puzzle.copyright = fetched.get('Copyright', '')
        puzzle.width = int(xword_data.get('Width'))
        puzzle.height = int(xword_data.get('Height'))

        solution = xword_data.get('AllAnswer').replace('-', '.')

        puzzle.solution = solution

        fill = ''
        for letter in solution:
            if letter == '.':
                fill += '.'
            else:
                fill += '-'
        puzzle.fill = fill

        across_clues = xword_data['AcrossClue'].splitlines()
        down_clues = self.process_clues(xword_data['DownClue'].splitlines())

        clues_list = across_clues + down_clues

        clues_list_stripped = [{
            'number': clue.split('|')[0],
            'clue': clue.split('|')[1]
        } for clue in clues_list]

        clues_sorted = sorted(clues_list_stripped, key=lambda x: x['number'])

        clues = [clue['clue'] for clue in clues_sorted]

        puzzle.clues = clues

        return puzzle
コード例 #8
0
 def test_save_small_puzzle(self):
     ''' an example of creating a small 3x3 puzzle from scratch and writing
     to a file
     '''
     p = puz.Puzzle()
     with tempfile.NamedTemporaryFile(suffix='.puz') as tmp:
         p.title = 'Test Puzzle'
         p.author = 'Alex'
         p.height = 3
         p.width = 3
         p.solution = 'A' * 9
         p.clues = ['clue'] * 6
         p.fill = '-' * 9
         p.save(tmp.name)
         p2 = puz.read(tmp.name)
         self.assertEqual(p.title, p2.title)
         self.assertEqual(p.author, p2.author)
         self.assertEqual(p.solution, p2.solution)
         self.assertEqual(p.clues, p2.clues)
         self.assertEqual(p.fill, p2.fill)
コード例 #9
0
def printBinary(ip):
  np = puz.Puzzle()
  np.author = ip['author']
  np.title = ip['title']
  np.copyright = ip['copyright']
  np.width = ip['dimensions']['width']
  np.height = ip['dimensions']['height']
    
  # Converting a solution: The ipuz format is an array of array of chars.
  # The puz format is a single string, known to be width x height chars.
  # Just need to convert # to . as each of those is the empty cell marking.
  sstrings = [''.join(row) for row in ip['solution']]
  sstring = ''.join(sstrings)
  sstring = sstring.replace('#', '.')
    
  np.solution = ''.join(sstring)
  np.fill = re.sub(r"[^.]", "-", np.solution)

  # origin and publisher fields ignored in ipuzzle. What about kind?
  # Ignoring 'puzzle' field, which contains a sophisticated grid format.
    
  # Fortunately ipuz specifies clue numbers, which allows us to order
  # in PUZ's unclear clue ordering.
  a = [(n, latin1ify(clue)) for n, clue in ip['clues']['Across']]
  d = [(n + 0.5, latin1ify(clue)) for n, clue in ip['clues']['Down']]
  np.clues = [clue for _, clue in sorted(a + d)]

  np.markup().markup = [0] * np.width * np.height
  for y, cols in enumerate(ip['puzzle']):
    for x, cell in enumerate(cols):
      if not isinstance(cell, dict):
        continue
      shapebg = cell.get('style', {}).get('shapebg')
      if shapebg == 'circle':
        np.markup().markup[y * np.width + x] = puz.GridMarkup.Circled

  # np.preamble = ip['intro']
  np.save(output_file)
コード例 #10
0
    def to_puz(self, filename: str):
        """Ouputs a .puz file from the Crossword object.

        Args:
            filename (str): The output path.
        """
        puz_obj = puz.Puzzle()
        puz_obj.height = self.num_rows
        puz_obj.width = self.num_cols
        puz_obj.solution = ("".join(self._grid.ravel()).replace(
            black, ".").replace(empty, "-"))
        fill_grid = self._grid.copy()
        fill_grid[fill_grid != black] = "-"
        fill_grid[fill_grid == black] = "."
        puz_obj.fill = "".join(fill_grid.ravel())
        sorted_words = sorted(
            list(self.iterwords()),
            key=lambda w: w.number + (0.5 if w.direction == down else 0),
        )
        puz_obj.clues = [w.clue for w in sorted_words]
        puz_obj.cksum_global = puz_obj.global_cksum()
        puz_obj.cksum_hdr = puz_obj.header_cksum()
        puz_obj.cksum_magic = puz_obj.magic_cksum()
        puz_obj.save(filename)
コード例 #11
0
ファイル: qxw2puz.py プロジェクト: rsbowen/xwordtools
                        metavar='p',
                        type=str,
                        help='Path to the output .puz file')
    parser.add_argument('--cluesfile',
                        metavar='c',
                        type=str,
                        help="Path to the clues file")
    parser.add_argument('--author', metavar='a', type=str, help="Author")
    parser.add_argument('--title', metavar='t', type=str, help="Title")
    parser.add_argument('--copyright', metavar='t', type=str, help="Title")

    ns = parser.parse_args()

    (rows, cols, solution) = ReadQXW(ns.qxwfile)

    puzzle = puz.Puzzle()
    puzzle.solution = "".join(solution).upper()
    puzzle.height = rows
    puzzle.width = cols
    puzzle.fill = "".join([('.' if c == '.' else '-') for c in solution])
    clues = [s.strip() for s in file(ns.cluesfile).readlines()]
    puzzle.clues = OrderClues(clues, puzzle.fill, rows, cols)

    puzzle.author = ns.author
    puzzle.title = ns.title
    # Another tool, decode_crossword.perl, explicitly looks for the copyright symbol 0xA9. So, include it.
    puzzle.copyright = u'' + unichr(0xA9) + (ns.copyright
                                             if ns.copyright else "")
    puzzle.notes = ""

    print puzzle.__dict__
コード例 #12
0
    def parse_xword(self, xword_data):
        puzzle = puz.Puzzle()
        puzzle.title = xword_data.get('title', '').strip()
        puzzle.author = xword_data.get('author', '').strip()
        puzzle.copyright = xword_data.get('copyright', '').strip()
        puzzle.width = xword_data.get('w')
        puzzle.height = xword_data.get('h')

        markup_data = xword_data.get('cellInfos', '')

        circled = [(square['x'], square['y']) for square in markup_data
                   if square['isCircled']]

        solution = ''
        fill = ''
        markup = b''
        rebus_board = []
        rebus_index = 0
        rebus_table = ''

        box = xword_data['box']
        for row_num in range(xword_data.get('h')):
            for col_num, column in enumerate(box):
                cell = column[row_num]
                if cell == '\x00':
                    solution += '.'
                    fill += '.'
                    markup += b'\x00'
                    rebus_board.append(0)
                elif len(cell) == 1:
                    solution += cell
                    fill += '-'
                    markup += b'\x80' if (col_num,
                                          row_num) in circled else b'\x00'
                    rebus_board.append(0)
                else:
                    solution += cell[0]
                    fill += '-'
                    rebus_board.append(rebus_index + 1)
                    rebus_table += '{:2d}:{};'.format(rebus_index, cell)
                    rebus_index += 1

        puzzle.solution = solution
        puzzle.fill = fill

        placed_words = xword_data['placedWords']
        across_words = [word for word in placed_words if word['acrossNotDown']]
        down_words = [
            word for word in placed_words if not word['acrossNotDown']
        ]

        weirdass_puz_clue_sorting = sorted(
            placed_words,
            key=lambda word: (word['y'], word['x'], not word['acrossNotDown']))

        clues = [word['clue']['clue'] for word in weirdass_puz_clue_sorting]

        normalized_clues = [
            html2text(unidecode(clue), bodywidth=0) for clue in clues
        ]
        puzzle.clues.extend(normalized_clues)

        has_markup = b'\x80' in markup
        has_rebus = any(rebus_board)

        if has_markup:
            puzzle.extensions[b'GEXT'] = markup
            puzzle._extensions_order.append(b'GEXT')
            puzzle.markup()

        if has_rebus:
            puzzle.extensions[b'GRBS'] = bytes(rebus_board)
            puzzle.extensions[b'RTBL'] = rebus_table.encode(puz.ENCODING)
            puzzle._extensions_order.extend([b'GRBS', b'RTBL'])
            puzzle.rebus()

        return puzzle
コード例 #13
0
 def test_junk_at_end_of_puzzle(self):
     with open('testfiles/washpost.puz', 'rb') as fp:
         data = fp.read() + b'\r\n\r\n'
     p = puz.Puzzle()
     p.load(data)
     self.assertEqual(p.postscript, b'\r\n\r\n')
コード例 #14
0
 def test_empty_puzzle(self):
     p = puz.Puzzle()
     self.assertRaises(puz.PuzzleFormatError, p.load, b'')
コード例 #15
0
    def parse_xword(self, xword_data):
        puzzle = puz.Puzzle()

        metadata = xword_data.get('puzzle_meta')
        puzzle.author = metadata.get('author').strip()
        puzzle.copyright = metadata.get('copyright').strip()
        puzzle.height = metadata.get('height')
        puzzle.width = metadata.get('width')

        if metadata.get('notes'):
            puzzle.notes = metadata.get('notes')[0]['txt'].strip()

        date_string = metadata.get('printDate')

        self.date = datetime.datetime.strptime(date_string, '%Y-%m-%d')

        puzzle.title = metadata.get('title') or self.date.strftime(
                '%A, %B %d, %Y')

        puzzle_data = xword_data['puzzle_data']

        solution = ''
        fill = ''
        markup = b''
        rebus_board = []
        rebus_index = 0
        rebus_table = ''

        for idx, square in enumerate(puzzle_data['answers']):
            if not square:
                solution += '.'
                fill += '.'
                rebus_board.append(0)
            elif len(square) == 1:
                solution += square
                fill += '-'
                rebus_board.append(0)
            else:
                solution += square[0][0]
                fill += '-'
                rebus_board.append(rebus_index + 1)
                rebus_table += '{:2d}:{};'.format(rebus_index, square[0])
                rebus_index += 1

            markup += (b'\x80' if puzzle_data['layout'][idx] == 3 else b'\x00')

        puzzle.solution = solution
        puzzle.fill = fill

        clue_list = puzzle_data['clues']['A'] + puzzle_data['clues']['D']
        clue_list.sort(key=lambda c: c['clueNum'])

        puzzle.clues = [unidecode(c['value']).strip() for c in clue_list]

        if b'\x80' in markup:
            puzzle.extensions[b'GEXT'] = markup
            puzzle._extensions_order.append(b'GEXT')
            puzzle.markup()

        if any(rebus_board):
            puzzle.extensions[b'GRBS'] = bytes(rebus_board)
            puzzle.extensions[b'RTBL'] = rebus_table.encode(puz.ENCODING)
            puzzle._extensions_order.extend([b'GRBS', b'RTBL'])
            puzzle.rebus()

        return puzzle