Advertisement
Guest User

calculate

a guest
Jun 1st, 2010
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.11 KB | None | 0 0
  1. # HablarConSara.activity
  2. # A simple hack to attach a chatterbot to speak activity
  3. # Copyright (C) 2008 Sebastian Silva Fundacion FuenteLibre sebastian@fuentelibre.org
  4. #
  5. # Style and structure taken from Speak.activity Copyright (C) Joshua Minor
  6. #
  7. #     HablarConSara.activity is free software: you can redistribute it and/or modify
  8. #     it under the terms of the GNU General Public License as published by
  9. #     the Free Software Foundation, either version 3 of the License, or
  10. #     (at your option) any later version.
  11. #
  12. #     HablarConSara.activity is distributed in the hope that it will be useful,
  13. #     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. #     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. #     GNU General Public License for more details.
  16. #
  17. #     You should have received a copy of the GNU General Public License
  18. #     along with HablarConSara.activity.  If not, see <http://www.gnu.org/licenses/>.
  19.  
  20. import gtk
  21. import gobject
  22. from gettext import gettext as _
  23.  
  24. import logging
  25. logger = logging.getLogger('speak')
  26.  
  27. from toolkit.combobox import ComboBox
  28.  
  29. import bot.aiml
  30. import voice
  31.  
  32. import decimal
  33.  
  34. #
  35. # relies on these two modules from the
  36. # Calculate activity
  37. #
  38. try:
  39.     from astparser import AstParser
  40.     import rational
  41.     MATHS_MODE='full'
  42. except ImportError:
  43.     MATHS_MODE='manual'
  44.  
  45. BOTS = {
  46.     _('Spanish'): { 'name': 'Sara',
  47.                     'brain': 'bot/sara.brn',
  48.                     'predicates': { 'nombre_bot': 'Sara',
  49.                                     'botmaster': 'la comunidad Azucar' } },
  50.     _('English'): { 'name': 'Alice',
  51.                     'brain': 'bot/alice.brn',
  52.                     'predicates': { 'name': 'Alice',
  53.                                     'master': 'the Sugar Community' } } }
  54.  
  55. # load Standard AIML set for restricted systems
  56. if int([i for i in file('/proc/meminfo').readlines()
  57.         if i.startswith('MemTotal:')][0].split()[1]) < 524288:
  58.     BOTS[_('English')]['brain'] = 'bot/alisochka.brn'
  59.  
  60. _kernel = None
  61. _kernel_voice = None
  62.  
  63.  
  64. def get_default_voice():
  65.     default_voice = voice.defaultVoice()
  66.     if default_voice.friendlyname not in BOTS:
  67.         return voice.allVoices()[_('English')]
  68.     else:
  69.         return default_voicem4ce751e0
  70.  
  71.  
  72. def get_voices():
  73.     voices = ComboBox()
  74.     for lang in sorted(BOTS.keys()):
  75.         voices.append_item(voice.allVoices()[lang], lang)
  76.     return voices.get_model()
  77.  
  78.  
  79. def respond(voice, text):
  80.     if text.rstrip()[-1:] == '=':
  81.         try:
  82.             text = str(eval(text.rstrip()[:-1]))
  83.         except:
  84.             pass
  85.  
  86.     if _kernel is None:
  87.         return text
  88.     else:
  89.         return _kernel.respond(text)
  90.  
  91. def calculate(equation):
  92.     """
  93.    Calculates the result of an equation represented as a
  94.    string literal. We round the result down to 4 places
  95.    of significance, so that we don't overload the face
  96.    when it says the result
  97.  
  98.    >>> MATHS_MODE='full'
  99.    >>> calculate('10/3')
  100.    '3.3333'
  101.    >>> MATHS_MODE='manual'
  102.    >>> calculate('10/3')
  103.    '3.3333'
  104.    """
  105.     parse_msg = 'MATHS_MODE=%s : "%s" couldn\'t be parsed.' % (
  106.                MATHS_MODE, equation)
  107.     except_msg = 'MATHS_MODE=%s : "%s" raised an unhandled exception' % (
  108.                MATHS_MODE, equation)
  109.     msg = _("I don't know how to answer this problem, sorry.")
  110.    
  111.     if MATHS_MODE is 'full':
  112.         decimal.Decimal = D
  113.         decimal.getcontext().prec = 4
  114.         decimal.getcontext().rounding = decimal.ROUND_DOWN
  115.         parsr = AstParser()
  116.         try:
  117.             res = parsr.evaluate(parsr.parse(equation))
  118.         except ParseError:
  119.             logger.exception(parse_msg)
  120.             return equation
  121.         except:
  122.             logger.exception(except_msg)
  123.             return equation
  124.            
  125.         #AstParser.evaluate() returns rational numbers sometimes
  126.         if isinstance(res, rational.Rational):
  127.             res = D(str(r.n))/D(str(r.d))
  128.  
  129.     ## FIXME think of a tricker way to do this
  130.     #fallback to using eval, quick n dirty
  131.     else:
  132.         try:
  133.             from __future__ import division
  134.         except ImportError:
  135.             pass
  136.         try:
  137.             res = eval(equation)
  138.         except SyntaxError:
  139.             logger.exception(parse_msg)
  140.             return equation
  141.         except:
  142.             logger.exception(except_msg)
  143.             return equation
  144.  
  145.     #round result, unless it's already rounded because of Decimal's context
  146.     if not isinstance(res, D):
  147.         ## FIXME InvalidOperation: quantize result has too many digits for current context
  148.         ## res = D(str(res)).quantize(D('0.001'), decimal.ROUND_HALF_UP)
  149.        
  150.         #rely on string type coerion to deal with precision issues
  151.         res = round(res, 4)
  152.  
  153.     res = str(res)
  154.     if res[-2:] == '.0': return res[:-2]
  155.     else: return res
  156.  
  157.  
  158. def load(activity, voice, sorry=None):
  159.     if voice == _kernel_voice:
  160.         return False
  161.  
  162.     old_cursor = activity.get_cursor()
  163.     activity.set_cursor(gtk.gdk.WATCH)
  164.  
  165.     def load_brain():
  166.         global _kernel
  167.         global _kernel_voice
  168.  
  169.         is_first_session = _kernel is None
  170.  
  171.         try:
  172.             brain = BOTS[voice.friendlyname]
  173.             logger.debug('Load bot: %s' % brain)
  174.  
  175.             kernel = bot.aiml.Kernel()
  176.             kernel.loadBrain(brain['brain'])
  177.             for name, value in brain['predicates'].items():
  178.                 kernel.setBotPredicate(name, value)
  179.  
  180.             if _kernel is not None:
  181.                 del _kernel
  182.                 _kernel = None
  183.                 import gc
  184.                 gc.collect()
  185.  
  186.             _kernel = kernel
  187.             _kernel_voice = voice
  188.         finally:
  189.             activity.set_cursor(old_cursor)
  190.  
  191.         if is_first_session:
  192.             hello = _("Hello, I'm a robot \"%s\". Ask me any question.") \
  193.                     % BOTS[voice.friendlyname]['name']
  194.             if sorry:
  195.                 hello += ' ' + sorry
  196.             activity.face.say_notification(hello)
  197.         elif sorry:
  198.             activity.face.say_notification(sorry)
  199.  
  200.     gobject.idle_add(load_brain)
  201.     return True
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement