300 lines
8.1 KiB
Python
300 lines
8.1 KiB
Python
|
#!/usr/bin/env python
|
||
|
# -*- coding: iso-8859-15 -*-
|
||
|
|
||
|
# /usr/local/bin/scatolo.py
|
||
|
#
|
||
|
########################################################################
|
||
|
# File : scatolo.py
|
||
|
# Project : scatolo talking Machine
|
||
|
# Version : 1.0.0
|
||
|
# Author : giodim & Unit team
|
||
|
# Comment :
|
||
|
# 06.07.2017 - Version 1.0.0 developement
|
||
|
########################################################################
|
||
|
# Copyright 2015 GioDim <giodim1317@gmail.com>
|
||
|
#
|
||
|
# This program 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 2 of the License, or
|
||
|
# (at your option) any later version.
|
||
|
#
|
||
|
# This program 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 this program; if not, write to the Free Software
|
||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
|
# MA 02110-1301, USA.
|
||
|
########################################################################
|
||
|
|
||
|
|
||
|
########################################################################
|
||
|
# Import
|
||
|
########################################################################
|
||
|
|
||
|
import os
|
||
|
import time
|
||
|
import subprocess
|
||
|
import random
|
||
|
|
||
|
from string import ascii_letters
|
||
|
from random import choice
|
||
|
|
||
|
########################################################################
|
||
|
# Constants
|
||
|
########################################################################
|
||
|
|
||
|
DADA_FILE = "scatolo_v0.1_iotunoi.pb"
|
||
|
MARKOV_FILE = "macao.txt"
|
||
|
EDITED_FILE = "humor.txt"
|
||
|
|
||
|
DADA_CMD = "dada"
|
||
|
GEN_CMD = "/usr/local/bin/pico.sh"
|
||
|
PLAY_CMD = ["aplay", "tmp.wav"]
|
||
|
|
||
|
MAX_RND = 100
|
||
|
|
||
|
DADA_WEIGHT = 30
|
||
|
MARKOV_WEIGHT = 90
|
||
|
|
||
|
MARKOV_MAX_WORD = 20
|
||
|
|
||
|
########################################################################
|
||
|
# Global Variables
|
||
|
########################################################################
|
||
|
|
||
|
Debug = True
|
||
|
Word_List = []
|
||
|
Associations = []
|
||
|
Humor_Text = []
|
||
|
|
||
|
########################################################################
|
||
|
# Class : _Getch
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
class _Getch:
|
||
|
"""Gets a single character from standard input. Does not echo to the screen."""
|
||
|
def __init__(self):
|
||
|
try:
|
||
|
self.impl = _GetchWindows()
|
||
|
except ImportError:
|
||
|
self.impl = _GetchUnix()
|
||
|
|
||
|
def __call__(self): return self.impl()
|
||
|
|
||
|
########################################################################
|
||
|
# Class : _GetchUnix
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
class _GetchUnix:
|
||
|
def __init__(self):
|
||
|
import tty, sys
|
||
|
|
||
|
def __call__(self):
|
||
|
import sys, tty, termios
|
||
|
fd = sys.stdin.fileno()
|
||
|
old_settings = termios.tcgetattr(fd)
|
||
|
try:
|
||
|
tty.setraw(sys.stdin.fileno())
|
||
|
ch = sys.stdin.read(1)
|
||
|
finally:
|
||
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
||
|
return ch
|
||
|
|
||
|
########################################################################
|
||
|
# Class : _GetchWindows
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
class _GetchWindows:
|
||
|
def __init__(self):
|
||
|
import msvcrt
|
||
|
|
||
|
def __call__(self):
|
||
|
import msvcrt
|
||
|
return msvcrt.getch()
|
||
|
|
||
|
########################################################################
|
||
|
# Function : Markov_Get_Word_List
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def Markov_Get_Word_List (text) :
|
||
|
# Define a set of allowed letters
|
||
|
allowed_letters = ascii_letters + "áàéèíìóòúù" + "ÁÀÉÈÍÌÓÒÚÙ" + "'."
|
||
|
# Keep only the allowed replacing the others with a space
|
||
|
text = "".join (c.lower ()
|
||
|
if c in allowed_letters else " "
|
||
|
for c in text)
|
||
|
# Split by words, using space as separator
|
||
|
return text.split ()
|
||
|
|
||
|
########################################################################
|
||
|
# Function : Markov_Get_Associations
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def Markov_Get_Associations (word_list):
|
||
|
# Build a dictionary where each word is a key, and the values are the list
|
||
|
# of the words that follow the key one
|
||
|
# ['a', 'b', 'a', 'c'] became {'a': ['b', 'c'], 'b': ['a']}
|
||
|
associations = {}
|
||
|
for i, word in enumerate(word_list[:-1]):
|
||
|
if word not in associations:
|
||
|
associations[word] = []
|
||
|
associations[word].append(word_list[i+1])
|
||
|
return associations
|
||
|
|
||
|
########################################################################
|
||
|
# Function : Markov_Build_Chains
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def Markov_Build_Chains (text) :
|
||
|
global Word_List
|
||
|
global Associations
|
||
|
|
||
|
Word_List = Markov_Get_Word_List (text)
|
||
|
Associations = Markov_Get_Associations (Word_List)
|
||
|
|
||
|
########################################################################
|
||
|
# Function : Markov_Generator
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def Markov_Generator (max_words=MARKOV_MAX_WORD):
|
||
|
out_list = []
|
||
|
current_word = choice (Word_List)
|
||
|
|
||
|
for i in range (max_words):
|
||
|
out_list.append(current_word)
|
||
|
choice_list = Associations.get (current_word, Word_List)
|
||
|
|
||
|
if current_word.endswith ("."):
|
||
|
break
|
||
|
|
||
|
current_word = choice (choice_list)
|
||
|
|
||
|
out_string = " ".join (out_list)
|
||
|
out_string = out_string.replace (" .", ".")
|
||
|
out_string = out_string [0].upper () + out_string [1:]
|
||
|
|
||
|
return out_string
|
||
|
|
||
|
########################################################################
|
||
|
# Function : Dada_Generator
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def Dada_Generator (nomef) :
|
||
|
|
||
|
if (not os.path.exists (nomef)) :
|
||
|
return " "
|
||
|
|
||
|
testo_dada = subprocess.check_output ([DADA_CMD, nomef])
|
||
|
testo_dada.replace ('\n', '').replace ('\r', '')
|
||
|
|
||
|
return testo_dada
|
||
|
|
||
|
########################################################################
|
||
|
# Function : File_Load
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def File_Load (nomef) :
|
||
|
global Humor_Text
|
||
|
|
||
|
if (not os.path.exists (nomef)) :
|
||
|
return
|
||
|
|
||
|
for buf in open (nomef) :
|
||
|
Humor_Text.append (buf.rstrip ('\n'))
|
||
|
|
||
|
########################################################################
|
||
|
# Function : File_Rand_Generator
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def File_Rand_Generator () :
|
||
|
return choice (Humor_Text)
|
||
|
|
||
|
########################################################################
|
||
|
# Function : Play
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
def Play (text_to_play) :
|
||
|
if (text_to_play == "") or (text_to_play == " ") :
|
||
|
return
|
||
|
|
||
|
if (Debug == True) :
|
||
|
print (text_to_play)
|
||
|
|
||
|
subprocess.call ([GEN_CMD, text_to_play])
|
||
|
subprocess.check_output (PLAY_CMD)
|
||
|
|
||
|
########################################################################
|
||
|
# Function :
|
||
|
# Input :
|
||
|
# Output :
|
||
|
# Comment :
|
||
|
########################################################################
|
||
|
|
||
|
random.seed ()
|
||
|
mygetch = _Getch()
|
||
|
|
||
|
with open (MARKOV_FILE) as f:
|
||
|
Markov_Build_Chains (f.read())
|
||
|
|
||
|
File_Load (EDITED_FILE)
|
||
|
|
||
|
while (True) :
|
||
|
|
||
|
print "prompt ",
|
||
|
|
||
|
ch = mygetch ()
|
||
|
|
||
|
if (ch != " ") :
|
||
|
time.sleep (1)
|
||
|
continue
|
||
|
|
||
|
idx = int (random.random () * MAX_RND)
|
||
|
|
||
|
if (Debug == True) :
|
||
|
print ("Idx=", idx)
|
||
|
|
||
|
if (idx < DADA_WEIGHT) :
|
||
|
if (Debug == True) :
|
||
|
print ("DADA ")
|
||
|
testo = Dada_Generator (DADA_FILE)
|
||
|
elif (idx >= DADA_WEIGHT) and (idx < MARKOV_WEIGHT) :
|
||
|
if (Debug == True) :
|
||
|
print ("MARKOV ")
|
||
|
testo = Markov_Generator ()
|
||
|
else :
|
||
|
if (Debug == True) :
|
||
|
print ("FILE ")
|
||
|
testo = File_Rand_Generator ()
|
||
|
|
||
|
Play (testo)
|