-
Notifications
You must be signed in to change notification settings - Fork 0
/
data.py
179 lines (166 loc) · 6.05 KB
/
data.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import sqlite3, re, sys
from datetime import date
'''We start by selecting a script from the db. Having done this, the opening phrase is loaded as pertaining to this
script, then printed to the user. The next task is to parse user input, according to rules stored in the database.i.e
1. Substitution
2. Decomposition
3. Transformation
4. Reassembly.
'''
class UNITY():
def __init__(self, script):
#Load the welcome message for the specified script.
self.script = script
self.conn = sqlite3.connect('testdb')
o = self.conn.execute('SELECT * FROM OPENING WHERE __SCRIPT="' + self.script + '"')
if len(o.fetchall()) > 0:
o = self.conn.execute('SELECT * FROM OPENING WHERE __SCRIPT="' + self.script + '"')
self.mem_counter = 0
for opening in o:
print("\n[SESSION OPENED: " + date.today().ctime() + "](TYPE 'exit' to close.)")
print('UNITY: ' + opening[0].upper())
while True:
self.parse_input()
else:
print('The specified script does not exist. Did you check your spelling?')
def parse_input(self):
#Collect the user input for analysis.
self.keystack = []
capture = input()
if capture.lower() == 'exit':
self.conn.close()
sys.exit()
else:
self.sub_specials(capture)
self.substitute()
self.transform()
def sub_specials(self, user_input):
specials = [',', '.']
user_input = re.sub(r'\?', '', user_input).lower()
for special in specials:
if special in user_input:
user_input = user_input.split(special)[-1]
self.user_inputs = user_input.strip().split(' ')
def substitute(self):
#Substitute selected words before rules are applied.
counter, res = 0, []
for i in self.user_inputs:
subs = self.conn.execute('SELECT __NAME, SUBSTITUTION FROM SUBSTITUTION WHERE __NAME=="' + i + \
'" AND __SCRIPT="' + self.script + '"')
for j in subs:
self.user_inputs[counter] = j[1]
counter += 1
#print(self.user_inputs) #Debug
def transform(self):
#Requires construction of regular expressions to look for decomposition rule matches.
self.initialize_keystack()
self.parse_decomposition_rules()
def initialize_keystack(self):
for i in self.user_inputs:
#Scan input text for keywords, and sort them in a stack by rank
keys = self.conn.execute('SELECT RANK, EQ FROM KEYWORD WHERE __NAME=="' + i + \
'" AND __SCRIPT=="' + self.script + '"')
if len(keys.fetchall()) != 0:
keys = self.conn.execute('SELECT RANK, EQ FROM KEYWORD WHERE __NAME=="' + i + \
'" AND __SCRIPT=="' + self.script + '"')
for j in keys:
rank, eq = j[0], j[1]
add = False
if len(self.keystack) == 0:
self.keystack.append([i, rank, eq])
else:
for y in self.keystack:
if not i in y:
self.keystack.append([i, rank, eq])
self.keystack.sort(key= lambda s: s[1], reverse=True)
#print(self.keystack) #Debug
def parse_decomposition_rules(self):
#Create a rule stack of decomposition rules from the equivalence class of the topmost keyword
self.d_rule_stack = []
try:
decom = self.conn.execute('SELECT __NAME, EQ FROM DECOMP_RULE WHERE EQ=="' + self.keystack[0][2] + \
'" AND __SCRIPT=="' + self.script + '"')
for i in decom:
self.d_rule_stack.append([i[0], i[1]])
#print('Stack: ' + str(self.d_rule_stack)) #Debug
#print(self.reconstruct_word(self.user_inputs)) #Debug
#Topmost decomposition rule determines how the word is reassembled
self.assemble_reply(self.extract_response())
except IndexError as e:
rank = 999999999999999999
message = self.conn.execute('SELECT * FROM EMPTY WHERE __SCRIPT=="' + self.script + '"')
for i in message:
if int(i[1]) <= rank:
rank = int(i[1])
selected_message = i[0]
self.conn.execute('UPDATE EMPTY SET RANK=' + str(rank+1) + ' WHERE __NAME=="' + selected_message + '"')
self.conn.commit()
print('UNITY: ' + selected_message.upper())
def extract_response(self):
#Transform decomposition rule into a regex, and extract input components necessary for reassembly
word = re.sub(self.keystack[0][0], self.keystack[0][2], self.reconstruct_word(self.user_inputs))
#print('word: ' + word) #Debug
for i in self.d_rule_stack:
res = self.clean_rule(i[0])
#print('res: ' + str(res)) #Debug
#print('res: ' + str(re.sub(r'\d', r'\s?(.*)\s?', str(res)))) #Debug
regex = re.compile(re.sub(r'\d', r'\s?(.*)\s?', str(res)))
#print(regex) #Debug
match = re.search(regex, word)
#print(match.groups()) #Debug
responses = []
if match:
for j in match.groups():
responses.append(j.strip())
#print(responses) #Debug
self.trans = i
#print(self.trans[0]) #Debug
return responses
def assemble_reply(self, responses):
#Use response values as well as stored reassembly rules to create a reply
if responses:
selected_rule, lowest_rank = '', 9999999999999999
rules = self.conn.execute('SELECT * FROM REASSEM_RULE WHERE D_RULE=="' + self.trans[0] + \
'" AND __SCRIPT=="' + self.script + '"')
for i in rules:
#Rules should be shuffled to prevent repetitiveness
if int(i[3]) <= lowest_rank:
lowest_rank = int(i[3])
selected_rule = i[0]
#print('R-RULE: ' + selected_rule)
lowest_rank += 1
self.conn.execute('UPDATE REASSEM_RULE SET RANK=' + str(lowest_rank) + ' WHERE __NAME=="' + \
selected_rule + '"')
self.conn.commit()
for i in selected_rule:
try:
ref = int(i) - 1
except ValueError as e:
pass
cleaned_rule = self.clean_rule(selected_rule)
#print('Clean: ' + cleaned_rule) #Debug
#print(responses[ref]) #Debug
try:
self.reply = re.sub(r'\d', str(responses[ref]), cleaned_rule)
except UnboundLocalError as e:
self.reply = re.sub(r'\d', str(responses), cleaned_rule)
print('UNITY: ' + self.reply.upper())
#Helper functions
def reconstruct_word(self, word):
w = ''
for i in word:
w += i
w += ' '
w.strip()
return w
def clean_rule(self, rule):
#print('Rule: ' + str(rule))
rule = re.sub('\(', '', rule)
rule = re.sub('\)', '', rule)
rule = re.sub(r'\s?0\s?', '0', rule)
return rule.strip()
if __name__ == '__main__':
if len(sys.argv) > 1:
UNITY(sys.argv[1])
else:
print('Please specify a script.')