mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Added random lookup. #57
This commit is contained in:
parent
9e3d8b317d
commit
f5853c0a0b
2 changed files with 71 additions and 11 deletions
|
@ -2,6 +2,7 @@
|
|||
from collections import namedtuple
|
||||
import os, os.path
|
||||
import pkg_resources
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
|
||||
|
@ -18,7 +19,7 @@ from pokedex.db import connect
|
|||
import pokedex.db.tables as tables
|
||||
from pokedex.roomaji import romanize
|
||||
|
||||
__all__ = ['open_index', 'lookup']
|
||||
__all__ = ['open_index', 'lookup', 'random_lookup']
|
||||
|
||||
INTERMEDIATE_LOOKUP_RESULTS = 25
|
||||
MAX_LOOKUP_RESULTS = 10
|
||||
|
@ -176,6 +177,24 @@ rx_is_number = re.compile('^\d+$')
|
|||
|
||||
LookupResult = namedtuple('LookupResult',
|
||||
['object', 'name', 'language', 'exact'])
|
||||
|
||||
def _parse_table_name(name):
|
||||
"""Takes a singular table name, table name, or table object and returns the
|
||||
table name.
|
||||
|
||||
Returns None for a bogus name.
|
||||
"""
|
||||
if hasattr(name, '__tablename__'):
|
||||
return getattr(name, '__tablename__')
|
||||
elif name in indexed_tables:
|
||||
return name
|
||||
elif name + 's' in indexed_tables:
|
||||
return name + 's'
|
||||
else:
|
||||
# Bogus. Be nice and return dummy
|
||||
return None
|
||||
|
||||
|
||||
def lookup(input, valid_types=[], session=None, indices=None, exact_only=False):
|
||||
"""Attempts to find some sort of object, given a database session and name.
|
||||
|
||||
|
@ -245,6 +264,12 @@ def lookup(input, valid_types=[], session=None, indices=None, exact_only=False):
|
|||
# provided
|
||||
valid_types = prefixes
|
||||
|
||||
# Random lookup
|
||||
if name == 'random':
|
||||
return random_lookup(indices=(index, speller),
|
||||
session=session,
|
||||
valid_types=valid_types)
|
||||
|
||||
# Do different things depending what the query looks like
|
||||
# Note: Term objects do an exact match, so we don't have to worry about a
|
||||
# query parser tripping on weird characters in the input
|
||||
|
@ -270,16 +295,7 @@ def lookup(input, valid_types=[], session=None, indices=None, exact_only=False):
|
|||
### Filter by type of object
|
||||
type_terms = []
|
||||
for valid_type in valid_types:
|
||||
if hasattr(valid_type, '__tablename__'):
|
||||
table_name = getattr(valid_type, '__tablename__')
|
||||
elif valid_type in indexed_tables:
|
||||
table_name = valid_type
|
||||
elif valid_type + 's' in indexed_tables:
|
||||
table_name = valid_type + 's'
|
||||
else:
|
||||
# Bogus. Be nice and ignore it
|
||||
continue
|
||||
|
||||
table_name = _parse_table_name(valid_type)
|
||||
type_terms.append(whoosh.query.Term(u'table', table_name))
|
||||
|
||||
if type_terms:
|
||||
|
@ -326,3 +342,36 @@ def lookup(input, valid_types=[], session=None, indices=None, exact_only=False):
|
|||
# give us some padding, and should avoid that problem. Not a big deal if
|
||||
# we lose the 25th-most-likely match anyway.
|
||||
return objects[:MAX_LOOKUP_RESULTS]
|
||||
|
||||
|
||||
def random_lookup(valid_types=[], session=None, indices=None):
|
||||
"""Takes similar arguments as `lookup()`, but returns a random lookup
|
||||
result from one of the provided `valid_types`.
|
||||
"""
|
||||
|
||||
tables = []
|
||||
for valid_type in valid_types:
|
||||
table_name = _parse_table_name(valid_type)
|
||||
if table_name:
|
||||
tables.append(indexed_tables[table_name])
|
||||
|
||||
if not tables:
|
||||
tables = indexed_tables.values()
|
||||
|
||||
# Rather than create an array of many hundred items and pick randomly from
|
||||
# it, just pick a number up to the total number of potential items, then
|
||||
# pick randomly from that, and partition the whole range into chunks
|
||||
total = 0
|
||||
partitions = []
|
||||
for table in tables:
|
||||
count = session.query(table).count()
|
||||
total += count
|
||||
partitions.append((table, count))
|
||||
|
||||
n = random.randint(1, total)
|
||||
while n > partitions[0][1]:
|
||||
n -= partitions[0][1]
|
||||
partitions.pop(0)
|
||||
|
||||
return lookup(unicode(n), valid_types=[ partitions[0][0] ],
|
||||
indices=indices, session=session)
|
||||
|
|
|
@ -102,3 +102,14 @@ def test_wildcard_lookup():
|
|||
first_result = results[0]
|
||||
assert_equal(first_result.object.name, name,
|
||||
u'Wildcards work correctly')
|
||||
|
||||
def test_random_lookup():
|
||||
for _ in xrange(5):
|
||||
results = pokedex.lookup.lookup(u'random')
|
||||
assert_equal(len(results), 1, u'Random returns one result')
|
||||
|
||||
for table_name in [u'pokemon', u'moves', u'items', u'abilities', u'types']:
|
||||
results = pokedex.lookup.lookup(u'random', valid_types=[table_name])
|
||||
assert_equal(len(results), 1, u'Constrained random returns one result')
|
||||
assert_equal(results[0].object.__tablename__, table_name,
|
||||
u'Constrained random returns result from the right table')
|
||||
|
|
Loading…
Reference in a new issue