Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
deyk committed May 6, 2012
2 parents c32fdc0 + 55c4d89 commit 33ad071
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 0 deletions.
3 changes: 3 additions & 0 deletions blueprint/__init__.py
Expand Up @@ -14,9 +14,12 @@
from fields import *
from mods import *
from factories import *
from markov import *
from collection import *

__all__ = list(base.__all__) \
+ fields.__all__ \
+ mods.__all__ \
+ factories.__all__ \
+ collection.__all__ \
+ ['base', 'fields', 'taggables', 'factories', 'mods', 'dice']
8 changes: 8 additions & 0 deletions blueprint/base.py
Expand Up @@ -55,6 +55,8 @@ def __deepcopy__(self, memo):
for name, value in self.__dict__.iteritems():
if name == 'source' or name == 'parent':
setattr(meta, name, value)
elif name == 'random':
meta.random = random.Random()
else:
setattr(meta, name, copy.deepcopy(value, memo))
memo[self] = meta
Expand Down Expand Up @@ -189,6 +191,8 @@ def __init__(self, parent=None, seed=None, **kwargs):
self.meta.mastered = True
if seed is not None:
self.meta.seed = seed
elif parent is not None:
self.meta.seed = parent.meta.seed
else:
self.meta.seed = random.random()
self.meta.random.seed(self.meta.seed)
Expand Down Expand Up @@ -237,3 +241,7 @@ def resolve(name, field):
name = deferred_to_end.pop()
field = getattr(self, name)
resolve(name, field)

@fields.generator
def as_dict(self):
return dict((n, getattr(self, n)) for n in self.meta.fields)
45 changes: 45 additions & 0 deletions blueprint/collection.py
@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
"""blueprint.collections -- a collection class for blueprints.
"""
import sys
import collections

__all__ = ['BlueprintCollection']


class BlueprintCollection(collections.Sequence, collections.Callable):
def __init__(self, blueprint, seed='', **kwargs):
self.blueprint = blueprint
self.seed = seed
self.kwargs = kwargs

def __len__(self):
return sys.maxint

def __iter__(self):
return iter(self)

def __contains__(self):
return True

def __call__(self, parent=None, seed=None, **kwargs):
options = {}
options.update(self.kwargs)
options.update(kwargs)
return self.blueprint(parent=parent,
seed=seed if seed is not None else self.seed,
**options)

def __getitem__(self, idx):
if isinstance(idx, slice):
seed = u"%s%%s" % self.seed
if idx.stop is None:
return (self(seed=seed % i, **self.kwargs)
for i in it.count(idx.start or 0, idx.step or 1))
else:
return [self(seed=seed % i)
for i in xrange(idx.start or 0,
idx.stop, idx.step or 1)]
else:
seed = u"%s%s" % (self.seed, idx)
return self(seed=seed)
3 changes: 3 additions & 0 deletions blueprint/dice.py
Expand Up @@ -12,6 +12,9 @@ class results(list):
def __int__(self):
return int(sum(self))

def __hash__(self):
return hash(int(self))

def __float__(self):
return float(sum(self))

Expand Down
78 changes: 78 additions & 0 deletions blueprint/markov.py
@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
"""blueprint.markov -- Markov Chain generator.
"""
import collections

from blueprint import fields

__all__ = ['MarkovChain']


class MarkovChain(fields.Field, collections.Mapping):
"""Uses a Markov Chain to generate random sequences.
Derived from Peter Corbett's CGI random name generator, with input
from the ElderLore object-oriented variation.
http://www.pick.ucam.org/~ptc24/mchain.html
"""
def __init__(self, source_list, chainlen=2, max_length=10):
if 1 > chainlen > 10:
raise ValueError("Chain length must be between 1 and 10, inclusive")
self._dict = collections.defaultdict(list)
self.chainlen = chainlen
self.max_length = max_length
self.readData(source_list)

def next(self):
return self.getRandomName()

def readData(self, names, destroy=False):
if destroy:
self._dict.clear()

oldnames = []
chainlen = self.chainlen

for name in names:
oldnames.append(name)
spacer = u''.join((u" " * chainlen, name))
name_len = len(name)
for num in xrange(name_len):
self.add_key(spacer[num:num+chainlen], spacer[num+chainlen])
self.add_key(spacer[name_len:name_len+chainlen], "\n")

def getRandomName(self, parent):
"""Return a random name.
"""
prefix = u" " * self.chainlen
name = u""
suffix = u""
while 1:
suffix = self.get_suffix(prefix, parent)
if suffix == u"-":
continue
elif suffix == u"\n" or len(name) == self.max_length:
break
else:
name = u''.join((name, suffix))
prefix = u''.join((prefix[1:], suffix))
return name

def __call__(self, parent):
return self.getRandomName(parent)

def __getitem__(self, key):
return self._dict[key]

def __len__(self):
return len(self._dict)

def __iter__(self):
return iter(self._dict)

def add_key(self, prefix, suffix):
self._dict[prefix].append(suffix)

def get_suffix(self, prefix, parent):
return parent.meta.random.choice(self[prefix])

0 comments on commit 33ad071

Please sign in to comment.