Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # HablarConSara.activity
- # A simple hack to attach a chatterbot to speak activity
- # Copyright (C) 2008 Sebastian Silva Fundacion FuenteLibre sebastian@fuentelibre.org
- #
- # Style and structure taken from Speak.activity Copyright (C) Joshua Minor
- #
- # HablarConSara.activity is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # HablarConSara.activity is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with HablarConSara.activity. If not, see <http://www.gnu.org/licenses/>.
- import gtk
- import gobject
- from gettext import gettext as _
- import logging
- logger = logging.getLogger('speak')
- from toolkit.combobox import ComboBox
- import bot.aiml
- import voice
- import decimal
- #
- # relies on these two modules from the
- # Calculate activity
- #
- try:
- from astparser import AstParser
- import rational
- MATHS_MODE='full'
- except ImportError:
- MATHS_MODE='manual'
- BOTS = {
- _('Spanish'): { 'name': 'Sara',
- 'brain': 'bot/sara.brn',
- 'predicates': { 'nombre_bot': 'Sara',
- 'botmaster': 'la comunidad Azucar' } },
- _('English'): { 'name': 'Alice',
- 'brain': 'bot/alice.brn',
- 'predicates': { 'name': 'Alice',
- 'master': 'the Sugar Community' } } }
- # load Standard AIML set for restricted systems
- if int([i for i in file('/proc/meminfo').readlines()
- if i.startswith('MemTotal:')][0].split()[1]) < 524288:
- BOTS[_('English')]['brain'] = 'bot/alisochka.brn'
- _kernel = None
- _kernel_voice = None
- def get_default_voice():
- default_voice = voice.defaultVoice()
- if default_voice.friendlyname not in BOTS:
- return voice.allVoices()[_('English')]
- else:
- return default_voicem4ce751e0
- def get_voices():
- voices = ComboBox()
- for lang in sorted(BOTS.keys()):
- voices.append_item(voice.allVoices()[lang], lang)
- return voices.get_model()
- def respond(voice, text):
- if text.rstrip()[-1:] == '=':
- try:
- text = str(eval(text.rstrip()[:-1]))
- except:
- pass
- if _kernel is None:
- return text
- else:
- return _kernel.respond(text)
- def calculate(equation):
- """
- Calculates the result of an equation represented as a
- string literal. We round the result down to 4 places
- of significance, so that we don't overload the face
- when it says the result
- >>> MATHS_MODE='full'
- >>> calculate('10/3')
- '3.3333'
- >>> MATHS_MODE='manual'
- >>> calculate('10/3')
- '3.3333'
- """
- parse_msg = 'MATHS_MODE=%s : "%s" couldn\'t be parsed.' % (
- MATHS_MODE, equation)
- except_msg = 'MATHS_MODE=%s : "%s" raised an unhandled exception' % (
- MATHS_MODE, equation)
- msg = _("I don't know how to answer this problem, sorry.")
- if MATHS_MODE is 'full':
- decimal.Decimal = D
- decimal.getcontext().prec = 4
- decimal.getcontext().rounding = decimal.ROUND_DOWN
- parsr = AstParser()
- try:
- res = parsr.evaluate(parsr.parse(equation))
- except ParseError:
- logger.exception(parse_msg)
- return equation
- except:
- logger.exception(except_msg)
- return equation
- #AstParser.evaluate() returns rational numbers sometimes
- if isinstance(res, rational.Rational):
- res = D(str(r.n))/D(str(r.d))
- ## FIXME think of a tricker way to do this
- #fallback to using eval, quick n dirty
- else:
- try:
- from __future__ import division
- except ImportError:
- pass
- try:
- res = eval(equation)
- except SyntaxError:
- logger.exception(parse_msg)
- return equation
- except:
- logger.exception(except_msg)
- return equation
- #round result, unless it's already rounded because of Decimal's context
- if not isinstance(res, D):
- ## FIXME InvalidOperation: quantize result has too many digits for current context
- ## res = D(str(res)).quantize(D('0.001'), decimal.ROUND_HALF_UP)
- #rely on string type coerion to deal with precision issues
- res = round(res, 4)
- res = str(res)
- if res[-2:] == '.0': return res[:-2]
- else: return res
- def load(activity, voice, sorry=None):
- if voice == _kernel_voice:
- return False
- old_cursor = activity.get_cursor()
- activity.set_cursor(gtk.gdk.WATCH)
- def load_brain():
- global _kernel
- global _kernel_voice
- is_first_session = _kernel is None
- try:
- brain = BOTS[voice.friendlyname]
- logger.debug('Load bot: %s' % brain)
- kernel = bot.aiml.Kernel()
- kernel.loadBrain(brain['brain'])
- for name, value in brain['predicates'].items():
- kernel.setBotPredicate(name, value)
- if _kernel is not None:
- del _kernel
- _kernel = None
- import gc
- gc.collect()
- _kernel = kernel
- _kernel_voice = voice
- finally:
- activity.set_cursor(old_cursor)
- if is_first_session:
- hello = _("Hello, I'm a robot \"%s\". Ask me any question.") \
- % BOTS[voice.friendlyname]['name']
- if sorry:
- hello += ' ' + sorry
- activity.face.say_notification(hello)
- elif sorry:
- activity.face.say_notification(sorry)
- gobject.idle_add(load_brain)
- return True
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement