Language Python
(Advanced, extensible beer/wall framework)
Date: | 05/17/06 |
Author: | Jamie Turner |
URL: | http://jamwt.com |
Comments: | 7 |
Info: | http://python.org |
Score: | (3.03 in 191 votes) |
'''An extensible framework for simulated bottle buying, putting away, taking down, and drinking. ''' import sys def vernacularFilter(f): '''Let's say "no more" instead of "zero" ''' def _f(*args, **kw): word = f(*args, **kw) if word == 'zero': return 'no more' return word return _f class LanguageTranslationError(Exception): pass class NumToLanguageTranslator: '''Translate integers to spoken words, for various locales. ''' DEFAULT_LOCALE = 'en-US' def __init__(self, locale=DEFAULT_LOCALE): self.translate = getattr(self, 'translate_%s' % locale.lower().replace('-','_')) if not self.translate: raise LanguageTranslationError, \ "Missing locale translation tables for numeric values" # en-US section. More to follow EN_US_SINGLETON = { 0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', 11: 'eleven', 12: 'twelve', 20: 'twenty', 30: 'thirty', 40: 'fourty', 50: 'fifty', 60: 'sixty', 70: 'seventy', 80: 'eighty', 90: 'ninety', } EN_US_TEENS = (13,20) EN_US_TEEN_SPECIAL_PFX = { 3: 'thir', 4: 'four', 5: 'fif', 8: 'eigh', } EN_US_RANGE = (0, 100) EN_US_TEEN_SFX = 'teen' @vernacularFilter def translate_en_us(self, num): '''Translations for en-US; currently only 0-99 are supported. That should be enough bottles for anyone. ''' if num not in range(*self.EN_US_RANGE): raise LanguageTranslationError, \ "Cannot tranlsate: number out of range" if num in self.EN_US_SINGLETON: return self.EN_US_SINGLETON[num] remainder = num % 10 if num in range(*self.EN_US_TEENS): return '%s%s' % ( self.EN_US_TEEN_SPECIAL_PFX.get(remainder, self.EN_US_SINGLETON[remainder]), self.EN_US_TEEN_SFX) return '%s-%s' % (self.EN_US_SINGLETON[num / 10 * 10], self.EN_US_SINGLETON[remainder]) def joinStringList(strings): '''Take care of those pesky contractions. ''' if len(strings) == 1: return strings[0] return '%s and %s' % (','.join(strings[:-1]), strings[-1]) class Collection: '''A collection of items, complete with a few common actions (taking down, passing around, putting away) and extensive logging. ''' def __init__(self, itemClass, emptyClass, translator=NumToLanguageTranslator(), logfd=sys.stdout): self.itemClass = itemClass self.emptyClass = emptyClass self.items = [] self.location = None self.numTranslator = translator self.logfd = logfd def _get_description(self): return '%s %s' % (self.numTranslator.translate(len(self.items)), self.itemClass.name(plural=len(self.items) != 1)) description = property(_get_description) def _get_longDescription(self): return '%s %s' % (self.description, self.location) longDescription = property(_get_longDescription) def putAway(self, items, location): self.items.extend(items) self.location = location (EVENT_TAKE_ONE_DOWN, EVENT_PASS_IT_AROUND) = range(2) def takeOneDown(self, actor): '''Get an item and log its removal and distribution. ''' try: item_to_discard = self.items.pop(0) except IndexError: raise self.emptyClass self.logEvents( [self.EVENT_TAKE_ONE_DOWN, self.EVENT_PASS_IT_AROUND, ], actor) return item_to_discard LOG_MESSAGES = { EVENT_TAKE_ONE_DOWN: 'take one down', EVENT_PASS_IT_AROUND: 'pass it around', } def logEvents(self, events, actor): self.logfd.write('%s%s, ' % ( actor and (str(actor) + ' ') or '', joinStringList(map(lambda x: self.LOG_MESSAGES[x], events)) )) class Item: '''Any damn thing. ''' @staticmethod def name(plural=False): raise NotImplementedError, "Override me!" class Person: '''Someone, but specifically someone with a name. ''' def __init__(self, name): self.name = name def __str__(self): return self.name class TheStore: '''The source of many things. At the moment, only beer. TODO: pretzels. ''' @staticmethod def buyBeer(howMuch): return [BeerBottle() for x in range(howMuch)] ## Our application: Separate module?? class OutOfBeer(Exception): '''For resonable handling of a terrible situation. ''' def __str__(self): return "Go to the store and buy some more" class BeerBottle(Item): '''A potential item for collecting, passing around, etc. ''' @staticmethod def name(plural=False): return 'bottle%s of beer' % (plural and 's' or '') def drink(self): pass # Mmm. Beer. def letsDrink(who, howMuch, whereToKeep): '''A "sample" application, if you will, of this framework in use. Scales easily up to 99 bottles. ''' assert 1 <= howMuch <= 99 actor = Person(who) collection = Collection(BeerBottle, OutOfBeer) def refill(): collection.putAway(TheStore.buyBeer(howMuch), whereToKeep) refill() try: while True: print collection.longDescription.capitalize() + ', ' + collection.description + '.' bottle = collection.takeOneDown(actor) print collection.longDescription + '.' bottle.drink() print '' except OutOfBeer, e: sys.stdout.write(str(e)) # Lets be polite and leave the wall full! refill() print ',', collection.longDescription + '.' # --oh wait, GC. damn if __name__ == "__main__": # test letsDrink('You', 99, 'on the wall')
Download Source | Write Comment
Alternative Versions
Version | Author | Date | Comments | Rate |
---|---|---|---|---|
This example demonstrates the simplicity | Gerold Penz | 07/23/05 | 15 | |
Creative version | Schizo | 11/06/05 | 16 | |
minimal version | Oliver Xymoron | 04/20/05 | 5 | |
using lambda in LISP style | J Adrian Zimmer | 11/14/06 | 2 | |
Exception based | Michael Galpin | 02/08/08 | 0 | |
functional, w/o variables or procedures | Ivan Tkatchev | 07/14/05 | 2 | |
minimal version with singular | Emlyn Jones | 06/13/05 | 3 | |
Fully compliant version | Ricardo Garcia Gonzalez | 01/15/06 | 7 | |
Using a iterator class | Eric Moritz | 01/20/06 | 2 | |
New conditional expressions in 2.5 | Ezequiel Pochiero | 12/18/06 | 1 |
Download Source | Write Comment
Add Comment
Please provide a value for the fields Name,
Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.
Please don't post large portions of code here! Use the form to submit new examples or updates instead!
Comments
Auders said on 10/29/06 15:51:56
Now this was cool!
Keep up the good work!
Isaac said on 12/08/06 17:12:45
So wrong, but sooo right. This should be in text books under the heading "The problems of over-design in OOP".
Hilarious.
Criptych said on 05/14/08 20:57:51
Complete and total overkill... programming at its best. Have you considered making this into a text-adventure engine? You have all the basics.
DND said on 11/30/08 17:03:58
Wall used 'Bottle of beer'
Critical Hit!
anon said on 11/19/09 13:15:35
Absolute overgeekness...
lucyisssilo said on 06/01/10 05:18:03
Total Screen Recorder, a great tool for making video tutorials:http://www.totalscreenrecorder.com
roosieslo said on 06/28/10 05:00:55
GodswMobile Software dedicated to providing a better experience life for the people who use and rely upon Microsoft Windows Mobile devices for their personal and commercial needs. With thousands of users over 50 countries worldwide, GodswMobile has become the popular, trusted and convenient choice to backup and restore the valuable information which stored in mobile phones.
http://www.godswmobile.com/