Initial commit
|
@ -0,0 +1,2 @@
|
|||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
|
@ -0,0 +1,11 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches/build_file_checksums.ser
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WizardSettings">
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="imageWizard">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="imageAssetPanel">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="launcher">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="foregroundImage">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="scalingPercent" value="173" />
|
||||
<entry key="trimmed" value="true" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="foregroundImage" value="C:\Users\tommy\AndroidStudioProjects\AndroidBotInterface\app\src\main\res\drawable\applgogo.png" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,29 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<Objective-C-extensions>
|
||||
<file>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||
</file>
|
||||
<class>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||
</class>
|
||||
<extensions>
|
||||
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
</code_scheme>
|
||||
</component>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="7">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="6">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,53 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url 'http://nexus.bippo.co.id/nexus/content/repositories/soluvas-public-snapshots/'
|
||||
}
|
||||
maven {
|
||||
url 'http://nexus.bippo.co.id/nexus/content/repositories/soluvas-public-thirdparty/'
|
||||
}
|
||||
maven {
|
||||
url 'http://jcenter.bintray.com'
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "com.fpghoti.androidbotinterface"
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
packagingOptions {
|
||||
exclude 'META-INF/DEPENDENCIES'
|
||||
exclude 'META-INF/LICENSE'
|
||||
exclude 'META-INF/LICENSE.txt'
|
||||
exclude 'META-INF/license.txt'
|
||||
exclude 'META-INF/NOTICE'
|
||||
exclude 'META-INF/NOTICE.txt'
|
||||
exclude 'META-INF/notice.txt'
|
||||
exclude 'META-INF/ASL2.0'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation ('com.android.support:appcompat-v7:28.0.0')
|
||||
implementation ('com.android.support.constraint:constraint-layout:1.1.3')
|
||||
implementation group: 'joda-time', name: 'joda-time', version: '2.3'
|
||||
implementation ('com.jcabi:jcabi-aspects:0.22.6')
|
||||
testImplementation ('junit:junit:4.12')
|
||||
androidTestImplementation ('com.android.support.test:runner:1.0.2')
|
||||
androidTestImplementation ('com.android.support.test.espresso:espresso-core:3.0.2')
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,26 @@
|
|||
package com.fpghoti.androidbotinterface;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.fpghoti.androidbotinterface", appContext.getPackageName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.fpghoti.androidbotinterface">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".SplashActivity"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
After Width: | Height: | Size: 19 KiB |
|
@ -0,0 +1,157 @@
|
|||
package com.fpghoti.androidbotinterface;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.fpghoti.androidbotinterface.bot.ChatBot;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private EditText editText;
|
||||
private TextView textOut;
|
||||
public static ChatBot bot;
|
||||
private boolean isLoaded;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
isLoaded = false;
|
||||
editText = (EditText) findViewById(R.id.editText);
|
||||
loadBot();
|
||||
}
|
||||
|
||||
private void loadBot(){
|
||||
outputPrint("Now loading the chat bot files...");
|
||||
File fileExt = new File(getExternalFilesDir(null).getAbsolutePath() + "/bots");
|
||||
if (!fileExt.exists()) {
|
||||
try {
|
||||
unpackBot();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
bot = new ChatBot(getExternalFilesDir(null).getAbsolutePath());
|
||||
isLoaded = true;
|
||||
outputPrint("Chat bot files are done loading!");
|
||||
}
|
||||
|
||||
private void unpackBot() {
|
||||
try {
|
||||
ZipInputStream zs = new ZipInputStream(getAssets().open("bots.zip"));
|
||||
ZipEntry entry = null;
|
||||
|
||||
String destination = getExternalFilesDir(null).getAbsolutePath() + "/";
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytes;
|
||||
while ((entry = zs.getNextEntry()) != null) {
|
||||
if (entry.isDirectory()) {
|
||||
File dir = new File(destination, entry.getName());
|
||||
if (!dir.exists()) {
|
||||
dir.mkdir();
|
||||
}
|
||||
} else {
|
||||
FileOutputStream file = new FileOutputStream(destination + entry.getName());
|
||||
while ((bytes = zs.read(buffer)) != -1) {
|
||||
file.write(buffer, 0, bytes);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
zs.close();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(View view) {
|
||||
String message = editText.getText().toString();
|
||||
textOut = (TextView) findViewById(R.id.output);
|
||||
if (message.length() > 0) {
|
||||
while(lineCount(textOut.getText().toString()) > 20){
|
||||
textOut.setText(removeFirstLine(textOut.getText().toString()));
|
||||
}
|
||||
textOut.setText(textOut.getText() + "\n" + "You: " + message);
|
||||
hideKeyboard();
|
||||
editText.getText().clear();
|
||||
|
||||
if(isLoaded) {
|
||||
final String finalmsg = bot.chatBot(message);
|
||||
new java.util.Timer().schedule(
|
||||
new java.util.TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (lineCount(textOut.getText().toString()) > 20) {
|
||||
textOut.setText(removeFirstLine(textOut.getText().toString()));
|
||||
}
|
||||
textOut.setText(textOut.getText() + "\n" + "Bot: " + finalmsg);
|
||||
}
|
||||
},
|
||||
2000
|
||||
);
|
||||
}else{
|
||||
new java.util.Timer().schedule(
|
||||
new java.util.TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (lineCount(textOut.getText().toString()) > 20) {
|
||||
textOut.setText(removeFirstLine(textOut.getText().toString()));
|
||||
}
|
||||
outputPrint("The chat bot is still loading.");
|
||||
}
|
||||
},
|
||||
2000
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void outputPrint(String input){
|
||||
textOut = (TextView) findViewById(R.id.output);
|
||||
if (input.length() > 0) {
|
||||
while(lineCount(textOut.getText().toString()) > 20){
|
||||
textOut.setText(removeFirstLine(textOut.getText().toString()));
|
||||
}
|
||||
textOut.setText(textOut.getText() + "\n" + input);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideKeyboard() {
|
||||
View v = getCurrentFocus();
|
||||
if (v == null) {
|
||||
v = new View(this);
|
||||
}
|
||||
InputMethodManager manager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
|
||||
manager.hideSoftInputFromWindow(v.getWindowToken(), 0);
|
||||
}
|
||||
|
||||
public int lineCount(String s){
|
||||
return s.split("\r\n|\r|\n").length;
|
||||
}
|
||||
|
||||
public String removeFirstLine(String s){
|
||||
if(lineCount(s) < 2){
|
||||
return "";
|
||||
}
|
||||
String result = "";
|
||||
String[] lines = s.split("\r\n|\r|\n");
|
||||
for(int i = 1; i < lineCount(s) - 1; i++){
|
||||
result += lines[i] + "\n";
|
||||
}
|
||||
result += lines[lineCount(s) - 1];
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.fpghoti.androidbotinterface;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
public class SplashActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.fpghoti.androidbotinterface.bot;
|
||||
|
||||
public class BotThink {
|
||||
//easteregg won't see this if everything's working
|
||||
public static String think(String input){
|
||||
input = input.toLowerCase();
|
||||
if(input.contains("android studio")){
|
||||
if(input.contains("like")){
|
||||
if(input.contains("dont") || input.contains("don't") || input.contains("not")){
|
||||
return "It is wise to keep your distance from Android Studio.";
|
||||
} else if(input.contains("i ")){
|
||||
return "Try staying up until 4:00 AM trying to get the bot software to load in Android Studio. Good luck liking it after that.";
|
||||
}
|
||||
return "No more Android Studio, please!";
|
||||
}
|
||||
}else if(input.contains("hello") || input.equals("hi") || input.equals("hi.") || input.equals("hi!") || input.contains("greetings") || input.contains("blessings and tidings")){
|
||||
return "Hello!";
|
||||
}else if(input.contains("are you working right now")){
|
||||
return("No, I am in fact NOT working right now. Android Studio INSISTS on not reading files from the SD card, so you are seeing this error message. Thanks for asking, though.");
|
||||
}else if(input.contains("the room")){
|
||||
return "Produced by, directed by, written by, and starring Tommy Wiseau, The Room was once an odd, obscure cult classic, but has gotten too much attention for my tastes lately.";
|
||||
}else if(input.contains("a talking cat")){
|
||||
return "That is that one movie with the cat that can only talk to people once. It was a direct to DVD low-budget film. I honestly thin Foodfight was higher quality than A Talking Cat.";
|
||||
}else if(input.contains("backstroke of the west")){
|
||||
return "Backstroke of the West is arguably the best Star Wars film and a fan-favorite Star War Gatering. It ends with Darth Vader shouting, \"DO NOT WANT!\" instead of his usual line.";
|
||||
}else if(input.contains("space thunder kids")){
|
||||
return "What can I say? This is a mix of eight different Korean cartoons with one guy doing ninety percent of the voice acting. A massive trainwreck.";
|
||||
}
|
||||
return "lol";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.fpghoti.androidbotinterface.bot;
|
||||
|
||||
import org.alicebot.ab.Bot;
|
||||
import org.alicebot.ab.Chat;
|
||||
|
||||
import com.jcabi.aspects.Async;
|
||||
|
||||
public class ChatBot {
|
||||
|
||||
private Bot bot;
|
||||
private Chat chatSession = null;
|
||||
|
||||
public ChatBot(String path) {
|
||||
bot = new Bot("default",path,"chat");
|
||||
chatSession = new Chat(bot);
|
||||
}
|
||||
|
||||
@Async
|
||||
public String chatBot(String input) {
|
||||
String msg = "none";
|
||||
try {
|
||||
msg = chatSession.multisentenceRespond(input);
|
||||
//zelda cdi reference
|
||||
if(input.toLowerCase().contains("youve killed me") || input.toLowerCase().contains("you've killed me")){
|
||||
msg = "Good.";
|
||||
}
|
||||
int count = 0;
|
||||
|
||||
//bot does not always respond
|
||||
while(msg.equalsIgnoreCase("") || msg.equalsIgnoreCase("I have no answer for that.")){
|
||||
String lastWord = input.substring(input.lastIndexOf(" ")+1);
|
||||
if(count > 0){
|
||||
lastWord = "lol ";
|
||||
}
|
||||
msg = chatSession.multisentenceRespond(lastWord);
|
||||
if(count > 0){
|
||||
msg = BotThink.think(input);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
//bot sometimes tries to pull up weird link. I Decided to just disable this outright by replacing the message
|
||||
if(msg.contains("<oob>") || msg.contains("<a") || msg.toLowerCase().contains("unknown?")){
|
||||
msg = "If you say so.";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
final String sendthis = msg;
|
||||
return sendthis;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.alicebot.ab.utils.IOUtils;
|
||||
|
||||
|
||||
public class AB {
|
||||
|
||||
/**
|
||||
* Experimental class that analyzes log data and suggests
|
||||
* new AIML patterns.
|
||||
*
|
||||
*/
|
||||
public static boolean shuffle_mode = true;
|
||||
public static boolean sort_mode = false;
|
||||
public static boolean filter_atomic_mode = false;
|
||||
public static boolean filter_wild_mode = false;
|
||||
public static String logfile = MagicStrings.root_path+"/data/"+MagicStrings.ab_sample_file; //normal.txt";
|
||||
public static AIMLSet passed = new AIMLSet("passed");
|
||||
public static AIMLSet testSet = new AIMLSet("1000");
|
||||
public static int runCompletedCnt;
|
||||
/**
|
||||
* Calculates the botmaster's productivity rate in
|
||||
* categories/sec when using Pattern Suggestor to create content.
|
||||
*
|
||||
* @param runCompletedCnt number of categories completed in this run
|
||||
* @param timer tells elapsed time in ms
|
||||
* @see AB
|
||||
*/
|
||||
public static void productivity (int runCompletedCnt, Timer timer) {
|
||||
//float time = timer.elapsedTimeMins();
|
||||
|
||||
}
|
||||
|
||||
/** saves a new AIML category and increments runCompletedCnt
|
||||
*
|
||||
* @param bot the bot the category belongs to
|
||||
* @param pattern the category's pattern (that and topic = *)
|
||||
* @param template the category's template
|
||||
* @param filename the filename for the category.
|
||||
*/
|
||||
public static void saveCategory(Bot bot, String pattern, String template, String filename) {
|
||||
String that = "*";
|
||||
String topic = "*";
|
||||
Category c = new Category(0, pattern, that, topic, template, filename);
|
||||
if (c.validate()) {
|
||||
bot.brain.addCategory(c);
|
||||
// bot.categories.add(c);
|
||||
bot.writeAIMLIFFiles();
|
||||
runCompletedCnt++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** mark a category as deleted
|
||||
*
|
||||
* @param bot the bot the category belogs to
|
||||
* @param c the category
|
||||
*/
|
||||
public static void deleteCategory(Bot bot, Category c) {
|
||||
c.setFilename(MagicStrings.deleted_aiml_file);
|
||||
c.setTemplate(MagicStrings.deleted_template);
|
||||
bot.deletedGraph.addCategory(c);
|
||||
bot.writeDeletedIFCategories();
|
||||
}
|
||||
|
||||
/** skip a category. Make the category as "unfinished"
|
||||
*
|
||||
* @param bot the bot the category belogs to
|
||||
* @param c the category
|
||||
*/
|
||||
public static void skipCategory(Bot bot, Category c) {
|
||||
c.setFilename(MagicStrings.unfinished_aiml_file);
|
||||
c.setTemplate(MagicStrings.unfinished_template);
|
||||
bot.unfinishedGraph.addCategory(c);
|
||||
|
||||
bot.writeUnfinishedIFCategories();
|
||||
}
|
||||
public static void abwq(Bot bot) {
|
||||
Timer timer = new Timer();
|
||||
timer.start();
|
||||
bot.classifyInputs(logfile);
|
||||
|
||||
bot.writeQuit();
|
||||
}
|
||||
/** magically suggests new patterns for a bot.
|
||||
* Reads an input file of sample data called logFile.
|
||||
* Builds a graph of all the inputs.
|
||||
* Finds new patterns in the graph that are not already in the bot.
|
||||
* Classifies input log into those new patterns.
|
||||
*
|
||||
*
|
||||
* @param bot the bot to perform the magic on
|
||||
*/
|
||||
public static void ab (Bot bot) {
|
||||
String logFile = logfile;
|
||||
MagicBooleans.trace_mode = false;
|
||||
MagicBooleans.enable_external_sets = false;
|
||||
Timer timer = new Timer();
|
||||
bot.brain.nodeStats();
|
||||
timer.start();
|
||||
|
||||
bot.graphInputs(logFile);
|
||||
|
||||
//bot.inputGraph.printgraph();
|
||||
timer.start();
|
||||
|
||||
bot.findPatterns();
|
||||
|
||||
|
||||
timer.start();
|
||||
bot.patternGraph.nodeStats();
|
||||
|
||||
bot.classifyInputs(logFile);
|
||||
|
||||
}
|
||||
|
||||
/** train the bot through a terminal interaction
|
||||
*
|
||||
* @param bot the bot to train
|
||||
*/
|
||||
public static void terminalInteraction (Bot bot) {
|
||||
Timer timer = new Timer();
|
||||
sort_mode = !shuffle_mode;
|
||||
// if (sort_mode)
|
||||
Collections.sort(bot.suggestedCategories, Category.ACTIVATION_COMPARATOR);
|
||||
ArrayList<Category> topSuggestCategories = new ArrayList<Category>();
|
||||
for (int i = 0; i < 10000 && i < bot.suggestedCategories.size(); i++) {
|
||||
topSuggestCategories.add(bot.suggestedCategories.get(i));
|
||||
}
|
||||
bot.suggestedCategories = topSuggestCategories;
|
||||
if (shuffle_mode) Collections.shuffle(bot.suggestedCategories);
|
||||
timer = new Timer();
|
||||
timer.start();
|
||||
runCompletedCnt = 0;
|
||||
ArrayList<Category> filteredAtomicCategories = new ArrayList<Category>();
|
||||
ArrayList<Category> filteredWildCategories = new ArrayList<Category>();
|
||||
for (Category c : bot.suggestedCategories) if (!c.getPattern().contains("*")) filteredAtomicCategories.add(c);
|
||||
else filteredWildCategories.add(c);
|
||||
ArrayList <Category> browserCategories;
|
||||
if (filter_atomic_mode) browserCategories = filteredAtomicCategories;
|
||||
else if (filter_wild_mode) browserCategories = filteredWildCategories;
|
||||
else browserCategories = bot.suggestedCategories;
|
||||
// log.info(filteredAtomicCategories.size()+" filtered suggested categories");
|
||||
for (Category c : browserCategories) {
|
||||
try {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
ArrayList samples = new ArrayList(c.getMatches());
|
||||
Collections.shuffle(samples);
|
||||
int sampleSize = Math.min(MagicNumbers.displayed_input_sample_size, c.getMatches().size());
|
||||
for (int i = 0; i < sampleSize; i++) {
|
||||
|
||||
}
|
||||
|
||||
productivity(runCompletedCnt, timer);
|
||||
String textLine = "" + IOUtils.readInputTextLine();
|
||||
terminalInteractionStep(bot, "", textLine, c);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** process one step of the terminal interaction
|
||||
*
|
||||
* @param bot the bot being trained.
|
||||
* @param request used when this routine is called by benchmark testSuite
|
||||
* @param textLine response typed by the botmaster
|
||||
* @param c AIML category selected
|
||||
*/
|
||||
public static void terminalInteractionStep (Bot bot, String request, String textLine, Category c) {
|
||||
String template = null;
|
||||
if (textLine.contains("<pattern>") && textLine.contains("</pattern>")) {
|
||||
int index = textLine.indexOf("<pattern>")+"<pattern>".length();
|
||||
int jndex = textLine.indexOf("</pattern>");
|
||||
int kndex = jndex + "</pattern>".length();
|
||||
if (index < jndex) {
|
||||
String pattern = textLine.substring(index, jndex);
|
||||
c.setPattern(pattern);
|
||||
textLine = textLine.substring(kndex, textLine.length());
|
||||
|
||||
}
|
||||
}
|
||||
String botThinks = "";
|
||||
String[] pronouns = {"he", "she", "it", "we", "they"};
|
||||
for (String p : pronouns) {
|
||||
if (textLine.contains("<"+p+">")) {
|
||||
textLine = textLine.replace("<"+p+">","");
|
||||
botThinks = "<think><set name=\""+p+"\"><set name=\"topic\"><star/></set></set></think>";
|
||||
}
|
||||
}
|
||||
if (textLine.equals("q")) System.exit(0); // Quit program
|
||||
else if (textLine.equals("wq")) { // Write AIML Files and quit program
|
||||
bot.writeQuit();
|
||||
/* Nodemapper udcNode = bot.brain.findNode("*", "*", "*");
|
||||
if (udcNode != null) {
|
||||
AIMLSet udcMatches = new AIMLSet("udcmatches");
|
||||
udcMatches.addAll(udcNode.category.getMatches());
|
||||
udcMatches.writeAIMLSet();
|
||||
}*/
|
||||
/* Nodemapper cNode = bot.brain.match("JOE MAKES BEER", "unknown", "unknown");
|
||||
if (cNode != null) {
|
||||
AIMLSet cMatches = new AIMLSet("cmatches");
|
||||
cMatches.addAll(cNode.category.getMatches());
|
||||
cMatches.writeAIMLSet();
|
||||
}
|
||||
if (passed.size() > 0) {
|
||||
AIMLSet difference = new AIMLSet("difference");
|
||||
AIMLSet intersection = new AIMLSet("intersection");
|
||||
for (String s : passed) if (testSet.contains(s)) intersection.add(s);
|
||||
passed = intersection;
|
||||
passed.setName = "passed";
|
||||
difference.addAll(testSet);
|
||||
difference.removeAll(passed);
|
||||
difference.writeAIMLSet();
|
||||
|
||||
passed.writeAIMLSet();
|
||||
testSet.writeAIMLSet();
|
||||
log.info("Wrote passed test cases");
|
||||
}*/
|
||||
System.exit(0);
|
||||
}
|
||||
else if (textLine.equals("skip") || textLine.equals("")) { // skip this one for now
|
||||
skipCategory(bot, c);
|
||||
}
|
||||
else if (textLine.equals("s") || textLine.equals("pass")) { // skip this one for now
|
||||
passed.add(request);
|
||||
AIMLSet difference = new AIMLSet("difference");
|
||||
difference.addAll(testSet);
|
||||
difference.removeAll(passed);
|
||||
difference.writeAIMLSet();
|
||||
passed.writeAIMLSet();
|
||||
}
|
||||
else if (textLine.equals("d")) { // delete this suggested category
|
||||
deleteCategory(bot, c);
|
||||
}
|
||||
else if (textLine.equals("x")) { // ask another bot
|
||||
template = "<sraix>"+c.getPattern().replace("*","<star/>")+"</sraix>";
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.sraix_aiml_file);
|
||||
}
|
||||
else if (textLine.equals("p")) { // filter inappropriate content
|
||||
template = "<srai>"+MagicStrings.inappropriate_filter+"</srai>";
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.inappropriate_aiml_file);
|
||||
}
|
||||
else if (textLine.equals("f")) { // filter profanity
|
||||
template = "<srai>"+MagicStrings.profanity_filter+"</srai>";
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.profanity_aiml_file);
|
||||
}
|
||||
else if (textLine.equals("i")) {
|
||||
template = "<srai>"+MagicStrings.insult_filter+"</srai>";
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.insult_aiml_file);
|
||||
}
|
||||
else if (textLine.contains("<srai>") || textLine.contains("<sr/>")) {
|
||||
template = textLine;
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.reductions_update_aiml_file);
|
||||
}
|
||||
else if (textLine.contains("<oob>")) {
|
||||
textLine = "I don't know.";
|
||||
template = textLine;
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.oob_aiml_file);
|
||||
}
|
||||
else if (textLine.contains("<set name") || botThinks.length() > 0) {
|
||||
template = textLine;
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.predicates_aiml_file);
|
||||
}
|
||||
else if (textLine.contains("<get name") && !textLine.contains("<get name=\"name")) {
|
||||
template = textLine;
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.predicates_aiml_file);
|
||||
}
|
||||
else {
|
||||
template = textLine;
|
||||
template += botThinks;
|
||||
saveCategory(bot, c.getPattern(), template, MagicStrings.personality_aiml_file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* implements AIML Map
|
||||
*
|
||||
* A map is a function from one string set to another.
|
||||
* Elements of the domain are called keys and elements of the range are called values.
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AIMLMap extends HashMap<String, String> {
|
||||
|
||||
public String mapName;
|
||||
String host; // for external maps
|
||||
String botid; // for external maps
|
||||
boolean isExternal = false;
|
||||
|
||||
/**
|
||||
* constructor to create a new AIML Map
|
||||
*
|
||||
* @param name the name of the map
|
||||
*/
|
||||
public AIMLMap (String name) {
|
||||
super();
|
||||
this.mapName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a map value given a key
|
||||
*
|
||||
* @param key the domain element
|
||||
* @return the range element or a string indicating the key was not found
|
||||
*/
|
||||
public String get(String key) {
|
||||
String value;
|
||||
if (mapName.equals(MagicStrings.map_successor)) {
|
||||
try {
|
||||
int number = Integer.parseInt(key);
|
||||
return String.valueOf(number+1);
|
||||
} catch (Exception ex) {
|
||||
return MagicStrings.unknown_map_value;
|
||||
}
|
||||
}
|
||||
else if (mapName.equals(MagicStrings.map_predecessor)) {
|
||||
try {
|
||||
int number = Integer.parseInt(key);
|
||||
return String.valueOf(number-1);
|
||||
} catch (Exception ex) {
|
||||
return MagicStrings.unknown_map_value;
|
||||
}
|
||||
}
|
||||
else if (isExternal && MagicBooleans.enable_external_sets) {
|
||||
//String[] split = key.split(" ");
|
||||
String query = mapName.toUpperCase()+" "+key;
|
||||
String response = Sraix.sraix(null, query, MagicStrings.unknown_map_value, null, host, botid, null, "0");
|
||||
|
||||
value = response;
|
||||
}
|
||||
else value = super.get(key);
|
||||
if (value == null) value = MagicStrings.unknown_map_value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* put a new key, value pair into the map.
|
||||
*
|
||||
* @param key the domain element
|
||||
* @param value the range element
|
||||
* @return the value
|
||||
*/
|
||||
@Override
|
||||
public String put(String key, String value) {
|
||||
//log.info("AIMLMap put "+key+"="+value);
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* reads an input stream and loads a map into the bot.
|
||||
*
|
||||
* @param in input stream
|
||||
* @param bot AIML bot
|
||||
* @return number of map elements loaded
|
||||
*/
|
||||
public int readAIMLMapFromInputStream(InputStream in, Bot bot) {
|
||||
int cnt=0;
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
try {
|
||||
while ((strLine = br.readLine()) != null && strLine.length() > 0) {
|
||||
String[] splitLine = strLine.split(":");
|
||||
//log.info("AIMLMap line="+strLine);
|
||||
if (splitLine.length >= 2) {
|
||||
cnt++;
|
||||
if (strLine.startsWith(MagicStrings.remote_map_key)) {
|
||||
if (splitLine.length >= 3) {
|
||||
host = splitLine[1];
|
||||
botid = splitLine[2];
|
||||
isExternal = true;
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
String key = splitLine[0].toUpperCase();
|
||||
String value = splitLine[1];
|
||||
// assume domain element is already normalized for speedier load
|
||||
//key = bot.preProcessor.normalize(key).trim();
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* read an AIML map for a bot
|
||||
*
|
||||
* @param bot the bot associated with this map.
|
||||
*/
|
||||
public void readAIMLMap (Bot bot) {
|
||||
|
||||
try{
|
||||
// Open the file that is the first
|
||||
// command line parameter
|
||||
File file = new File(MagicStrings.maps_path+"/"+mapName+".txt");
|
||||
if (file.exists()) {
|
||||
FileInputStream fstream = new FileInputStream(MagicStrings.maps_path+"/"+mapName+".txt");
|
||||
// Get the object
|
||||
readAIMLMapFromInputStream(fstream, bot);
|
||||
fstream.close();
|
||||
}
|
||||
|
||||
}catch (Exception e){//Catch exception if any
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The interface needed to implement AIML Extension
|
||||
*
|
||||
* A class implementing AIMLProcessorExtension should return
|
||||
* a Set of tag names and provide a function to recursively evaluate the
|
||||
* XML parse tree for each node associated with a new tag.
|
||||
*/
|
||||
public interface AIMLProcessorExtension {
|
||||
/**
|
||||
* provide the AIMLProcessor with a list of extension tag names.
|
||||
*
|
||||
* @return Set of extension tag names
|
||||
*/
|
||||
public Set<String> extensionTagSet();
|
||||
|
||||
/**
|
||||
* recursively evaluate AIML from a node corresponding an extension tag
|
||||
*
|
||||
* @param node current XML parse node
|
||||
* @param ps current parse state
|
||||
* @return result of evaluating AIML
|
||||
*/
|
||||
public String recursEval(Node node, ParseState ps);
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* implements AIML Sets
|
||||
*/
|
||||
public class AIMLSet extends HashSet<String> {
|
||||
//private static final Logger log = LoggerFactory.getLogger(AIMLSet.class);
|
||||
public String setName;
|
||||
int maxLength = 1; // there are no empty sets
|
||||
String host; // for external sets
|
||||
String botid; // for external sets
|
||||
boolean isExternal = false;
|
||||
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param name name of set
|
||||
*/
|
||||
public AIMLSet (String name) {
|
||||
super();
|
||||
this.setName = name.toLowerCase();
|
||||
if (setName.equals(MagicStrings.natural_number_set_name)) maxLength = 1;
|
||||
}
|
||||
public boolean contains(String s) {
|
||||
//if (isExternal) log.info("External "+setName+" contains "+s+"?");
|
||||
//else log.info("Internal "+setName+" contains "+s+"?");
|
||||
if (isExternal && MagicBooleans.enable_external_sets) {
|
||||
String[] split = s.split(" ");
|
||||
if (split.length > maxLength) return false;
|
||||
String query = MagicStrings.set_member_string+setName.toUpperCase()+" "+s;
|
||||
String response = Sraix.sraix(null, query, "false", null, host, botid, null, "0");
|
||||
// log.info("External "+setName+" contains "+s+"? "+response);
|
||||
if (response.equals("true")) return true;
|
||||
else return false;
|
||||
} else if (setName.equals(MagicStrings.natural_number_set_name)) {
|
||||
Pattern numberPattern = Pattern.compile("[0-9]+");
|
||||
Matcher numberMatcher = numberPattern.matcher(s);
|
||||
Boolean isanumber = numberMatcher.matches();
|
||||
//log.info("AIMLSet isanumber '"+s+"' "+isanumber);
|
||||
return isanumber;
|
||||
}
|
||||
else return super.contains(s);
|
||||
}
|
||||
public void writeAIMLSet () {
|
||||
// log.info("Writing AIML Set "+setName);
|
||||
try{
|
||||
// Create file
|
||||
FileWriter fstream = new FileWriter(MagicStrings.sets_path+"/"+setName+".txt");
|
||||
BufferedWriter out = new BufferedWriter(fstream);
|
||||
for (String p : this) {
|
||||
|
||||
out.write(p.trim());
|
||||
out.newLine();
|
||||
}
|
||||
//Close the output stream
|
||||
out.close();
|
||||
}catch (Exception e){//Catch exception if any
|
||||
// log.error("Cannot write AIML set " + setName + ": " + e, e);
|
||||
}
|
||||
}
|
||||
public int readAIMLSetFromInputStream(InputStream in, Bot bot) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
String strLine;
|
||||
int cnt = 0;
|
||||
//Read File Line By Line
|
||||
try {
|
||||
while ((strLine = br.readLine()) != null && strLine.length() > 0) {
|
||||
cnt++;
|
||||
//strLine = bot.preProcessor.normalize(strLine).toUpperCase();
|
||||
// assume the set is pre-normalized for faster loading
|
||||
if (strLine.startsWith("external")) {
|
||||
String[] splitLine = strLine.split(":");
|
||||
if (splitLine.length >= 4) {
|
||||
host = splitLine[1];
|
||||
botid = splitLine[2];
|
||||
maxLength = Integer.parseInt(splitLine[3]);
|
||||
isExternal = true;
|
||||
// log.info("Created external set at "+host+" "+botid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strLine = strLine.toUpperCase().trim();
|
||||
String [] splitLine = strLine.split(" ");
|
||||
int length = splitLine.length;
|
||||
if (length > maxLength) maxLength = length;
|
||||
//log.info("readAIMLSetFromInputStream "+strLine);
|
||||
add(strLine.trim());
|
||||
}
|
||||
/*Category c = new Category(0, "ISA"+setName.toUpperCase()+" "+strLine.toUpperCase(), "*", "*", "true", MagicStrings.null_aiml_file);
|
||||
bot.brain.addCategory(c);*/
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
public void readAIMLSet (Bot bot) {
|
||||
final String setPath = MagicStrings.sets_path+"/"+setName+".txt";
|
||||
// log.info("Reading AIML Set " + setPath);
|
||||
try{
|
||||
// Open the file that is the first
|
||||
// command line parameter
|
||||
File file = new File(setPath);
|
||||
if (file.exists()) {
|
||||
FileInputStream fstream = new FileInputStream(setPath);
|
||||
// Get the object
|
||||
readAIMLSetFromInputStream(fstream, bot);
|
||||
fstream.close();
|
||||
}
|
||||
// else log.info(MagicStrings.sets_path+"/"+setName+".txt not found");
|
||||
}catch (Exception e){//Catch exception if any
|
||||
// log.error("Cannot read AIML set '" + setPath + "': " + e, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package org.alicebot.ab;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper class to write some custom AIML
|
||||
*/
|
||||
public class AIMLWriter {
|
||||
//private static final Logger log = LoggerFactory.getLogger(AIMLWriter.class);
|
||||
public static String[][] relatives = {
|
||||
// aunt uncle nephew niece grandma grandpa
|
||||
{"aunt", "her", "who", "aunt"},
|
||||
{"ant", "her", "who", "aunt"},
|
||||
{"uncle", "his", "who", "uncle"},
|
||||
{"friend", "his", "who", "friend"},
|
||||
{"bestfriend", "his", "who", "bestfriend"},
|
||||
{"niece", "her", "who", "niece"},
|
||||
{"nephew", "his", "who", "nephew"},
|
||||
{"grandmother", "her", "who", "grandmother"},
|
||||
{"grandma", "her", "who", "grandmother"},
|
||||
{"grandmom", "her", "who", "grandmother"},
|
||||
{"mother", "her", "who", "mother"},
|
||||
{"ma", "her", "who", "mother"},
|
||||
{"mom", "her", "who", "mother"},
|
||||
{"momma", "her", "who", "mother"},
|
||||
{"mum", "her", "who", "mother"},
|
||||
{"mumma", "her", "who", "mother"},
|
||||
{"mommy", "her", "who", "mother"},
|
||||
{"mummy", "her", "who", "mother"},
|
||||
{"grandfather", "his", "who", "grandfather"},
|
||||
{"granddad", "his", "who", "grandfather"},
|
||||
{"father", "his", "who", "father"},
|
||||
{"dad", "his", "who", "father"},
|
||||
{"dada", "his", "who", "father"},
|
||||
{"daddy", "his", "who", "father"},
|
||||
{"husband", "his", "who", "husband"},
|
||||
{"hubby", "his", "who", "husband"},
|
||||
{"wife", "her", "who", "wife"},
|
||||
{"wifey", "her", "who", "wife"},
|
||||
{"son", "his", "who", "son"},
|
||||
{"daughter", "her", "who", "daughter"},
|
||||
{"brother", "his", "who", "brother"},
|
||||
{"sister", "her", "who", "sister"},
|
||||
{"bro", "his", "who", "brother"},
|
||||
{"sis", "her", "who", "sister"},
|
||||
{"boyfriend", "his", "who", "boyfriend"},
|
||||
{"girlfriend", "her", "who", "girlfriend"}};
|
||||
public static void familiarContactAIML () {
|
||||
for (int i = 0; i < relatives.length; i++) {
|
||||
String familiar = relatives[i][0];
|
||||
String pronoun = relatives[i][1];
|
||||
String predicate = relatives[i][3];
|
||||
String aiml =
|
||||
"<category><pattern>ISFAMILIARNAME "+familiar.toUpperCase()+"</pattern>" +
|
||||
"<template>true</template></category>\n"+
|
||||
"<category><pattern>FAMILIARPREDICATE "+familiar.toUpperCase()+"</pattern>" +
|
||||
"<template>"+predicate +"</template></category>\n"+
|
||||
"<category><pattern>FAMILIARPRONOUN "+familiar.toUpperCase()+"</pattern>" +
|
||||
"<template>"+pronoun+"</template></category>\n";
|
||||
|
||||
|
||||
|
||||
//info(aiml);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,756 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Class representing the AIML bot
|
||||
*/
|
||||
public class Bot {
|
||||
//private static final Logger log = LoggerFactory.getLogger(Bot.class);
|
||||
public final Properties properties = new Properties();
|
||||
public final PreProcessor preProcessor;
|
||||
public final Graphmaster brain;
|
||||
public final Graphmaster inputGraph;
|
||||
public final Graphmaster learnfGraph;
|
||||
public final Graphmaster patternGraph;
|
||||
public final Graphmaster deletedGraph;
|
||||
public Graphmaster unfinishedGraph;
|
||||
// public final ArrayList<Category> categories;
|
||||
public ArrayList<Category> suggestedCategories;
|
||||
public String name=MagicStrings.unknown_bot_name;
|
||||
public HashMap<String, AIMLSet> setMap = new HashMap<String, AIMLSet>();
|
||||
public HashMap<String, AIMLMap> mapMap = new HashMap<String, AIMLMap>();
|
||||
|
||||
/**
|
||||
* Set all directory path variables for this bot
|
||||
*
|
||||
* @param root root directory of Program AB
|
||||
* @param name name of bot
|
||||
*/
|
||||
public void setAllPaths (String root, String name) {
|
||||
MagicStrings.bot_path = root+"/bots";
|
||||
MagicStrings.bot_name_path = MagicStrings.bot_path+"/"+name;
|
||||
// org.alicebot.ab
|
||||
// org.alicebot.ab.cli
|
||||
// org.alicebot.ab.utils
|
||||
MagicStrings.aiml_path = MagicStrings.bot_name_path+"/aiml";
|
||||
MagicStrings.aimlif_path = MagicStrings.bot_name_path+"/aimlif";
|
||||
MagicStrings.config_path = MagicStrings.bot_name_path+"/config";
|
||||
MagicStrings.log_path = MagicStrings.bot_name_path+"/logs";
|
||||
MagicStrings.sets_path = MagicStrings.bot_name_path+"/sets";
|
||||
MagicStrings.maps_path = MagicStrings.bot_name_path+"/maps";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor (default action, default path, default bot name)
|
||||
*/
|
||||
public Bot() {
|
||||
this(MagicStrings.default_bot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor (default action, default path)
|
||||
* @param name
|
||||
*/
|
||||
public Bot(String name) {
|
||||
this(name, MagicStrings.root_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor (default action)
|
||||
*
|
||||
* @param name
|
||||
* @param path
|
||||
*/
|
||||
public Bot(String name, String path) {
|
||||
this(name, path, "auto");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name name of bot
|
||||
* @param path root path of Program AB
|
||||
* @param action Program AB action
|
||||
*/
|
||||
public Bot(String name, String path, String action) {
|
||||
this.name = name;
|
||||
setAllPaths(path, name);
|
||||
this.brain = new Graphmaster(this);
|
||||
this.inputGraph = new Graphmaster(this);
|
||||
this.learnfGraph = new Graphmaster(this);
|
||||
this.deletedGraph = new Graphmaster(this);
|
||||
this.patternGraph = new Graphmaster(this);
|
||||
this.unfinishedGraph = new Graphmaster(this);
|
||||
// this.categories = new ArrayList<Category>();
|
||||
this.suggestedCategories = new ArrayList<Category>();
|
||||
preProcessor = new PreProcessor(this);
|
||||
addProperties();
|
||||
addAIMLSets();
|
||||
addAIMLMaps();
|
||||
AIMLSet number = new AIMLSet(MagicStrings.natural_number_set_name);
|
||||
setMap.put(MagicStrings.natural_number_set_name, number);
|
||||
AIMLMap successor = new AIMLMap(MagicStrings.map_successor);
|
||||
mapMap.put(MagicStrings.map_successor, successor);
|
||||
AIMLMap predecessor = new AIMLMap(MagicStrings.map_predecessor);
|
||||
mapMap.put(MagicStrings.map_predecessor, predecessor);
|
||||
////info("setMap = "+setMap);
|
||||
Date aimlDate = new Date(new File(MagicStrings.aiml_path).lastModified());
|
||||
Date aimlIFDate = new Date(new File(MagicStrings.aimlif_path).lastModified());
|
||||
//info("AIML modified {} AIMLIF modified {}", aimlDate, aimlIFDate);
|
||||
readDeletedIFCategories();
|
||||
readUnfinishedIFCategories();
|
||||
MagicStrings.pannous_api_key = Utilities.getPannousAPIKey();
|
||||
MagicStrings.pannous_login = Utilities.getPannousLogin();
|
||||
if (action.equals("aiml2csv")) addCategoriesFromAIML();
|
||||
else if (action.equals("csv2aiml")) addCategoriesFromAIMLIF();
|
||||
else if (aimlDate.after(aimlIFDate)) {
|
||||
//info("AIML modified after AIMLIF");
|
||||
addCategoriesFromAIML();
|
||||
writeAIMLIFFiles();
|
||||
}
|
||||
else {
|
||||
addCategoriesFromAIMLIF();
|
||||
if (brain.getCategories().size()==0) {
|
||||
//info("No AIMLIF Files found. Looking for AIML");
|
||||
addCategoriesFromAIML();
|
||||
}
|
||||
}
|
||||
//info("--> Bot {} {} completed {} deleted {} unfinished",
|
||||
//name, brain.getCategories().size(), deletedGraph.getCategories().size(), unfinishedGraph.getCategories().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* add an array list of categories with a specific file name
|
||||
*
|
||||
* @param file name of AIML file
|
||||
* @param moreCategories list of categories
|
||||
*/
|
||||
void addMoreCategories (String file, ArrayList<Category> moreCategories) {
|
||||
if (file.contains(MagicStrings.deleted_aiml_file)) {
|
||||
for (Category c : moreCategories) {
|
||||
////info("Delete "+c.getPattern());
|
||||
deletedGraph.addCategory(c);
|
||||
}
|
||||
} else if (file.contains(MagicStrings.unfinished_aiml_file)) {
|
||||
for (Category c : moreCategories) {
|
||||
////info("Delete "+c.getPattern());
|
||||
if (brain.findNode(c) == null)
|
||||
unfinishedGraph.addCategory(c);
|
||||
//info("unfinished {} found in brain", c.inputThatTopic());
|
||||
}
|
||||
} else if (file.contains(MagicStrings.learnf_aiml_file) ) {
|
||||
//info("Reading Learnf file");
|
||||
for (Category c : moreCategories) {
|
||||
brain.addCategory(c);
|
||||
learnfGraph.addCategory(c);
|
||||
patternGraph.addCategory(c);
|
||||
}
|
||||
//this.categories.addAll(moreCategories);
|
||||
} else {
|
||||
for (Category c : moreCategories) {
|
||||
////info("Brain size="+brain.root.size());
|
||||
//brain.printgraph();
|
||||
brain.addCategory(c);
|
||||
patternGraph.addCategory(c);
|
||||
//brain.printgraph();
|
||||
}
|
||||
//this.categories.addAll(moreCategories);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all brain categories from AIML directory
|
||||
*/
|
||||
void addCategoriesFromAIML() {
|
||||
Timer timer = new Timer();
|
||||
timer.start();
|
||||
try {
|
||||
// Directory path here
|
||||
String file;
|
||||
File folder = new File(MagicStrings.aiml_path);
|
||||
if (folder.exists()) {
|
||||
File[] listOfFiles = folder.listFiles();
|
||||
//info("Loading AIML files from '{}'", MagicStrings.aiml_path);
|
||||
for (File listOfFile : listOfFiles) {
|
||||
if (listOfFile.isFile()) {
|
||||
file = listOfFile.getName();
|
||||
if (file.endsWith(".aiml") || file.endsWith(".AIML")) {
|
||||
//info(file);
|
||||
try {
|
||||
ArrayList<Category> moreCategories = AIMLProcessor.AIMLToCategories(MagicStrings.aiml_path, file);
|
||||
addMoreCategories(file, moreCategories);
|
||||
} catch (Exception iex) {
|
||||
//error("Problem loading '" + file +"': " + iex, iex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//info("addCategories: '{}' does not exist.", MagicStrings.aiml_path);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
//info("Loaded {} categories in {} sec", brain.getCategories().size(), timer.elapsedTimeSecs());
|
||||
}
|
||||
|
||||
/**
|
||||
* load all brain categories from AIMLIF directory
|
||||
*/
|
||||
void addCategoriesFromAIMLIF() {
|
||||
Timer timer = new Timer();
|
||||
timer.start();
|
||||
try {
|
||||
// Directory path here
|
||||
String file;
|
||||
File folder = new File(MagicStrings.aimlif_path);
|
||||
if (folder.exists()) {
|
||||
File[] listOfFiles = folder.listFiles();
|
||||
//info("Loading AIML files from '{}'", MagicStrings.aimlif_path);
|
||||
for (File listOfFile : listOfFiles) {
|
||||
if (listOfFile.isFile()) {
|
||||
file = listOfFile.getName();
|
||||
if (file.endsWith(MagicStrings.aimlif_file_suffix) || file.endsWith(MagicStrings.aimlif_file_suffix.toUpperCase())) {
|
||||
////info(file);
|
||||
try {
|
||||
ArrayList<Category> moreCategories = readIFCategories(MagicStrings.aimlif_path + "/" + file);
|
||||
addMoreCategories(file, moreCategories);
|
||||
// MemStats.memStats();
|
||||
} catch (Exception iex) {
|
||||
//error("Problem loading '" + file + "': " + iex, iex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//info("addCategories: '{}' does not exist.", MagicStrings.aimlif_path);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
//info("Loaded {} categories in {} sec", brain.getCategories().size(), timer.elapsedTimeSecs());
|
||||
}
|
||||
|
||||
/**
|
||||
* read deleted categories from AIMLIF file
|
||||
*/
|
||||
public void readDeletedIFCategories() {
|
||||
readCertainIFCategories(deletedGraph, MagicStrings.deleted_aiml_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* read unfinished categories from AIMLIF file
|
||||
*/
|
||||
public void readUnfinishedIFCategories() {
|
||||
readCertainIFCategories(unfinishedGraph, MagicStrings.unfinished_aiml_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* update unfinished categories removing any categories that have been finished
|
||||
*/
|
||||
public void updateUnfinishedCategories () {
|
||||
ArrayList<Category> unfinished = unfinishedGraph.getCategories();
|
||||
unfinishedGraph = new Graphmaster(this);
|
||||
for (Category c : unfinished) {
|
||||
if (!brain.existsCategory(c)) unfinishedGraph.addCategory(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* write all AIML and AIMLIF categories
|
||||
*/
|
||||
public void writeQuit() {
|
||||
writeAIMLIFFiles();
|
||||
//info("Wrote AIMLIF Files");
|
||||
writeAIMLFiles();
|
||||
//info("Wrote AIML Files");
|
||||
writeDeletedIFCategories();
|
||||
updateUnfinishedCategories();
|
||||
writeUnfinishedIFCategories();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* read categories from specified AIMLIF file into specified graph
|
||||
*
|
||||
* @param graph Graphmaster to store categories
|
||||
* @param fileName file name of AIMLIF file
|
||||
*/
|
||||
public void readCertainIFCategories(Graphmaster graph, String fileName) {
|
||||
File file = new File(MagicStrings.aimlif_path+"/"+fileName+MagicStrings.aimlif_file_suffix);
|
||||
if (file.exists()) {
|
||||
try {
|
||||
ArrayList<Category> deletedCategories = readIFCategories(MagicStrings.aimlif_path+"/"+fileName+MagicStrings.aimlif_file_suffix);
|
||||
for (Category d : deletedCategories) graph.addCategory(d);
|
||||
//info("readCertainIFCategories {} categories from {}", graph.getCategories().size(), fileName+MagicStrings.aimlif_file_suffix);
|
||||
} catch (Exception iex) {
|
||||
//error("Problem loading '" + fileName + "': " + iex, iex);
|
||||
}
|
||||
}
|
||||
//info("No "+MagicStrings.deleted_aiml_file+MagicStrings.aimlif_file_suffix+" file found");
|
||||
}
|
||||
|
||||
/**
|
||||
* write certain specified categories as AIMLIF files
|
||||
*
|
||||
* @param graph the Graphmaster containing the categories to write
|
||||
* @param file the destination AIMLIF file
|
||||
*/
|
||||
public void writeCertainIFCategories(Graphmaster graph, String file) {
|
||||
if (MagicBooleans.trace_mode) //info("writeCertainIFCaegories "+file+" size= "+graph.getCategories().size());
|
||||
writeIFCategories(graph.getCategories(), file+MagicStrings.aimlif_file_suffix);
|
||||
File dir = new File(MagicStrings.aimlif_path);
|
||||
dir.setLastModified(new Date().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* write deleted categories to AIMLIF file
|
||||
*/
|
||||
public void writeDeletedIFCategories() {
|
||||
writeCertainIFCategories(deletedGraph, MagicStrings.deleted_aiml_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* write learned categories to AIMLIF file
|
||||
*/
|
||||
public void writeLearnfIFCategories() {
|
||||
writeCertainIFCategories(learnfGraph, MagicStrings.learnf_aiml_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* write unfinished categories to AIMLIF file
|
||||
*/
|
||||
public void writeUnfinishedIFCategories() {
|
||||
writeCertainIFCategories(unfinishedGraph, MagicStrings.unfinished_aiml_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* write categories to AIMLIF file
|
||||
*
|
||||
* @param cats array list of categories
|
||||
* @param filename AIMLIF filename
|
||||
*/
|
||||
public void writeIFCategories (ArrayList<Category> cats, String filename) {
|
||||
////info("writeIFCategories "+filename);
|
||||
BufferedWriter bw = null;
|
||||
File existsPath = new File(MagicStrings.aimlif_path);
|
||||
if (existsPath.exists())
|
||||
try {
|
||||
//Construct the bw object
|
||||
bw = new BufferedWriter(new FileWriter(MagicStrings.aimlif_path+"/"+filename)) ;
|
||||
for (Category category : cats) {
|
||||
bw.write(Category.categoryToIF(category));
|
||||
bw.newLine();
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
//Close the bw
|
||||
try {
|
||||
if (bw != null) {
|
||||
bw.flush();
|
||||
bw.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all AIMLIF files from bot brain
|
||||
*/
|
||||
public void writeAIMLIFFiles () {
|
||||
//info("writeAIMLIFFiles");
|
||||
HashMap<String, BufferedWriter> fileMap = new HashMap<String, BufferedWriter>();
|
||||
if (deletedGraph.getCategories().size() > 0) writeDeletedIFCategories();
|
||||
ArrayList<Category> brainCategories = brain.getCategories();
|
||||
Collections.sort(brainCategories, Category.CATEGORY_NUMBER_COMPARATOR);
|
||||
for (Category c : brainCategories) {
|
||||
try {
|
||||
BufferedWriter bw;
|
||||
String fileName = c.getFilename();
|
||||
if (fileMap.containsKey(fileName)) bw = fileMap.get(fileName);
|
||||
else {
|
||||
bw = new BufferedWriter(new FileWriter(MagicStrings.aimlif_path+"/"+fileName+MagicStrings.aimlif_file_suffix));
|
||||
fileMap.put(fileName, bw);
|
||||
|
||||
}
|
||||
bw.write(Category.categoryToIF(c));
|
||||
bw.newLine();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
Set set = fileMap.keySet();
|
||||
for (Object aSet : set) {
|
||||
BufferedWriter bw = fileMap.get(aSet);
|
||||
//Close the bw
|
||||
try {
|
||||
if (bw != null) {
|
||||
bw.flush();
|
||||
bw.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
File dir = new File(MagicStrings.aimlif_path);
|
||||
dir.setLastModified(new Date().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all AIML files. Adds categories for BUILD and DEVELOPMENT ENVIRONMENT
|
||||
*/
|
||||
public void writeAIMLFiles () {
|
||||
HashMap<String, BufferedWriter> fileMap = new HashMap<String, BufferedWriter>();
|
||||
Category b = new Category(0, "BUILD", "*", "*", new Date().toString(), "update.aiml");
|
||||
brain.addCategory(b);
|
||||
b = new Category(0, "DELEVLOPMENT ENVIRONMENT", "*", "*", MagicStrings.programNameVersion, "update.aiml");
|
||||
brain.addCategory(b);
|
||||
ArrayList<Category> brainCategories = brain.getCategories();
|
||||
Collections.sort(brainCategories, Category.CATEGORY_NUMBER_COMPARATOR);
|
||||
for (Category c : brainCategories) {
|
||||
|
||||
if (!c.getFilename().equals(MagicStrings.null_aiml_file))
|
||||
try {
|
||||
////info("Writing "+c.getCategoryNumber()+" "+c.inputThatTopic());
|
||||
BufferedWriter bw;
|
||||
String fileName = c.getFilename();
|
||||
if (fileMap.containsKey(fileName)) bw = fileMap.get(fileName);
|
||||
else {
|
||||
String copyright = Utilities.getCopyright(this, fileName);
|
||||
bw = new BufferedWriter(new FileWriter(MagicStrings.aiml_path+"/"+fileName));
|
||||
fileMap.put(fileName, bw);
|
||||
bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n" +
|
||||
"<aiml>\n");
|
||||
bw.write(copyright);
|
||||
//bw.newLine();
|
||||
}
|
||||
bw.write(Category.categoryToAIML(c)+"\n");
|
||||
//bw.newLine();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
Set set = fileMap.keySet();
|
||||
for (Object aSet : set) {
|
||||
BufferedWriter bw = fileMap.get(aSet);
|
||||
//Close the bw
|
||||
try {
|
||||
if (bw != null) {
|
||||
bw.write("</aiml>\n");
|
||||
bw.flush();
|
||||
bw.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
File dir = new File(MagicStrings.aiml_path);
|
||||
dir.setLastModified(new Date().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* load bot properties
|
||||
*/
|
||||
void addProperties() {
|
||||
try {
|
||||
properties.getProperties(MagicStrings.config_path+"/properties.txt");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static int leafPatternCnt = 0;
|
||||
static int starPatternCnt = 0;
|
||||
|
||||
/** find suggested patterns in a graph of inputs
|
||||
*
|
||||
*/
|
||||
public void findPatterns() {
|
||||
findPatterns(inputGraph.root, "");
|
||||
//info("{} Leaf Patterns {} Star Patterns", leafPatternCnt, starPatternCnt);
|
||||
}
|
||||
|
||||
/** find patterns recursively
|
||||
*
|
||||
* @param node current graph node
|
||||
* @param partialPatternThatTopic partial pattern path
|
||||
*/
|
||||
void findPatterns(Nodemapper node, String partialPatternThatTopic) {
|
||||
if (NodemapperOperator.isLeaf(node)) {
|
||||
////info("LEAF: "+node.category.getActivationCnt()+". "+partialPatternThatTopic);
|
||||
if (node.category.getActivationCnt() > MagicNumbers.node_activation_cnt) {
|
||||
////info("LEAF: "+node.category.getActivationCnt()+". "+partialPatternThatTopic+" "+node.shortCut); //Start writing to the output stream
|
||||
leafPatternCnt ++;
|
||||
try {
|
||||
String categoryPatternThatTopic = "";
|
||||
if (node.shortCut) {
|
||||
////info("Partial patternThatTopic = "+partialPatternThatTopic);
|
||||
categoryPatternThatTopic = partialPatternThatTopic + " <THAT> * <TOPIC> *";
|
||||
}
|
||||
else categoryPatternThatTopic = partialPatternThatTopic;
|
||||
Category c = new Category(0, categoryPatternThatTopic, MagicStrings.blank_template, MagicStrings.unknown_aiml_file);
|
||||
//if (brain.existsCategory(c)) //info(c.inputThatTopic()+" Exists");
|
||||
//if (deleted.existsCategory(c)) //info(c.inputThatTopic()+ " Deleted");
|
||||
if (!brain.existsCategory(c) && !deletedGraph.existsCategory(c) && !unfinishedGraph.existsCategory(c)) {
|
||||
patternGraph.addCategory(c);
|
||||
suggestedCategories.add(c);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(NodemapperOperator.size(node) > MagicNumbers.node_size) {
|
||||
////info("STAR: "+NodemapperOperator.size(node)+". "+partialPatternThatTopic+" * <that> * <topic> *");
|
||||
starPatternCnt ++;
|
||||
try {
|
||||
Category c = new Category(0, partialPatternThatTopic+" * <THAT> * <TOPIC> *", MagicStrings.blank_template, MagicStrings.unknown_aiml_file);
|
||||
//if (brain.existsCategory(c)) //info(c.inputThatTopic()+" Exists");
|
||||
//if (deleted.existsCategory(c)) //info(c.inputThatTopic()+ " Deleted");
|
||||
if (!brain.existsCategory(c) && !deletedGraph.existsCategory(c) && !unfinishedGraph.existsCategory(c)) {
|
||||
patternGraph.addCategory(c);
|
||||
suggestedCategories.add(c);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
for (String key : NodemapperOperator.keySet(node)) {
|
||||
Nodemapper value = NodemapperOperator.get(node, key);
|
||||
findPatterns(value, partialPatternThatTopic + " " + key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** classify inputs into matching categories
|
||||
*
|
||||
* @param filename file containing sample normalized inputs
|
||||
*/
|
||||
public void classifyInputs (String filename) {
|
||||
try{
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
int count = 0;
|
||||
while ((strLine = br.readLine())!= null) {
|
||||
// Print the content on the console
|
||||
////info("Classifying "+strLine);
|
||||
if (strLine.startsWith("Human: ")) strLine = strLine.substring("Human: ".length(), strLine.length());
|
||||
Nodemapper match = patternGraph.match(strLine, "unknown", "unknown");
|
||||
match.category.incrementActivationCnt();
|
||||
count += 1;
|
||||
}
|
||||
//Close the input stream
|
||||
br.close();
|
||||
} catch (Exception e){//Catch exception if any
|
||||
//error("Cannot classify inputs from '" + filename + "': " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
/** read sample inputs from filename, turn them into Paths, and
|
||||
* add them to the graph.
|
||||
*
|
||||
* @param filename file containing sample inputs
|
||||
*/
|
||||
public void graphInputs (String filename) {
|
||||
try{
|
||||
// Open the file that is the first
|
||||
// command line parameter
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
//strLine = preProcessor.normalize(strLine);
|
||||
Category c = new Category(0, strLine, "*", "*", "nothing", MagicStrings.unknown_aiml_file);
|
||||
Nodemapper node = inputGraph.findNode(c);
|
||||
if (node == null) {
|
||||
inputGraph.addCategory(c);
|
||||
c.incrementActivationCnt();
|
||||
}
|
||||
else node.category.incrementActivationCnt();
|
||||
////info("Root branches="+g.root.size());
|
||||
}
|
||||
//Close the input stream
|
||||
br.close();
|
||||
}catch (Exception e){//Catch exception if any
|
||||
//error("Cannot graph inputs from '" + filename + "': " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* read AIMLIF categories from a file into bot brain
|
||||
*
|
||||
* @param filename name of AIMLIF file
|
||||
* @return array list of categories read
|
||||
*/
|
||||
public ArrayList<Category> readIFCategories (String filename) {
|
||||
ArrayList<Category> categories = new ArrayList<Category>();
|
||||
try{
|
||||
// Open the file that is the first
|
||||
// command line parameter
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
try {
|
||||
Category c = Category.IFToCategory(strLine);
|
||||
categories.add(c);
|
||||
} catch (Exception ex) {
|
||||
//warn("Invalid AIMLIF in "+filename+" line "+strLine, ex);
|
||||
}
|
||||
}
|
||||
//Close the input stream
|
||||
br.close();
|
||||
}catch (Exception e){//Catch exception if any
|
||||
//error("Cannot read IF Categories from '" + filename + "': " + e, e);
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* check Graphmaster for shadowed categories
|
||||
*/
|
||||
public void shadowChecker () {
|
||||
shadowChecker(brain.root) ;
|
||||
}
|
||||
|
||||
/** traverse graph and test all categories found in leaf nodes for shadows
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
void shadowChecker(Nodemapper node) {
|
||||
if (NodemapperOperator.isLeaf(node)) {
|
||||
String input = node.category.getPattern().replace("*", "XXX").replace("_", "XXX");
|
||||
String that = node.category.getThat().replace("*", "XXX").replace("_", "XXX");
|
||||
String topic = node.category.getTopic().replace("*", "XXX").replace("_", "XXX");
|
||||
Nodemapper match = brain.match(input, that, topic);
|
||||
if (match != node) {
|
||||
//info(Graphmaster.inputThatTopic(input, that, topic));
|
||||
//info("MATCHED: {}", match.category.inputThatTopic());
|
||||
//info("SHOULD MATCH: {}", node.category.inputThatTopic());
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (String key : NodemapperOperator.keySet(node)) {
|
||||
shadowChecker(NodemapperOperator.get(node, key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all AIML Sets
|
||||
*/
|
||||
void addAIMLSets() {
|
||||
Timer timer = new Timer();
|
||||
timer.start();
|
||||
try {
|
||||
// Directory path here
|
||||
String file;
|
||||
File folder = new File(MagicStrings.sets_path);
|
||||
if (folder.exists()) {
|
||||
File[] listOfFiles = folder.listFiles();
|
||||
//info("Loading AIML Sets files from '{}'", MagicStrings.sets_path);
|
||||
for (File listOfFile : listOfFiles) {
|
||||
if (listOfFile.isFile()) {
|
||||
file = listOfFile.getName();
|
||||
if (file.endsWith(".txt") || file.endsWith(".TXT")) {
|
||||
//info(file);
|
||||
String setName = file.substring(0, file.length()-".txt".length());
|
||||
//info("Read AIML Set {}", setName);
|
||||
AIMLSet aimlSet = new AIMLSet(setName);
|
||||
aimlSet.readAIMLSet(this);
|
||||
setMap.put(setName, aimlSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//info("addAIMLSets: {} does not exist.", MagicStrings.sets_path);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all AIML Maps
|
||||
*/
|
||||
void addAIMLMaps() {
|
||||
Timer timer = new Timer();
|
||||
timer.start();
|
||||
try {
|
||||
// Directory path here
|
||||
String file;
|
||||
File folder = new File(MagicStrings.maps_path);
|
||||
if (folder.exists()) {
|
||||
File[] listOfFiles = folder.listFiles();
|
||||
//info("Loading AIML Map files from '{}'", MagicStrings.maps_path);
|
||||
for (File listOfFile : listOfFiles) {
|
||||
if (listOfFile.isFile()) {
|
||||
file = listOfFile.getName();
|
||||
if (file.endsWith(".txt") || file.endsWith(".TXT")) {
|
||||
//info(file);
|
||||
String mapName = file.substring(0, file.length()-".txt".length());
|
||||
//info("Read AIML Map "+mapName);
|
||||
AIMLMap aimlMap = new AIMLMap(mapName);
|
||||
aimlMap.readAIMLMap(this);
|
||||
mapMap.put(mapName, aimlMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//info("addCategories: '{}' does not exist.", MagicStrings.aiml_path);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,392 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.util.Comparator;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* structure representing an AIML category and operations on Category
|
||||
*/
|
||||
public class Category {
|
||||
//private static final Logger log = LoggerFactory.getLogger(Category.class);
|
||||
private String pattern;
|
||||
private String that;
|
||||
private String topic;
|
||||
private String template;
|
||||
private String filename;
|
||||
private int activationCnt;
|
||||
private final int categoryNumber; // for loading order
|
||||
public static int categoryCnt = 0;
|
||||
private AIMLSet matches;
|
||||
|
||||
/**
|
||||
* Return a set of inputs matching the category
|
||||
*
|
||||
* @return and AIML Set of elements matching this category
|
||||
*/
|
||||
public AIMLSet getMatches() {
|
||||
if (matches != null)
|
||||
return matches;
|
||||
else return new AIMLSet("No Matches");
|
||||
}
|
||||
|
||||
/**
|
||||
* number of times a category was activated by inputs
|
||||
*
|
||||
* @return integer number of activations
|
||||
*/
|
||||
public int getActivationCnt () {
|
||||
return activationCnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the index number of this category
|
||||
*
|
||||
* @return unique integer identifying this category
|
||||
*/
|
||||
public int getCategoryNumber () {
|
||||
return categoryNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* get category pattern
|
||||
*
|
||||
* @return pattern
|
||||
*/
|
||||
public String getPattern () {
|
||||
if (pattern == null) return "*";
|
||||
else return pattern;
|
||||
}
|
||||
/**
|
||||
* get category that pattern
|
||||
*
|
||||
* @return that pattern
|
||||
*/
|
||||
public String getThat () {
|
||||
if (that == null) return "*";
|
||||
else return that;
|
||||
}
|
||||
/**
|
||||
* get category topic pattern
|
||||
*
|
||||
* @return topic pattern
|
||||
*/
|
||||
public String getTopic () {
|
||||
if (topic == null) return "*";
|
||||
else return topic;
|
||||
}
|
||||
/**
|
||||
* get category template
|
||||
*
|
||||
* @return template
|
||||
*/
|
||||
public String getTemplate () {
|
||||
if (template==null) return "";
|
||||
else
|
||||
return template;
|
||||
}
|
||||
/**
|
||||
* get name of AIML file for this category
|
||||
*
|
||||
* @return file name
|
||||
*/
|
||||
public String getFilename () {
|
||||
if (filename==null) return MagicStrings.unknown_aiml_file;
|
||||
else
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* increment the category activation count
|
||||
*/
|
||||
public void incrementActivationCnt() {
|
||||
activationCnt++;
|
||||
}
|
||||
|
||||
/** set category activation count
|
||||
*
|
||||
* @param cnt activation count
|
||||
*/
|
||||
public void setActivationCnt(int cnt) {
|
||||
activationCnt = cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* set category filename
|
||||
* @param filename name of AIML file
|
||||
*/
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
/**
|
||||
* set category template
|
||||
* @param template AIML template
|
||||
*/
|
||||
public void setTemplate(String template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
/**
|
||||
* set category pattern
|
||||
*
|
||||
* @param pattern AIML pattern
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* set category that pattern
|
||||
*
|
||||
* @param that AIML that pattern
|
||||
*/
|
||||
public void setThat(String that) {
|
||||
this.that = that;
|
||||
}
|
||||
|
||||
/**
|
||||
* set category topic
|
||||
*
|
||||
* @param topic AIML topic pattern
|
||||
*/
|
||||
public void setTopic(String topic) {
|
||||
this.topic = topic;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a string represeting the full pattern path as "{@code input pattern <THAT> that pattern <TOPIC> topic pattern}"
|
||||
* @return
|
||||
*/
|
||||
public String inputThatTopic() {
|
||||
return Graphmaster.inputThatTopic(pattern, that, topic);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a matching input to the matching input set
|
||||
*
|
||||
* @param input matching input
|
||||
*/
|
||||
public void addMatch (String input) {
|
||||
if (matches == null) {
|
||||
String setName = this.inputThatTopic().replace("*", "STAR").replace("_", "UNDERSCORE").replace(" ","-").replace("<THAT>","THAT").replace("<TOPIC>","TOPIC");
|
||||
// log.info("Created match set "+setName);
|
||||
matches = new AIMLSet(setName);
|
||||
}
|
||||
matches.add(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a template to a single-line representation by replacing "," with #Comma and newline with #Newline
|
||||
* @param template original template
|
||||
* @return template on a single line of text
|
||||
*/
|
||||
public static String templateToLine (String template) {
|
||||
String result = template;
|
||||
result = result.replaceAll("(\r\n|\n\r|\r|\n)", "\\#Newline");
|
||||
result = result.replaceAll(MagicStrings.aimlif_split_char, MagicStrings.aimlif_split_char_name);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* restore a template to its original form by replacing #Comma with "," and #Newline with newline.
|
||||
* @param line template on a single line of text
|
||||
* @return original multi-line template
|
||||
*/
|
||||
private static String lineToTemplate(String line) {
|
||||
String result = line.replaceAll("\\#Newline","\n");
|
||||
result = result.replaceAll(MagicStrings.aimlif_split_char_name, MagicStrings.aimlif_split_char);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a category from AIMLIF format to a Category object
|
||||
*
|
||||
* @param IF Category in AIMLIF format
|
||||
* @return Category object
|
||||
*/
|
||||
public static Category IFToCategory(String IF) {
|
||||
String[] split = IF.split(MagicStrings.aimlif_split_char);
|
||||
//log.info("Read: "+split);
|
||||
return new Category(Integer.parseInt(split[0]), split[1], split[2], split[3], lineToTemplate(split[4]), split[5]);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a Category object to AIMLIF format
|
||||
* @param category Category object
|
||||
* @return category in AIML format
|
||||
*/
|
||||
public static String categoryToIF(Category category) {
|
||||
//log.info("categoryToIF: template="+templateToLine(category.getTemplate()));
|
||||
String c = MagicStrings.aimlif_split_char;
|
||||
return category.getActivationCnt()+c+category.getPattern()+c+category.getThat()+c+category.getTopic()+c+templateToLine(category.getTemplate())+c+category.getFilename();
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a Category object to AIML syntax
|
||||
*
|
||||
* @param category Category object
|
||||
* @return AIML Category
|
||||
*/
|
||||
public static String categoryToAIML(Category category) {
|
||||
String topicStart = ""; String topicEnd = "";
|
||||
String thatStatement = "";
|
||||
String result = "";
|
||||
String pattern = category.getPattern();
|
||||
String[] splitPattern = pattern.split(" ");
|
||||
for (String w : splitPattern) {
|
||||
if (w.startsWith("<TYPE>")) w = w.toLowerCase();
|
||||
pattern = pattern+" "+w;
|
||||
}
|
||||
pattern = pattern.trim();
|
||||
// if (pattern.contains("type")) log.info("Rebuilt pattern "+pattern);
|
||||
|
||||
String NL = System.getProperty("line.separator");
|
||||
NL = "\n";
|
||||
try {
|
||||
if (!category.getTopic().equals("*")) { topicStart = "<topic name=\""+category.getTopic()+"\">"+NL; topicEnd = "</topic>"+NL;}
|
||||
if (!category.getThat().equals("*")) { thatStatement = "<that>"+category.getThat()+"</that>";}
|
||||
result = topicStart+"<category><pattern>"+category.getPattern()+"</pattern>"+thatStatement+NL+
|
||||
"<template>"+category.getTemplate()+"</template>"+NL+
|
||||
"</category>"+topicEnd;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* check to see if a pattern expression is valid in AIML 2.0
|
||||
*
|
||||
* @param pattern pattern expression
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean validPatternForm(String pattern) {
|
||||
if (pattern.length() < 1) {validationMessage += "Zero length. "; return false; }
|
||||
String[] words = pattern.split(" ");
|
||||
for (int i = 0; i < words.length; i++) {
|
||||
//String word = words[i];
|
||||
/*if (!(word.matches("[\\p{Hiragana}\\p{Katakana}\\p{Han}\\p{Latin}]*+") || word.equals("*") || word.equals("_"))) {
|
||||
log.info("Invalid pattern word "+word);
|
||||
return false;
|
||||
}*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public String validationMessage="";
|
||||
|
||||
/**
|
||||
* check for valid Category format
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean validate () {
|
||||
validationMessage = "";
|
||||
if (!validPatternForm(pattern)) {validationMessage += "Badly formatted <pattern>"; return false;}
|
||||
if (!validPatternForm(that)) {validationMessage += "Badly formatted <that>"; return false;}
|
||||
if (!validPatternForm(topic)) {validationMessage += "Badly formatted <topic>"; return false;}
|
||||
if (!AIMLProcessor.validTemplate(template)) {validationMessage += "Badly formatted <template>"; return false;}
|
||||
if (!filename.endsWith(".aiml")) {validationMessage += "Filename suffix should be .aiml"; return false;}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param activationCnt category activation count
|
||||
* @param pattern input pattern
|
||||
* @param that that pattern
|
||||
* @param topic topic pattern
|
||||
* @param template AIML template
|
||||
* @param filename AIML file name
|
||||
*/
|
||||
|
||||
public Category (int activationCnt, String pattern, String that, String topic, String template, String filename){
|
||||
if (MagicBooleans.fix_excel_csv) {
|
||||
pattern = Utilities.fixCSV(pattern);
|
||||
that = Utilities.fixCSV(that);
|
||||
topic = Utilities.fixCSV(topic);
|
||||
template = Utilities.fixCSV(template);
|
||||
filename = Utilities.fixCSV(filename);
|
||||
}
|
||||
this.pattern = pattern.trim().toUpperCase();
|
||||
this.that = that.trim().toUpperCase();
|
||||
this.topic = topic.trim().toUpperCase();
|
||||
this.template = template.replace("& ", " and "); // XML parser treats & badly
|
||||
this.filename = filename;
|
||||
this.activationCnt = activationCnt;
|
||||
matches = null;
|
||||
this.categoryNumber = categoryCnt++;
|
||||
// in Android, even this is too much for trace:
|
||||
//log.trace("Creating {} {}", categoryNumber, inputThatTopic());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param activationCnt category activation count
|
||||
* @param patternThatTopic string representing Pattern Path
|
||||
* @param template AIML template
|
||||
* @param filename AIML category
|
||||
*/
|
||||
public Category(int activationCnt, String patternThatTopic, String template, String filename){
|
||||
this(activationCnt,
|
||||
patternThatTopic.substring(0, patternThatTopic.indexOf("<THAT>")),
|
||||
patternThatTopic.substring(patternThatTopic.indexOf("<THAT>")+"<THAT>".length(), patternThatTopic.indexOf("<TOPIC>")),
|
||||
patternThatTopic.substring(patternThatTopic.indexOf("<TOPIC>")+"<TOPIC>".length(), patternThatTopic.length()), template, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* compare two categories for sorting purposes based on activation count
|
||||
*/
|
||||
public static Comparator<Category> ACTIVATION_COMPARATOR = new Comparator<Category>()
|
||||
{
|
||||
@Override
|
||||
public int compare(Category c1, Category c2)
|
||||
{
|
||||
return c2.getActivationCnt() - c1.getActivationCnt();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* compare two categories for sorting purposes based on alphabetical order of patterns
|
||||
*/
|
||||
public static Comparator<Category> PATTERN_COMPARATOR = new Comparator<Category>()
|
||||
{
|
||||
@Override
|
||||
public int compare(Category c1, Category c2)
|
||||
{
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(c1.inputThatTopic(), c2.inputThatTopic());
|
||||
}
|
||||
};
|
||||
/**
|
||||
* compare two categories for sorting purposes based on category index number
|
||||
*/
|
||||
public static Comparator<Category> CATEGORY_NUMBER_COMPARATOR = new Comparator<Category>()
|
||||
{
|
||||
@Override
|
||||
public int compare(Category c1, Category c2)
|
||||
{
|
||||
return c1.getCategoryNumber() - c2.getCategoryNumber();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
package org.alicebot.ab;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
|
||||
import org.alicebot.ab.utils.IOUtils;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/**
|
||||
* Class encapsulating a chat session between a bot and a client
|
||||
*/
|
||||
public class Chat {
|
||||
//private static final Logger log = LoggerFactory.getLogger(Chat.class);
|
||||
public Bot bot;
|
||||
public String customerId = MagicStrings.unknown_customer_id;
|
||||
public History<History> thatHistory= new History<History>("that");
|
||||
public History<String> requestHistory=new History<String>("request");
|
||||
public History<String> responseHistory=new History<String>("response");
|
||||
public History<String> inputHistory=new History<String>("input");
|
||||
public Predicates predicates = new Predicates();
|
||||
public static String matchTrace = "";
|
||||
public static boolean locationKnown = false;
|
||||
public static String longitude;
|
||||
public static String latitude;
|
||||
|
||||
/**
|
||||
* Constructor (defualt customer ID)
|
||||
*
|
||||
* @param bot the bot to chat with
|
||||
*/
|
||||
public Chat(Bot bot) {
|
||||
this(bot, "0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param bot bot to chat with
|
||||
* @param customerId unique customer identifier
|
||||
*/
|
||||
public Chat(Bot bot, String customerId) {
|
||||
this.customerId = customerId;
|
||||
this.bot = bot;
|
||||
History<String> contextThatHistory = new History<String>();
|
||||
contextThatHistory.add(MagicStrings.default_that);
|
||||
thatHistory.add(contextThatHistory);
|
||||
addPredicates();
|
||||
predicates.put("topic", MagicStrings.default_topic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all predicate defaults
|
||||
*/
|
||||
void addPredicates() {
|
||||
try {
|
||||
predicates.getPredicateDefaults(MagicStrings.config_path+"/predicates.txt") ;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Chat session terminal interaction
|
||||
*/
|
||||
public void chat () {
|
||||
BufferedWriter bw = null;
|
||||
String logFile = MagicStrings.log_path+"/log_"+customerId+".txt";
|
||||
try {
|
||||
//Construct the bw object
|
||||
bw = new BufferedWriter(new FileWriter(logFile, true)) ;
|
||||
String request="SET PREDICATES";
|
||||
String response = multisentenceRespond(request);
|
||||
while (!request.equals("quit")) {
|
||||
System.out.print("Human: ");
|
||||
request = IOUtils.readInputTextLine();
|
||||
response = multisentenceRespond(request);
|
||||
//info("Robot: "+response);
|
||||
bw.write("Human: "+request);
|
||||
bw.newLine();
|
||||
bw.write("Robot: "+response);
|
||||
bw.newLine();
|
||||
bw.flush();
|
||||
}
|
||||
bw.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bot response to a single sentence input given conversation context
|
||||
*
|
||||
* @param input client input
|
||||
* @param that bot's last sentence
|
||||
* @param topic current topic
|
||||
* @param contextThatHistory history of "that" values for this request/response interaction
|
||||
* @return bot's reply
|
||||
*/
|
||||
String respond(String input, String that, String topic, History contextThatHistory) {
|
||||
String response;
|
||||
inputHistory.add(input);
|
||||
response = AIMLProcessor.respond(input, that, topic, this);
|
||||
String normResponse = bot.preProcessor.normalize(response);
|
||||
// normResponse = JapaneseTokenizer.morphSentence(normResponse); //response.trim(); //
|
||||
String sentences[] = bot.preProcessor.sentenceSplit(normResponse);
|
||||
for (int i = 0; i < sentences.length; i++) {
|
||||
that = sentences[i];
|
||||
////info("That "+i+" '"+that+"'");
|
||||
if (that.trim().equals("")) that = MagicStrings.default_that;
|
||||
contextThatHistory.add(that);
|
||||
}
|
||||
return response.trim()+" ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bot response given an input and a history of "that" for the current conversational interaction
|
||||
*
|
||||
* @param input client input
|
||||
* @param contextThatHistory history of "that" values for this request/response interaction
|
||||
* @return bot's reply
|
||||
*/
|
||||
String respond(String input, History<String> contextThatHistory) {
|
||||
History hist = thatHistory.get(0);
|
||||
String that;
|
||||
if (hist == null) that = MagicStrings.default_that;
|
||||
else that = hist.getString(0);
|
||||
return respond(input, that, predicates.get("topic"), contextThatHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a compound response to a multiple-sentence request. "Multiple" means one or more.
|
||||
*
|
||||
* @param request client's multiple-sentence input
|
||||
* @return
|
||||
*/
|
||||
public String multisentenceRespond(String request) {
|
||||
String response="";
|
||||
matchTrace="";
|
||||
/*thatHistory.printHistory();
|
||||
inputHistory.printHistory();
|
||||
requestHistory.printHistory();
|
||||
responseHistory.printHistory();*/
|
||||
try {
|
||||
String norm = bot.preProcessor.normalize(request);
|
||||
// norm = JapaneseTokenizer.morphSentence(norm);
|
||||
//debug("normalized = "+norm);
|
||||
String sentences[] = bot.preProcessor.sentenceSplit(norm);
|
||||
History<String> contextThatHistory = new History<String>("contextThat");
|
||||
for (int i = 0; i < sentences.length; i++) {
|
||||
////info("Human: "+sentences[i]);
|
||||
AIMLProcessor.trace_count = 0;
|
||||
String reply = respond(sentences[i], contextThatHistory);
|
||||
response += " "+reply;
|
||||
////info("Robot: "+reply);
|
||||
}
|
||||
requestHistory.add(request);
|
||||
responseHistory.add(response);
|
||||
thatHistory.add(contextThatHistory);
|
||||
//if (MagicBooleans.trace_mode) //info(matchTrace);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return MagicStrings.error_bot_response;
|
||||
}
|
||||
|
||||
bot.writeLearnfIFCategories();
|
||||
return response.trim();
|
||||
}
|
||||
|
||||
|
||||
public static void setMatchTrace(String newMatchTrace) {
|
||||
matchTrace = newMatchTrace;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package org.alicebot.ab;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class is here to simulate a Contacts database for the purpose of testing contactaction.aiml
|
||||
*/
|
||||
public class Contact {
|
||||
//private static final Logger log = LoggerFactory.getLogger(Contact.class);
|
||||
public static int contactCount=0;
|
||||
public static HashMap<String, Contact> idContactMap = new HashMap<String, Contact>();
|
||||
public static HashMap<String, String> nameIdMap = new HashMap<String, String>();
|
||||
public String contactId;
|
||||
public String displayName;
|
||||
public String birthday;
|
||||
public HashMap<String, String> phones;
|
||||
public HashMap<String, String> emails;
|
||||
public static String multipleIds(String contactName) {
|
||||
String patternString = " ("+contactName.toUpperCase()+") ";
|
||||
while (patternString.contains(" ")) patternString = patternString.replace(" ", "(.*)");
|
||||
////info("Pattern='"+patternString+"'");
|
||||
Pattern pattern = Pattern.compile(patternString);
|
||||
Set<String> keys = nameIdMap.keySet();
|
||||
String result="";
|
||||
int idCount = 0;
|
||||
for (String key : keys) {
|
||||
Matcher m = pattern.matcher(key);
|
||||
if (m.find()) {
|
||||
result += nameIdMap.get(key.toUpperCase())+" ";
|
||||
idCount++;
|
||||
}
|
||||
}
|
||||
if (idCount <= 1) result = "false";
|
||||
return result.trim();
|
||||
}
|
||||
public static String contactId(String contactName) {
|
||||
String patternString = " "+contactName.toUpperCase()+" ";
|
||||
while (patternString.contains(" ")) patternString = patternString.replace(" ", ".*");
|
||||
////info("Pattern='"+patternString+"'");
|
||||
Pattern pattern = Pattern.compile(patternString);
|
||||
Set<String> keys = nameIdMap.keySet();
|
||||
String result="unknown";
|
||||
for (String key: keys) {
|
||||
Matcher m = pattern.matcher(key);
|
||||
if (m.find()) result = nameIdMap.get(key.toUpperCase())+" ";
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
public static String displayName(String id) {
|
||||
Contact c = idContactMap.get(id.toUpperCase());
|
||||
String result = "unknown";
|
||||
if (c != null) {
|
||||
result = c.displayName;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static String dialNumber(String type, String id) {
|
||||
String result = "unknown";
|
||||
Contact c = idContactMap.get(id.toUpperCase());
|
||||
if (c != null) {
|
||||
String dialNumber = c.phones.get(type.toUpperCase());
|
||||
if (dialNumber != null) result = dialNumber;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static String emailAddress(String type, String id) {
|
||||
String result = "unknown";
|
||||
Contact c = idContactMap.get(id.toUpperCase());
|
||||
if (c != null) {
|
||||
String emailAddress = c.emails.get(type.toUpperCase());
|
||||
if (emailAddress != null) result = emailAddress;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static String birthday(String id) {
|
||||
Contact c = idContactMap.get(id.toUpperCase());
|
||||
if (c == null) return "unknown";
|
||||
else return c.birthday;
|
||||
}
|
||||
public Contact (String displayName, String phoneType, String dialNumber, String emailType, String emailAddress, String birthday) {
|
||||
contactId = "ID"+contactCount;
|
||||
contactCount++;
|
||||
phones = new HashMap<String, String>();
|
||||
emails = new HashMap<String, String>();
|
||||
idContactMap.put(contactId.toUpperCase(), this);
|
||||
addPhone(phoneType, dialNumber);
|
||||
addEmail(emailType, emailAddress);
|
||||
addName(displayName);
|
||||
addBirthday(birthday);
|
||||
}
|
||||
|
||||
public void addPhone(String type, String dialNumber) {
|
||||
phones.put(type.toUpperCase(), dialNumber);
|
||||
}
|
||||
public void addEmail(String type, String emailAddress) {
|
||||
emails.put(type.toUpperCase(), emailAddress);
|
||||
}
|
||||
public void addName (String name) {
|
||||
displayName = name;
|
||||
nameIdMap.put(displayName.toUpperCase(), contactId);
|
||||
////info(nameIdMap.toString());
|
||||
}
|
||||
public void addBirthday(String birthday) {
|
||||
this.birthday = birthday;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,605 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The AIML Pattern matching algorithm and data structure.
|
||||
*
|
||||
*/
|
||||
public class Graphmaster {
|
||||
//private static final Logger log = LoggerFactory.getLogger(Graphmaster.class);
|
||||
public Bot bot;
|
||||
public final Nodemapper root;
|
||||
public int matchCount = 0;
|
||||
public int upgradeCnt = 0;
|
||||
public HashSet<String> vocabulary;
|
||||
public String resultNote = "";
|
||||
public int categoryCnt = 0;
|
||||
public static boolean enableShortCuts = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param bot the bot the graph belongs to.
|
||||
*/
|
||||
public Graphmaster (Bot bot) {
|
||||
root = new Nodemapper();
|
||||
this.bot = bot;
|
||||
vocabulary = new HashSet<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert input, that and topic to a single sentence having the form
|
||||
* {@code input <THAT> that <TOPIC> topic}
|
||||
*
|
||||
* @param input input (or input pattern)
|
||||
* @param that that (or that pattern)
|
||||
* @param topic topic (or topic pattern)
|
||||
* @return
|
||||
*/
|
||||
public static String inputThatTopic (String input, String that, String topic) {
|
||||
return input.trim()+" <THAT> "+that.trim()+" <TOPIC> "+topic.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* add an AIML category to this graph.
|
||||
*
|
||||
* @param category AIML Category
|
||||
*/
|
||||
public void addCategory (Category category) {
|
||||
Path p = Path.sentenceToPath(inputThatTopic(category.getPattern(), category.getThat(), category.getTopic()));
|
||||
addPath(p, category);
|
||||
categoryCnt++;
|
||||
}
|
||||
|
||||
boolean thatStarTopicStar(Path path) {
|
||||
String tail = Path.pathToSentence(path).trim();
|
||||
//log.info("thatStarTopicStar "+tail+" "+tail.equals("<THAT> * <TOPIC> *"));
|
||||
return tail.equals("<THAT> * <TOPIC> *");
|
||||
}
|
||||
void addSets (String type, Bot bot, Nodemapper node) {
|
||||
//log.info("adding Set "+type+" from "+bot.setMap);
|
||||
String typeName = Utilities.tagTrim(type, "SET").toLowerCase();
|
||||
//AIMLSet aimlSet;
|
||||
if (bot.setMap.containsKey(typeName)) {
|
||||
if (node.sets == null) node.sets = new ArrayList<String>();
|
||||
node.sets.add(typeName);
|
||||
// log.info("sets = "+node.sets);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* add a path to the graph from the root to a Category
|
||||
*
|
||||
* @param path Pattern path
|
||||
* @param category AIML category
|
||||
*/
|
||||
void addPath(Path path, Category category) {
|
||||
addPath(root, path, category);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* add a Path to the graph from a given node.
|
||||
* Shortcuts: Replace all instances of paths "<THAT> * <TOPIC> *" with a direct link to the matching category
|
||||
*
|
||||
* @param node starting node in graph
|
||||
* @param path Pattern path to be added
|
||||
* @param category AIML Category
|
||||
*/
|
||||
void addPath(Nodemapper node, Path path, Category category) {
|
||||
if (path == null) {
|
||||
node.category = category;
|
||||
node.height = 0;
|
||||
}
|
||||
else if (enableShortCuts && thatStarTopicStar(path)) {
|
||||
node.category = category;
|
||||
node.height = Math.min(4, node.height);
|
||||
node.shortCut = true;
|
||||
}
|
||||
else if (NodemapperOperator.containsKey(node, path.word)) {
|
||||
if (path.word.startsWith("<SET>")) addSets(path.word, bot, node);
|
||||
Nodemapper nextNode = NodemapperOperator.get(node, path.word);
|
||||
addPath(nextNode, path.next, category);
|
||||
int offset = 1;
|
||||
if (path.word.equals("#") || path.word.equals("^")) offset = 0;
|
||||
node.height = Math.min(offset + nextNode.height, node.height);
|
||||
}
|
||||
else {
|
||||
Nodemapper nextNode = new Nodemapper();
|
||||
if (path.word.startsWith("<SET>")) {
|
||||
addSets(path.word, bot, node);
|
||||
}
|
||||
if (node.key != null) {
|
||||
NodemapperOperator.upgrade(node);
|
||||
upgradeCnt++;
|
||||
}
|
||||
NodemapperOperator.put(node, path.word, nextNode);
|
||||
addPath(nextNode, path.next, category);
|
||||
int offset = 1;
|
||||
if (path.word.equals("#") || path.word.equals("^")) offset = 0;
|
||||
node.height = Math.min(offset + nextNode.height, node.height);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* test if category is already in graph
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean existsCategory(Category c) {
|
||||
return (findNode(c) != null);
|
||||
}
|
||||
/**
|
||||
* test if category is already in graph
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public Nodemapper findNode(Category c) {
|
||||
return findNode(c.getPattern(), c.getThat(), c.getTopic());
|
||||
}
|
||||
|
||||
/** Given an input pattern, that pattern and topic pattern, find the leaf node associated with this path.
|
||||
*
|
||||
* @param input input pattern
|
||||
* @param that that pattern
|
||||
* @param topic topic pattern
|
||||
* @return leaf node or null if no matching node is found
|
||||
*/
|
||||
public Nodemapper findNode(String input, String that, String topic) {
|
||||
Nodemapper result = findNode(root, Path.sentenceToPath(inputThatTopic(input, that, topic)));
|
||||
if (verbose) ;
|
||||
return result;
|
||||
}
|
||||
public static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Recursively find a leaf node given a starting node and a path.
|
||||
*
|
||||
* @param node string node
|
||||
* @param path string path
|
||||
* @return the leaf node or null if no leaf is found
|
||||
*/
|
||||
Nodemapper findNode(Nodemapper node, Path path) {
|
||||
if (path == null && node != null) {
|
||||
if (verbose) ;
|
||||
return node;
|
||||
}
|
||||
else if (Path.pathToSentence(path).trim().equals("<THAT> * <TOPIC> *") && node.shortCut && path.word.equals("<THAT>")) {
|
||||
if (verbose);
|
||||
return node;
|
||||
}
|
||||
else if (NodemapperOperator.containsKey(node, path.word)) {
|
||||
if (verbose) ;
|
||||
Nodemapper nextNode = NodemapperOperator.get(node, path.word.toUpperCase());
|
||||
return findNode(nextNode, path.next);
|
||||
}
|
||||
|
||||
else {
|
||||
if (verbose) ;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the matching leaf node given an input, that state and topic value
|
||||
*
|
||||
* @param input client input
|
||||
* @param that bot's last sentence
|
||||
* @param topic current topic
|
||||
* @return matching leaf node or null if no match is found
|
||||
*/
|
||||
public final Nodemapper match(String input, String that, String topic) {
|
||||
Nodemapper n = null;
|
||||
try {
|
||||
String inputThatTopic = inputThatTopic(input, that, topic);
|
||||
//log.info("Matching: "+inputThatTopic);
|
||||
Path p = Path.sentenceToPath(inputThatTopic);
|
||||
//p.print();
|
||||
n = match(p, inputThatTopic);
|
||||
if (MagicBooleans.trace_mode) {
|
||||
if (n != null) {
|
||||
//log.debug("Matched: "+n.category.inputThatTopic()+" "+n.category.getFilename());
|
||||
}
|
||||
else ;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
//log.info("Match: "+input);
|
||||
ex.printStackTrace();
|
||||
n = null;
|
||||
}
|
||||
if (MagicBooleans.trace_mode && Chat.matchTrace.length() < MagicNumbers.max_trace_length) {
|
||||
if (n != null) {
|
||||
Chat.setMatchTrace(Chat.matchTrace + n.category.inputThatTopic()+"\n");
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the matching leaf node given a path of the form "{@code input <THAT> that <TOPIC> topic}"
|
||||
* @param path
|
||||
* @param inputThatTopic
|
||||
* @return matching leaf node or null if no match is found
|
||||
*/
|
||||
final Nodemapper match(Path path, String inputThatTopic) {
|
||||
try {
|
||||
String[] inputStars = new String[MagicNumbers.max_stars];
|
||||
String[] thatStars = new String[MagicNumbers.max_stars];
|
||||
String[] topicStars = new String[MagicNumbers.max_stars];
|
||||
String starState = "inputStar";
|
||||
String matchTrace = "";
|
||||
Nodemapper n = match(path, root, inputThatTopic, starState, 0, inputStars, thatStars, topicStars, matchTrace);
|
||||
if (n != null) {
|
||||
StarBindings sb = new StarBindings();
|
||||
for (int i=0; inputStars[i] != null && i < MagicNumbers.max_stars; i++) sb.inputStars.add(inputStars[i]);
|
||||
for (int i=0; thatStars[i] != null && i < MagicNumbers.max_stars; i++) sb.thatStars.add(thatStars[i]);
|
||||
for (int i=0; topicStars[i] != null && i < MagicNumbers.max_stars; i++) sb.topicStars.add(topicStars[i]);
|
||||
n.starBindings = sb;
|
||||
}
|
||||
//if (!n.category.getPattern().contains("*")) log.info("adding match "+inputThatTopic);
|
||||
if (n != null) n.category.addMatch(inputThatTopic);
|
||||
return n;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Depth-first search of the graph for a matching leaf node.
|
||||
* At each node, the order of search is
|
||||
* 1. $WORD (high priority exact word match)
|
||||
* 2. # wildcard (zero or more word match)
|
||||
* 3. _ wildcard (one or more words match)
|
||||
* 4. WORD (exact word match)
|
||||
* 5. {@code <set></set>} (AIML Set match)
|
||||
* 6. shortcut (graph shortcut when that pattern = * and topic pattern = *)
|
||||
* 7. ^ wildcard (zero or more words match)
|
||||
* 8. * wildcard (one or more words match)
|
||||
*
|
||||
* @param path remaining path to be matched
|
||||
* @param node current search node
|
||||
* @param inputThatTopic original input, that and topic string
|
||||
* @param starState tells whether wildcards are in input pattern, that pattern or topic pattern
|
||||
* @param starIndex index of wildcard
|
||||
* @param inputStars array of input pattern wildcard matches
|
||||
* @param thatStars array of that pattern wildcard matches
|
||||
* @param topicStars array of topic pattern wildcard matches
|
||||
* @param matchTrace trace of match path for debugging purposes
|
||||
* @return matching leaf node or null if no match is found
|
||||
*/
|
||||
final Nodemapper match(Path path, Nodemapper node, String inputThatTopic, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
Nodemapper matchedNode;
|
||||
//log.info("Match: Height="+node.height+" Length="+path.length+" Path="+Path.pathToSentence(path));
|
||||
matchCount++;
|
||||
if ((matchedNode = nullMatch(path, node, matchTrace)) != null) return matchedNode;
|
||||
else if (path.length < node.height) {
|
||||
return null;}
|
||||
|
||||
else if ((matchedNode = dollarMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else if ((matchedNode = sharpMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else if ((matchedNode = underMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else if ((matchedNode = wordMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else if ((matchedNode = setMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else if ((matchedNode = shortCutMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else if ((matchedNode = caretMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else if ((matchedNode = starMatch(path, node, inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) return matchedNode;
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* print out match trace when search fails
|
||||
*
|
||||
* @param mode Which mode of search
|
||||
* @param trace Match trace info
|
||||
*/
|
||||
void fail (String mode, String trace) {
|
||||
// log.info("Match failed ("+mode+") "+trace);
|
||||
}
|
||||
|
||||
/**
|
||||
* a match is found if the end of the path is reached and the node is a leaf node
|
||||
*
|
||||
* @param path remaining path
|
||||
* @param node current search node
|
||||
* @param matchTrace trace of match for debugging purposes
|
||||
* @return matching leaf node or null if no match found
|
||||
*/
|
||||
final Nodemapper nullMatch(Path path, Nodemapper node, String matchTrace) {
|
||||
if (path == null && node != null && NodemapperOperator.isLeaf(node) && node.category != null) return node;
|
||||
else {
|
||||
fail("null", matchTrace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final Nodemapper shortCutMatch(Path path, Nodemapper node, String inputThatTopic, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
if (node != null && node.shortCut && path.word.equals("<THAT>") && node.category != null) {
|
||||
String tail = Path.pathToSentence(path).trim();
|
||||
//log.info("Shortcut tail = "+tail);
|
||||
String that = tail.substring(tail.indexOf("<THAT>")+"<THAT>".length(), tail.indexOf("<TOPIC>")).trim();
|
||||
String topic = tail.substring(tail.indexOf("<TOPIC>")+"<TOPIC>".length(), tail.length()).trim();
|
||||
//log.info("Shortcut that = "+that+" topic = "+topic);
|
||||
//log.info("Shortcut matched: "+node.category.inputThatTopic());
|
||||
thatStars[0] = that;
|
||||
topicStars[0] = topic;
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
fail("shortCut", matchTrace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final Nodemapper wordMatch(Path path, Nodemapper node, String inputThatTopic, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
Nodemapper matchedNode;
|
||||
try {
|
||||
String uword = path.word.toUpperCase();
|
||||
if (uword.equals("<THAT>")) {starIndex = 0; starState = "thatStar";}
|
||||
else if (uword.equals("<TOPIC>")) {starIndex = 0; starState = "topicStar";}
|
||||
//log.info("path.next= "+path.next+" node.get="+node.get(uword));
|
||||
matchTrace += "["+uword+","+uword+"]";
|
||||
if (path != null && NodemapperOperator.containsKey(node, uword) &&
|
||||
(matchedNode = match(path.next, NodemapperOperator.get(node, uword), inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) {
|
||||
return matchedNode;
|
||||
} else {
|
||||
fail("word", matchTrace);
|
||||
return null;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// log.info("wordMatch: "+Path.pathToSentence(path)+": "+ex);
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final Nodemapper dollarMatch(Path path, Nodemapper node, String inputThatTopic, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
String uword = "$"+path.word.toUpperCase();
|
||||
Nodemapper matchedNode;
|
||||
if (path != null && NodemapperOperator.containsKey(node, uword) && (matchedNode = match(path.next, NodemapperOperator.get(node, uword), inputThatTopic, starState, starIndex, inputStars, thatStars, topicStars, matchTrace)) != null) {
|
||||
return matchedNode;
|
||||
} else {
|
||||
fail("dollar", matchTrace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final Nodemapper starMatch(Path path, Nodemapper node, String input, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
return wildMatch(path, node, input, starState, starIndex, inputStars, thatStars, topicStars, "*", matchTrace);
|
||||
}
|
||||
final Nodemapper underMatch(Path path, Nodemapper node, String input, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
return wildMatch(path, node, input, starState, starIndex, inputStars, thatStars, topicStars, "_", matchTrace);
|
||||
}
|
||||
final Nodemapper caretMatch(Path path, Nodemapper node, String input, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
Nodemapper matchedNode;
|
||||
matchedNode = zeroMatch(path, node, input, starState, starIndex, inputStars, thatStars, topicStars, "^", matchTrace);
|
||||
if (matchedNode != null) return matchedNode;
|
||||
else return wildMatch(path, node, input, starState, starIndex, inputStars, thatStars, topicStars, "^", matchTrace);
|
||||
}
|
||||
final Nodemapper sharpMatch(Path path, Nodemapper node, String input, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
//log.info("Entering sharpMatch with path.word="+path.word); NodemapperOperator.printKeys(node);
|
||||
Nodemapper matchedNode;
|
||||
matchedNode = zeroMatch(path, node, input, starState, starIndex, inputStars, thatStars, topicStars, "#", matchTrace);
|
||||
if (matchedNode != null) return matchedNode;
|
||||
else
|
||||
return wildMatch(path, node, input, starState, starIndex, inputStars, thatStars, topicStars, "#", matchTrace);
|
||||
}
|
||||
final Nodemapper zeroMatch(Path path, Nodemapper node, String input, String starState, int starIndex,
|
||||
String[] inputStars, String[] thatStars, String[] topicStars, String wildcard, String matchTrace) {
|
||||
// log.info("Entering zeroMatch on "+path.word+" "+NodemapperOperator.get(node, wildcard));
|
||||
matchTrace += "["+wildcard+",]";
|
||||
if (path != null && NodemapperOperator.containsKey(node, wildcard)) {
|
||||
setStars(bot.properties.get(MagicStrings.null_star), starIndex, starState, inputStars, thatStars, topicStars);
|
||||
Nodemapper nextNode = NodemapperOperator.get(node, wildcard);
|
||||
return match(path, nextNode, input, starState, starIndex+1, inputStars, thatStars, topicStars, matchTrace);
|
||||
}
|
||||
else {
|
||||
fail("zero "+wildcard, matchTrace);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
final Nodemapper wildMatch(Path path, Nodemapper node, String input, String starState, int starIndex,
|
||||
String[] inputStars, String[] thatStars, String[] topicStars, String wildcard, String matchTrace) {
|
||||
Nodemapper matchedNode;
|
||||
if (path.word.equals("<THAT>") || path.word.equals("<TOPIC>")) {
|
||||
fail("wild1 "+wildcard, matchTrace);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if (path != null && NodemapperOperator.containsKey(node, wildcard)) {
|
||||
matchTrace += "["+wildcard+","+path.word+"]";
|
||||
String currentWord;
|
||||
String starWords;
|
||||
Path pathStart;
|
||||
currentWord = path.word;
|
||||
starWords = currentWord+" ";
|
||||
pathStart = path.next;
|
||||
Nodemapper nextNode = NodemapperOperator.get(node, wildcard);
|
||||
if (NodemapperOperator.isLeaf(nextNode) && !nextNode.shortCut) {
|
||||
matchedNode = nextNode;
|
||||
starWords = Path.pathToSentence(path);
|
||||
//log.info(starIndex+". starwords="+starWords);
|
||||
setStars(starWords, starIndex, starState, inputStars, thatStars, topicStars);
|
||||
return matchedNode;
|
||||
}
|
||||
else {
|
||||
for (path = pathStart; path != null && !currentWord.equals("<THAT>") && !currentWord.equals("<TOPIC>"); path = path.next) {
|
||||
matchTrace += "["+wildcard+","+path.word+"]";
|
||||
if ((matchedNode = match(path, nextNode, input, starState, starIndex + 1, inputStars, thatStars, topicStars, matchTrace)) != null) {
|
||||
setStars(starWords, starIndex, starState, inputStars, thatStars, topicStars);
|
||||
return matchedNode;
|
||||
}
|
||||
else {
|
||||
currentWord = path.word;
|
||||
starWords += currentWord + " ";
|
||||
}
|
||||
}
|
||||
fail("wild2 "+wildcard, matchTrace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
//log.info("wildMatch: "+Path.pathToSentence(path)+": "+ex);
|
||||
}
|
||||
fail("wild3 "+wildcard, matchTrace);
|
||||
return null;
|
||||
}
|
||||
|
||||
final Nodemapper setMatch(Path path, Nodemapper node, String input, String starState, int starIndex, String[] inputStars, String[] thatStars, String[] topicStars, String matchTrace) {
|
||||
if (node.sets == null || path.word.equals("<THAT>") || path.word.equals("<TOPIC>")) return null;
|
||||
//log.info("setMatch sets ="+node.sets);
|
||||
for (String setName : node.sets) {
|
||||
//log.info("setMatch trying type "+setName);
|
||||
Nodemapper nextNode = NodemapperOperator.get(node, "<SET>"+setName.toUpperCase()+"</SET>");
|
||||
AIMLSet aimlSet = bot.setMap.get(setName);
|
||||
//log.info(aimlSet.setName + "="+ aimlSet);
|
||||
Nodemapper matchedNode;
|
||||
String currentWord = path.word;
|
||||
String starWords = currentWord+" ";
|
||||
int length = 1;
|
||||
matchTrace += "[<set>"+setName+"</set>,"+path.word+"]";
|
||||
//log.info("setMatch starWords =\""+starWords+"\"");
|
||||
for (Path qath = path.next; qath != null && !currentWord.equals("<THAT>") && !currentWord.equals("<TOPIC>") && length <= aimlSet.maxLength; qath = qath.next) {
|
||||
//log.info("qath.word = "+qath.word);
|
||||
String phrase = bot.preProcessor.normalize(starWords.trim()).toUpperCase();
|
||||
//log.info("setMatch trying \""+phrase+"\" in "+setName);
|
||||
if (aimlSet.contains(phrase) && (matchedNode = match(qath, nextNode, input, starState, starIndex + 1, inputStars, thatStars, topicStars, matchTrace)) != null) {
|
||||
setStars(starWords, starIndex, starState, inputStars, thatStars, topicStars);
|
||||
//log.info("setMatch found "+phrase+" in "+setName);
|
||||
return matchedNode;
|
||||
}
|
||||
// else if (qath.word.equals("<THAT>") || qath.word.equals("<TOPIC>")) return null;
|
||||
else {
|
||||
length = length + 1;
|
||||
currentWord = qath.word;
|
||||
starWords += currentWord + " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
fail("set", matchTrace);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setStars(String starWords, int starIndex, String starState, String[] inputStars, String[] thatStars, String[] topicStars) {
|
||||
if (starIndex < MagicNumbers.max_stars) {
|
||||
starWords = starWords.trim();
|
||||
if (starState.equals("inputStar")) inputStars[starIndex] = starWords;
|
||||
else if (starState.equals("thatStar")) thatStars[starIndex] = starWords;
|
||||
else if (starState.equals("topicStar")) topicStars[starIndex] = starWords;
|
||||
}
|
||||
}
|
||||
public void printgraph () {
|
||||
printgraph(root, "");
|
||||
}
|
||||
void printgraph(Nodemapper node, String partial) {
|
||||
if (node == null) ;
|
||||
else {
|
||||
String template = "";
|
||||
if (NodemapperOperator.isLeaf(node) || node.shortCut) {
|
||||
template = Category.templateToLine(node.category.getTemplate());
|
||||
template = template.substring(0, Math.min(16, template.length()));
|
||||
if (node.shortCut) ;
|
||||
else ;
|
||||
}
|
||||
for (String key : NodemapperOperator.keySet(node)) {
|
||||
//log.info(key);
|
||||
printgraph(NodemapperOperator.get(node, key), partial+"("+NodemapperOperator.size(node)+"["+node.height+"])--"+key+"-->");
|
||||
}
|
||||
}
|
||||
}
|
||||
public ArrayList<Category> getCategories() {
|
||||
ArrayList<Category> categories = new ArrayList<Category>();
|
||||
getCategories(root, categories);
|
||||
//for (Category c : categories) log.info("getCategories: "+c.inputThatTopic()+" "+c.getTemplate());
|
||||
return categories;
|
||||
}
|
||||
void getCategories(Nodemapper node, ArrayList<Category> categories) {
|
||||
if (node == null) return;
|
||||
|
||||
else {
|
||||
//String template = "";
|
||||
if (NodemapperOperator.isLeaf(node) || node.shortCut) {
|
||||
if (node.category != null) categories.add(node.category); // node.category == null when the category is deleted.
|
||||
}
|
||||
for (String key : NodemapperOperator.keySet(node)) {
|
||||
//log.info(key);
|
||||
getCategories(NodemapperOperator.get(node, key), categories);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int leafCnt;
|
||||
int nodeCnt;
|
||||
long nodeSize;
|
||||
int singletonCnt;
|
||||
int shortCutCnt;
|
||||
int naryCnt;
|
||||
public void nodeStats() {
|
||||
leafCnt = 0;
|
||||
nodeCnt = 0;
|
||||
nodeSize = 0;
|
||||
singletonCnt = 0;
|
||||
shortCutCnt = 0;
|
||||
naryCnt = 0;
|
||||
nodeStatsGraph(root);
|
||||
resultNote = nodeCnt+" nodes "+singletonCnt+" singletons "+leafCnt+" leaves "+shortCutCnt+" shortcuts "+naryCnt+" n-ary "+nodeSize+" branches "+(float)nodeSize/(float)nodeCnt+" average branching ";
|
||||
// log.info(resultNote);
|
||||
}
|
||||
public void nodeStatsGraph(Nodemapper node) {
|
||||
if (node != null) {
|
||||
//log.info("Counting "+node.key+ " size="+NodemapperOperator.size(node));
|
||||
nodeCnt++;
|
||||
nodeSize += NodemapperOperator.size(node);
|
||||
if (NodemapperOperator.size(node) == 1) singletonCnt += 1;
|
||||
if (NodemapperOperator.isLeaf(node) && !node.shortCut) {
|
||||
leafCnt++;
|
||||
}
|
||||
if (NodemapperOperator.size(node) > 1) naryCnt += 1;
|
||||
if (node.shortCut) {shortCutCnt += 1;}
|
||||
for (String key : NodemapperOperator.keySet(node)) {
|
||||
nodeStatsGraph(NodemapperOperator.get(node, key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<String> getVocabulary () {
|
||||
vocabulary = new HashSet<String>();
|
||||
getBrainVocabulary(root);
|
||||
for (String set : bot.setMap.keySet()) vocabulary.addAll(bot.setMap.get(set));
|
||||
return vocabulary;
|
||||
}
|
||||
public void getBrainVocabulary(Nodemapper node) {
|
||||
if (node != null) {
|
||||
//log.info("Counting "+node.key+ " size="+NodemapperOperator.size(node));
|
||||
for (String key : NodemapperOperator.keySet(node)) {
|
||||
vocabulary.add(key);
|
||||
getBrainVocabulary(NodemapperOperator.get(node, key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package org.alicebot.ab;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//mport org.slf4j.LoggerFactory;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* History object to maintain history of input, that request and response
|
||||
*
|
||||
* @param <T> type of history object
|
||||
*/
|
||||
public class History<T> {
|
||||
//private static final Logger log = LoggerFactory.getLogger(History.class);
|
||||
private Object[] history;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Constructor with default history name
|
||||
*/
|
||||
public History () {
|
||||
this("unknown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with history name
|
||||
*
|
||||
* @param name name of history
|
||||
*/
|
||||
public History(String name) {
|
||||
this.name = name;
|
||||
history = new Object[MagicNumbers.max_history];
|
||||
}
|
||||
|
||||
/**
|
||||
* add an item to history
|
||||
*
|
||||
* @param item history item to add
|
||||
*/
|
||||
public void add(T item) {
|
||||
for (int i = MagicNumbers.max_history-1; i > 0; i--) {
|
||||
history[i] = history[i-1];
|
||||
}
|
||||
history[0] = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* get an item from history
|
||||
*
|
||||
* @param index history index
|
||||
* @return history item
|
||||
*/
|
||||
public T get (int index) {
|
||||
if (index < MagicNumbers.max_history) {
|
||||
if (history[index] == null) return null;
|
||||
else return (T)history[index];
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a String history item
|
||||
*
|
||||
* @param index history index
|
||||
* @return history item
|
||||
*/
|
||||
public String getString (int index) {
|
||||
if (index < MagicNumbers.max_history) {
|
||||
if (history[index] == null) return MagicStrings.unknown_history_item;
|
||||
else return (String)history[index];
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* print history
|
||||
*/
|
||||
public void printHistory() {
|
||||
int i;
|
||||
for (i = 0; get(i) != null; i++) {
|
||||
// log.info(name+"History "+(i+1)+" = "+get(i));
|
||||
// log.info("{}", String.valueOf(get(i).getClass()).contains("History"));
|
||||
if (String.valueOf(get(i).getClass()).contains("History")) ((History)get(i)).printHistory();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package org.alicebot.ab;
|
||||
|
||||
import org.joda.time.Days;
|
||||
import org.joda.time.Hours;
|
||||
import org.joda.time.Months;
|
||||
import org.joda.time.Years;
|
||||
import org.joda.time.chrono.GregorianChronology;
|
||||
import org.joda.time.chrono.LenientChronology;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Interval {
|
||||
//private static final Logger log = LoggerFactory.getLogger(Interval.class);
|
||||
public static void test () {
|
||||
String date1 = "23:59:59.00";
|
||||
String date2 = "12:00:00.00";
|
||||
String format = "HH:mm:ss.SS";
|
||||
int hours = getHoursBetween(date2, date1, format);
|
||||
// log.info("Hours = "+hours);
|
||||
date1 = "January 30, 2013";
|
||||
date2 = "August 2, 1960";
|
||||
format = "MMMMMMMMM dd, yyyy";
|
||||
int years = getYearsBetween(date2, date1, format);
|
||||
// log.info("Years = "+years);
|
||||
}
|
||||
// http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html
|
||||
public static int getHoursBetween(final String date1, final String date2, String format){
|
||||
try {
|
||||
final DateTimeFormatter fmt =
|
||||
DateTimeFormat
|
||||
.forPattern(format)
|
||||
.withChronology(
|
||||
LenientChronology.getInstance(
|
||||
GregorianChronology.getInstance()));
|
||||
return Hours.hoursBetween(
|
||||
fmt.parseDateTime(date1),
|
||||
fmt.parseDateTime(date2)
|
||||
).getHours();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public static int getYearsBetween(final String date1, final String date2, String format){
|
||||
try {
|
||||
final DateTimeFormatter fmt =
|
||||
DateTimeFormat
|
||||
.forPattern(format)
|
||||
.withChronology(
|
||||
LenientChronology.getInstance(
|
||||
GregorianChronology.getInstance()));
|
||||
return Years.yearsBetween(
|
||||
fmt.parseDateTime(date1),
|
||||
fmt.parseDateTime(date2)
|
||||
).getYears();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public static int getMonthsBetween(final String date1, final String date2, String format){
|
||||
try {
|
||||
final DateTimeFormatter fmt =
|
||||
DateTimeFormat
|
||||
.forPattern(format)
|
||||
.withChronology(
|
||||
LenientChronology.getInstance(
|
||||
GregorianChronology.getInstance()));
|
||||
return Months.monthsBetween(
|
||||
fmt.parseDateTime(date1),
|
||||
fmt.parseDateTime(date2)
|
||||
).getMonths();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public static int getDaysBetween(final String date1, final String date2, String format){
|
||||
try {
|
||||
final DateTimeFormatter fmt =
|
||||
DateTimeFormat
|
||||
.forPattern(format)
|
||||
.withChronology(
|
||||
LenientChronology.getInstance(
|
||||
GregorianChronology.getInstance()));
|
||||
return Days.daysBetween(
|
||||
fmt.parseDateTime(date1),
|
||||
fmt.parseDateTime(date2)
|
||||
).getDays();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package org.alicebot.ab;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
//import net.reduls.sanmoku.Morpheme;
|
||||
//import net.reduls.sanmoku.Tagger;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
//import org.atilika.kuromoji.Token;
|
||||
//import org.atilika.kuromoji.Tokenizer;
|
||||
|
||||
/**
|
||||
* Tokenize a Japanese language input by inserting spaces between words
|
||||
*
|
||||
* see http://atilika.org/
|
||||
*/
|
||||
public class JapaneseTokenizer {
|
||||
//private static final Logger log = LoggerFactory
|
||||
// .getLogger(JapaneseTokenizer.class);
|
||||
//static final Tokenizer tokenizer = Tokenizer.builder().build();
|
||||
static final Pattern tagPattern = Pattern.compile("(<.*>.*</.*>)|(<.*/>)");
|
||||
static Set<Character.UnicodeBlock> japaneseUnicodeBlocks = new HashSet<Character.UnicodeBlock>() {{
|
||||
add(Character.UnicodeBlock.HIRAGANA);
|
||||
add(Character.UnicodeBlock.KATAKANA);
|
||||
add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS);
|
||||
}};
|
||||
|
||||
|
||||
/*public static ArrayList<String> tokenize(String sentence) {
|
||||
ArrayList<String> result = new ArrayList<String>();
|
||||
//Tokenizer tokenizer = Tokenizer.builder().build();
|
||||
for (Token token : tokenizer.tokenize(sentence)) {
|
||||
result.add(token.getSurfaceForm());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static String buildFragment(String fragment) {
|
||||
ArrayList<String> tokens = tokenize(fragment);
|
||||
String result = "";
|
||||
for (String word : tokens) {
|
||||
result += " "+word;
|
||||
}
|
||||
return result.trim();
|
||||
}*/
|
||||
/* public static String morphSentence (String sentence) {
|
||||
|
||||
Matcher matcher = tagPattern.matcher(sentence);
|
||||
String result = "";
|
||||
while (matcher.find()) {
|
||||
int i = matcher.start();
|
||||
int j = matcher.end();
|
||||
|
||||
String prefix, tag;
|
||||
if (i > 0) prefix = sentence.substring(0, i-1); else prefix = "";
|
||||
tag = sentence.substring(i, j);
|
||||
result += " "+buildFragment(prefix)+" "+tag;
|
||||
if (j < sentence.length()) sentence = sentence.substring(j, sentence.length()); else sentence = "";
|
||||
System.out.print("Start index: " + matcher.start());
|
||||
System.out.print(" End index: " + matcher.end() + " ");
|
||||
log.info(matcher.group());
|
||||
}
|
||||
result += " "+buildFragment(sentence);
|
||||
while (result.contains("$ ")) result = result.replace("$ ", "$");
|
||||
while (result.contains(" ")) result = result.replace(" "," ");
|
||||
return result.trim();
|
||||
}*/ /*
|
||||
public static String morphSentence (String sentence) {
|
||||
String result = "";
|
||||
for (char c : sentence.toCharArray()) {
|
||||
if (japaneseUnicodeBlocks.contains(Character.UnicodeBlock.of(c))) {
|
||||
//log.info(c + " is a Japanese character");
|
||||
result = result+" "+c+" ";
|
||||
} else {
|
||||
//log.info(c + " is not a Japanese character");
|
||||
result = result + c;
|
||||
}
|
||||
}
|
||||
while (result.contains("$ ")) result = result.replace("$ ", "$");
|
||||
while (result.contains(" ")) result = result.replace(" "," ");
|
||||
return result.trim();
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tokenize a fragment of the input that contains only text
|
||||
*
|
||||
* @param fragment fragment of input containing only text and no XML tags
|
||||
* @return tokenized fragment
|
||||
*/
|
||||
// public static String buildFragment(String fragment) {
|
||||
|
||||
// String result = "";
|
||||
// for(Morpheme e : Tagger.parse(fragment)) {
|
||||
// result += e.surface+" ";
|
||||
//
|
||||
// log.info("Feature "+e.feature+" Surface="+e.surface);
|
||||
// }
|
||||
// return result.trim();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Morphological analysis of an input sentence that contains an AIML pattern.
|
||||
*
|
||||
* @param sentence
|
||||
* @return morphed sentence with one space between words, preserving XML markup and AIML $ operation
|
||||
*/
|
||||
// public static String morphSentence (String sentence) {
|
||||
// if (!MagicBooleans.jp_morphological_analysis) return sentence;
|
||||
// String result = "";
|
||||
// Matcher matcher = tagPattern.matcher(sentence);
|
||||
// while (matcher.find()) {
|
||||
// int i = matcher.start();
|
||||
// int j = matcher.end();
|
||||
// String prefix, tag;
|
||||
// if (i > 0) prefix = sentence.substring(0, i-1); else prefix = "";
|
||||
// tag = sentence.substring(i, j);
|
||||
// result += " "+buildFragment(prefix)+" "+tag;
|
||||
// if (j < sentence.length()) sentence = sentence.substring(j, sentence.length()); else sentence = "";
|
||||
// //System.out.print("Start index: " + matcher.start());
|
||||
// //System.out.print("End index: " + matcher.end() + " ");
|
||||
// //log.info(matcher.group());
|
||||
// }
|
||||
// result += " "+buildFragment(sentence);
|
||||
// while (result.contains("$ ")) result = result.replace("$ ", "$");
|
||||
// while (result.contains(" ")) result = result.replace(" "," ");
|
||||
// return result.trim();
|
||||
// }
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Global boolean values that control various actions in Program AB
|
||||
*/
|
||||
public class MagicBooleans {
|
||||
public static boolean trace_mode = true;
|
||||
public static boolean enable_external_sets = true;
|
||||
public static boolean enable_external_maps = true;
|
||||
public static boolean jp_morphological_analysis = false;
|
||||
public static boolean fix_excel_csv = true;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Integers with specific values in Program AB
|
||||
*
|
||||
*/
|
||||
public class MagicNumbers {
|
||||
public static int node_activation_cnt = 4;
|
||||
public static int node_size = 4;
|
||||
public static int displayed_input_sample_size = 6;
|
||||
public static int max_history = 32;
|
||||
public static int max_stars = 1000;
|
||||
public static int max_graph_height = 100000;
|
||||
public static int max_substitutions = 10000;
|
||||
public static int max_recursion = 512;
|
||||
public static int max_trace_length = 2048;
|
||||
public static int max_loops = 10000;
|
||||
public static int estimated_brain_size = 5000;
|
||||
public static int max_natural_number_digits = 10000;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Global values for many strings in Program AB
|
||||
*/
|
||||
public class MagicStrings {
|
||||
// General global strings
|
||||
public static String programNameVersion = "Program AB 0.0.4.3 beta -- AI Foundation Reference AIML 2.0 implementation";
|
||||
public static String comment = "removed some recursion from Path";
|
||||
public static String aimlif_split_char = ",";
|
||||
public static String default_bot = "super";
|
||||
public static String default_language = "EN";
|
||||
public static String aimlif_split_char_name = "\\#Comma";
|
||||
public static String aimlif_file_suffix = ".csv";
|
||||
public static String ab_sample_file = "sample.txt";
|
||||
// <sraix> defaults
|
||||
public static String pannous_api_key = "guest";
|
||||
public static String pannous_login = "test-user";
|
||||
public static String sraix_failed = "SRAIXFAILED";
|
||||
public static String sraix_no_hint = "nohint";
|
||||
public static String sraix_event_hint = "event";
|
||||
public static String sraix_pic_hint = "pic";
|
||||
// AIML files
|
||||
public static String unknown_aiml_file = "unknown_aiml_file.aiml";
|
||||
public static String deleted_aiml_file = "deleted.aiml";
|
||||
public static String learnf_aiml_file = "learnf.aiml";
|
||||
public static String null_aiml_file = "null.aiml";
|
||||
public static String inappropriate_aiml_file = "inappropriate.aiml";
|
||||
public static String profanity_aiml_file = "profanity.aiml";
|
||||
public static String insult_aiml_file = "insults.aiml";
|
||||
public static String reductions_update_aiml_file = "reductions_update.aiml";
|
||||
public static String predicates_aiml_file = "client_profile.aiml";
|
||||
public static String update_aiml_file = "update.aiml";
|
||||
public static String personality_aiml_file = "personality.aiml";
|
||||
public static String sraix_aiml_file = "sraix.aiml";
|
||||
public static String oob_aiml_file = "oob.aiml";
|
||||
public static String unfinished_aiml_file = "unfinished.aiml";
|
||||
// filter responses
|
||||
public static String inappropriate_filter = "FILTER INAPPROPRIATE";
|
||||
public static String profanity_filter = "FILTER PROFANITY";
|
||||
public static String insult_filter = "FILTER INSULT";
|
||||
// default templates
|
||||
public static String deleted_template = "deleted";
|
||||
public static String unfinished_template = "unfinished";
|
||||
// AIML defaults
|
||||
public static String unknown_history_item = "unknown";
|
||||
public static String default_bot_response = "I have no answer for that.";
|
||||
public static String error_bot_response = "Something is wrong with my brain.";
|
||||
public static String schedule_error = "I'm unable to schedule that event.";
|
||||
public static String system_failed = "Failed to execute system command.";
|
||||
public static String unknown_predicate_value = "unknown";
|
||||
public static String unknown_property_value = "unknown";
|
||||
public static String unknown_map_value = "unknown";
|
||||
public static String unknown_customer_id = "unknown";
|
||||
public static String unknown_bot_name = "unknown";
|
||||
public static String default_that = "unknown";
|
||||
public static String default_topic = "unknown";
|
||||
public static String template_failed = "Template failed.";
|
||||
public static String too_much_recursion = "Too much recursion in AIML";
|
||||
public static String too_much_looping = "Too much looping in AIML";
|
||||
public static String blank_template = "blank template";
|
||||
public static String null_input = "NORESP";
|
||||
public static String null_star = "nullstar";
|
||||
// sets and maps
|
||||
public static String set_member_string = "ISA";
|
||||
public static String remote_map_key = "external";
|
||||
public static String remote_set_key = "external";
|
||||
public static String natural_number_set_name = "number";
|
||||
public static String map_successor = "successor";
|
||||
public static String map_predecessor = "predecessor";
|
||||
// paths
|
||||
public static String root_path = "c:/ab";
|
||||
public static String bot_path = root_path+"/bots";
|
||||
public static String bot_name_path = bot_path+"/super";
|
||||
public static String aimlif_path = bot_path+"/aimlif";
|
||||
public static String aiml_path = bot_path+"/aiml";
|
||||
public static String config_path = bot_path+"/config";
|
||||
public static String log_path = bot_path+"/log";
|
||||
public static String sets_path = bot_path+"/sets";
|
||||
public static String maps_path = bot_path+"/maps";
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package org.alicebot.ab;
|
||||
|
||||
import org.alicebot.ab.utils.MemoryUtils;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Memory statistics for program instrumentation
|
||||
*
|
||||
*/
|
||||
public class MemStats {
|
||||
//private static final Logger log = LoggerFactory.getLogger(MemStats.class);
|
||||
public static long prevHeapSize = 0;
|
||||
|
||||
/**
|
||||
* print out some statistics about heap size
|
||||
*/
|
||||
public static void memStats () {
|
||||
// Get current size of heap in bytes
|
||||
long heapSize = MemoryUtils.totalMemory();
|
||||
|
||||
// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
|
||||
// Any attempt will result in an OutOfMemoryException.
|
||||
long heapMaxSize = MemoryUtils.maxMemory();
|
||||
|
||||
// Get amount of free memory within the heap in bytes. This size will increase
|
||||
// after garbage collection and decrease as new objects are created.
|
||||
long heapFreeSize = MemoryUtils.freeMemory();
|
||||
long diff = heapSize - prevHeapSize;
|
||||
prevHeapSize = heapSize;
|
||||
// log.info("Heap "+heapSize+" MaxSize "+heapMaxSize+" Free "+heapFreeSize+" Diff "+diff);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Nodemapper data structure. In order to minimize memory overhead this class has no methods.
|
||||
* Operations on Nodemapper objects are performed by NodemapperOperator class
|
||||
*/
|
||||
public class Nodemapper {
|
||||
/* public static int idCnt=0;
|
||||
public int id;*/
|
||||
public Category category = null;
|
||||
public int height = MagicNumbers.max_graph_height;
|
||||
public StarBindings starBindings = null;
|
||||
public HashMap<String, Nodemapper> map = null;
|
||||
public String key = null;
|
||||
public Nodemapper value = null;
|
||||
public boolean shortCut = false;
|
||||
public ArrayList<String> sets;
|
||||
/* public Nodemapper () {
|
||||
id = idCnt++;
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
public class NodemapperOperator {
|
||||
//private static final Logger log = LoggerFactory
|
||||
// .getLogger(NodemapperOperator.class);
|
||||
/**
|
||||
* number of branches from node
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
* @return number of branches
|
||||
*/
|
||||
public static int size(Nodemapper node) {
|
||||
HashSet set = new HashSet();
|
||||
if (node.shortCut) set.add("<THAT>");
|
||||
if (node.key != null) set.add(node.key);
|
||||
if (node.map != null) set.addAll(node.map.keySet());
|
||||
return set.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* insert a new link from this node to another, by adding a key, value pair
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
* @param key key word
|
||||
* @param value word maps to this next node
|
||||
*/
|
||||
public static void put(Nodemapper node, String key, Nodemapper value) {
|
||||
if (node.map != null) {
|
||||
node.map.put(key, value);
|
||||
}
|
||||
else { // node.type == unary_node_mapper
|
||||
node.key = key;
|
||||
node.value = value;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the node linked to this one by the word key
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
* @param key key word to map
|
||||
* @return the mapped node or null if the key is not found
|
||||
*/
|
||||
public static Nodemapper get(Nodemapper node, String key) {
|
||||
if (node.map != null) {
|
||||
return node.map.get(key);
|
||||
}
|
||||
else {// node.type == unary_node_mapper
|
||||
if (key.equals(node.key)) return node.value;
|
||||
else return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether a node contains a particular key
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
* @param key key to test
|
||||
* @return true or false
|
||||
*/
|
||||
public static boolean containsKey(Nodemapper node, String key) {
|
||||
//log.info("containsKey: Node="+node+" Map="+node.map);
|
||||
if (node.map != null) {
|
||||
return node.map.containsKey(key) ;
|
||||
}
|
||||
else {// node.type == unary_node_mapper
|
||||
if (key.equals(node.key)) return true;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* print all node keys
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
*/
|
||||
public static void printKeys (Nodemapper node) {
|
||||
Set set = keySet(node);
|
||||
Iterator iter = set.iterator();
|
||||
while (iter.hasNext()) {
|
||||
// log.info("" + iter.next());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get key set of a node
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
* @return set of keys
|
||||
*/
|
||||
public static Set<String> keySet(Nodemapper node) {
|
||||
if (node.map != null) {
|
||||
return node.map.keySet();
|
||||
}
|
||||
else {// node.type == unary_node_mapper
|
||||
Set set = new HashSet<String>();
|
||||
if (node.key != null) set.add(node.key);
|
||||
return set;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* test whether a node is a leaf
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
* @return true or false
|
||||
*/
|
||||
public static boolean isLeaf(Nodemapper node) {
|
||||
return (node.category != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* upgrade a node from a singleton to a multi-way map
|
||||
*
|
||||
* @param node Nodemapper object
|
||||
*/
|
||||
public static void upgrade(Nodemapper node) {
|
||||
//log.info("Upgrading "+node.id);
|
||||
//node.type = MagicNumbers.hash_node_mapper;
|
||||
node.map = new HashMap<String, Nodemapper>();
|
||||
node.map.put(node.key, node.value);
|
||||
node.key = null;
|
||||
node.value = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* This is just a stub to make the contactaction.aiml file work on a PC
|
||||
* with some extension tags that are defined for mobile devices.
|
||||
*/
|
||||
public class PCAIMLProcessorExtension implements AIMLProcessorExtension {
|
||||
//private static final Logger log = LoggerFactory
|
||||
// .getLogger(PCAIMLProcessorExtension.class);
|
||||
public Set<String> extensionTagNames = Utilities.stringSet("contactid","multipleids","displayname","dialnumber","emailaddress","contactbirthday","addinfo");
|
||||
@Override
|
||||
public Set <String> extensionTagSet() {
|
||||
return extensionTagNames;
|
||||
}
|
||||
private String newContact(Node node, ParseState ps) {
|
||||
NodeList childList = node.getChildNodes();
|
||||
String emailAddress="unknown";
|
||||
String displayName="unknown";
|
||||
String dialNumber="unknown";
|
||||
String emailType="unknown";
|
||||
String phoneType="unknown";
|
||||
String birthday="unknown";
|
||||
for (int i = 0; i < childList.getLength(); i++) {
|
||||
if (childList.item(i).getNodeName().equals("birthday")) {
|
||||
birthday = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
if (childList.item(i).getNodeName().equals("phonetype")) {
|
||||
phoneType = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
if (childList.item(i).getNodeName().equals("emailtype")) {
|
||||
emailType = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
if (childList.item(i).getNodeName().equals("dialnumber")) {
|
||||
dialNumber = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
if (childList.item(i).getNodeName().equals("displayname")) {
|
||||
displayName = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
if (childList.item(i).getNodeName().equals("emailaddress")) {
|
||||
emailAddress = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
}
|
||||
// log.info("Adding new contact "+displayName+" "+phoneType+" "+dialNumber+" "+emailType+" "+emailAddress+" "+birthday);
|
||||
Contact contact = new Contact(displayName, phoneType, dialNumber, emailType, emailAddress, birthday);
|
||||
return "";
|
||||
}
|
||||
private String contactId(Node node, ParseState ps) {
|
||||
String displayName = AIMLProcessor.evalTagContent(node, ps, null);
|
||||
String result = Contact.contactId(displayName);
|
||||
//log.info("contactId("+displayName+")="+result);
|
||||
return result;
|
||||
}
|
||||
private String multipleIds(Node node, ParseState ps){
|
||||
String contactName = AIMLProcessor.evalTagContent(node, ps, null);
|
||||
String result = Contact.multipleIds(contactName);
|
||||
//log.info("multipleIds("+contactName+")="+result);
|
||||
return result;
|
||||
}
|
||||
private String displayName(Node node, ParseState ps){
|
||||
String id = AIMLProcessor.evalTagContent(node, ps, null);
|
||||
String result = Contact.displayName(id);
|
||||
//log.info("displayName("+id+")="+result);
|
||||
return result;
|
||||
}
|
||||
private String dialNumber(Node node, ParseState ps) {
|
||||
NodeList childList = node.getChildNodes();
|
||||
String id="unknown";
|
||||
String type="unknown";
|
||||
for (int i = 0; i < childList.getLength(); i++) {
|
||||
if (childList.item(i).getNodeName().equals("id")) {
|
||||
id = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
if (childList.item(i).getNodeName().equals("type")) {
|
||||
type = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
}
|
||||
String result = Contact.dialNumber(type, id);
|
||||
//log.info("dialNumber("+id+")="+result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private String emailAddress(Node node, ParseState ps){
|
||||
NodeList childList = node.getChildNodes();
|
||||
String id="unknown";
|
||||
String type="unknown";
|
||||
for (int i = 0; i < childList.getLength(); i++) {
|
||||
if (childList.item(i).getNodeName().equals("id")) {
|
||||
id = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
if (childList.item(i).getNodeName().equals("type")) {
|
||||
type = AIMLProcessor.evalTagContent(childList.item(i), ps, null);
|
||||
}
|
||||
}
|
||||
String result = Contact.emailAddress(type, id);
|
||||
//log.info("emailAddress("+id+")="+result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private String contactBirthday(Node node, ParseState ps){
|
||||
String id = AIMLProcessor.evalTagContent(node, ps, null);
|
||||
String result = Contact.birthday(id);
|
||||
//log.info("birthday("+id+")="+result);
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public String recursEval(Node node, ParseState ps) {
|
||||
try {
|
||||
String nodeName = node.getNodeName();
|
||||
if (nodeName.equals("contactid"))
|
||||
return contactId(node, ps);
|
||||
else if (nodeName.equals("multipleids"))
|
||||
return multipleIds(node, ps);
|
||||
else if (nodeName.equals("dialnumber"))
|
||||
return dialNumber(node, ps);
|
||||
else if (nodeName.equals("addinfo"))
|
||||
return newContact(node, ps);
|
||||
else if (nodeName.equals("displayname"))
|
||||
return displayName(node, ps);
|
||||
else if (nodeName.equals("emailaddress"))
|
||||
return emailAddress(node, ps);
|
||||
else if (nodeName.equals("contactbirthday"))
|
||||
return contactBirthday(node, ps) ;
|
||||
else return (AIMLProcessor.genericXML(node, ps));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/**
|
||||
ParseState is a helper class for AIMLProcessor
|
||||
*/
|
||||
public class ParseState {
|
||||
public Nodemapper leaf;
|
||||
public String input;
|
||||
public String that;
|
||||
public String topic;
|
||||
public Chat chatSession;
|
||||
public int depth;
|
||||
public Predicates vars;
|
||||
|
||||
/**
|
||||
* Constructor - class has public members
|
||||
*
|
||||
* @param depth depth in parse tree
|
||||
* @param chatSession client session
|
||||
* @param input client input
|
||||
* @param that bot's last sentence
|
||||
* @param topic current topic
|
||||
* @param leaf node containing the category processed
|
||||
*/
|
||||
public ParseState(int depth, Chat chatSession, String input, String that, String topic, Nodemapper leaf) {
|
||||
this.chatSession = chatSession;
|
||||
this.input = input;
|
||||
this.that = that;
|
||||
this.topic = topic;
|
||||
this.leaf = leaf;
|
||||
this.depth = depth; // to prevent runaway recursion
|
||||
this.vars = new Predicates();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package org.alicebot.ab;
|
||||
import java.util.ArrayList;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Linked list representation of Pattern Path and Input Path
|
||||
*/
|
||||
public class Path extends ArrayList<String>{
|
||||
//private static final Logger log = LoggerFactory.getLogger(Path.class);
|
||||
public String word;
|
||||
public Path next;
|
||||
public int length;
|
||||
|
||||
/**
|
||||
* Constructor - class has public members
|
||||
*/
|
||||
private Path() {
|
||||
next = null;
|
||||
word = null;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a sentence (a string consisting of words separated by single spaces) into a Path
|
||||
*
|
||||
* @param sentence sentence to convert
|
||||
* @return sentence in Path form
|
||||
*/
|
||||
public static Path sentenceToPath(String sentence) {
|
||||
sentence = sentence.trim();
|
||||
return arrayToPath(sentence.split(" "));
|
||||
}
|
||||
|
||||
/**
|
||||
* The inverse of sentenceToPath
|
||||
*
|
||||
* @param path input path
|
||||
* @return sentence
|
||||
*/
|
||||
public static String pathToSentence (Path path) {
|
||||
String result="";
|
||||
for (Path p = path; p != null; p = p.next) {
|
||||
result = result+" "+path.word;
|
||||
}
|
||||
return result.trim();
|
||||
/* if (path == null) return "";
|
||||
else return path.word+" "+pathToSentence(path.next);*/
|
||||
}
|
||||
|
||||
/**
|
||||
* convert an array of strings to a Path
|
||||
*
|
||||
* @param array array of strings
|
||||
* @return sequence of strings as Path
|
||||
*/
|
||||
private static Path arrayToPath(String[] array) {
|
||||
Path tail = null;
|
||||
Path head = null;
|
||||
for (int i = array.length-1; i >= 0; i--) {
|
||||
head = new Path();
|
||||
head.word = array[i];
|
||||
head.next = tail;
|
||||
if (tail == null) head.length = 1;
|
||||
else head.length = tail.length + 1;
|
||||
tail = head;
|
||||
}
|
||||
return head;
|
||||
//return arrayToPath(array, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* recursively convert an array to a Path
|
||||
*
|
||||
* @param array array of strings
|
||||
* @param index array index
|
||||
* @return Path form
|
||||
*/
|
||||
private static Path arrayToPath(String[] array, int index) {
|
||||
if (index >= array.length) return null;
|
||||
else {
|
||||
Path newPath = new Path();
|
||||
newPath.word = array[index];
|
||||
newPath.next = arrayToPath(array, index+1);
|
||||
if (newPath.next == null) newPath.length = 1;
|
||||
else newPath.length = newPath.next.length + 1;
|
||||
return newPath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* print a Path
|
||||
*/
|
||||
public void print() {
|
||||
String result = "";
|
||||
for (Path p = this; p != null; p = p.next) {
|
||||
result += p.word+",";
|
||||
}
|
||||
if (result.endsWith(",")) result = result.substring(0, result.length()-1);
|
||||
// log.info(result);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* AIML Preprocessor and substitutions
|
||||
*/
|
||||
public class PreProcessor {
|
||||
//private static final Logger log = LoggerFactory
|
||||
//.getLogger(PreProcessor.class);
|
||||
public int normalCount = 0;
|
||||
public int denormalCount = 0;
|
||||
public int personCount = 0;
|
||||
public int person2Count = 0;
|
||||
public int genderCount = 0;
|
||||
public String[] normalSubs = new String[MagicNumbers.max_substitutions];
|
||||
public Pattern[] normalPatterns = new Pattern[MagicNumbers.max_substitutions];
|
||||
public String[] denormalSubs = new String[MagicNumbers.max_substitutions];
|
||||
public Pattern[] denormalPatterns = new Pattern[MagicNumbers.max_substitutions];
|
||||
public String[] personSubs = new String[MagicNumbers.max_substitutions];
|
||||
public Pattern[] personPatterns = new Pattern[MagicNumbers.max_substitutions];
|
||||
public String[] person2Subs = new String[MagicNumbers.max_substitutions];
|
||||
public Pattern[] person2Patterns = new Pattern[MagicNumbers.max_substitutions];
|
||||
public String[] genderSubs = new String[MagicNumbers.max_substitutions];
|
||||
public Pattern[] genderPatterns = new Pattern[MagicNumbers.max_substitutions];
|
||||
|
||||
/**
|
||||
* Constructor given bot
|
||||
*
|
||||
* @param bot AIML bot
|
||||
*/
|
||||
public PreProcessor (Bot bot) {
|
||||
normalCount = readSubstitutions(MagicStrings.config_path+"/normal.txt", normalPatterns, normalSubs);
|
||||
denormalCount = readSubstitutions(MagicStrings.config_path+"/denormal.txt", denormalPatterns, denormalSubs);
|
||||
personCount = readSubstitutions(MagicStrings.config_path +"/person.txt", personPatterns, personSubs);
|
||||
person2Count = readSubstitutions(MagicStrings.config_path +"/person2.txt", person2Patterns, person2Subs);
|
||||
genderCount = readSubstitutions(MagicStrings.config_path +"/gender.txt", genderPatterns, genderSubs);
|
||||
// log.info("Preprocessor: "+normalCount+" norms "+personCount+" persons "+person2Count+" person2 ");
|
||||
}
|
||||
|
||||
/**
|
||||
* apply normalization substitutions to a request
|
||||
*
|
||||
* @param request client input
|
||||
* @return normalized client input
|
||||
*/
|
||||
public String normalize (String request) {
|
||||
return substitute(request, normalPatterns, normalSubs, normalCount);
|
||||
}
|
||||
/**
|
||||
* apply denormalization substitutions to a request
|
||||
*
|
||||
* @param request client input
|
||||
* @return normalized client input
|
||||
*/
|
||||
public String denormalize (String request) {
|
||||
return substitute(request, denormalPatterns, denormalSubs, denormalCount);
|
||||
}
|
||||
/**
|
||||
* personal pronoun substitution for {@code <person></person>} tag
|
||||
* @param input sentence
|
||||
* @return sentence with pronouns swapped
|
||||
*/
|
||||
public String person (String input) {
|
||||
return substitute(input, personPatterns, personSubs, personCount);
|
||||
|
||||
}
|
||||
/**
|
||||
* personal pronoun substitution for {@code <person2></person2>} tag
|
||||
* @param input sentence
|
||||
* @return sentence with pronouns swapped
|
||||
*/
|
||||
public String person2 (String input) {
|
||||
return substitute(input, person2Patterns, person2Subs, person2Count);
|
||||
|
||||
}
|
||||
/**
|
||||
* personal pronoun substitution for {@code <gender>} tag
|
||||
* @param input sentence
|
||||
* @return sentence with pronouns swapped
|
||||
*/
|
||||
public String gender (String input) {
|
||||
return substitute(input, genderPatterns, genderSubs, genderCount);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a sequence of subsitutions to an input string
|
||||
*
|
||||
* @param request input request
|
||||
* @param patterns array of patterns to match
|
||||
* @param subs array of substitution values
|
||||
* @param count number of patterns and substitutions
|
||||
* @return result of applying substitutions to input
|
||||
*/
|
||||
String substitute(String request, Pattern[] patterns, String[] subs, int count) {
|
||||
String result = " "+request+" ";
|
||||
try {
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
String replacement = subs[i];
|
||||
Pattern p = patterns[i];
|
||||
Matcher m = p.matcher(result);
|
||||
//log.info(i+" "+patterns[i].pattern()+"-->"+subs[i]);
|
||||
if (m.find()) {
|
||||
//log.info(m.group());
|
||||
result = m.replaceAll(replacement);
|
||||
}
|
||||
|
||||
//log.info(result);
|
||||
}
|
||||
while (result.contains(" ")) result = result.replace(" "," ");
|
||||
result = result.trim();
|
||||
//log.info("Normalized: "+result);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* read substitutions from input stream
|
||||
*
|
||||
* @param in input stream
|
||||
* @param patterns array of patterns
|
||||
* @param subs array of substitution values
|
||||
* @return number of patterns substitutions read
|
||||
*/
|
||||
public int readSubstitutionsFromInputStream(InputStream in, Pattern[] patterns, String[] subs) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
int subCount = 0;
|
||||
try {
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
//log.info(strLine);
|
||||
strLine = strLine.trim();
|
||||
Pattern pattern = Pattern.compile("\"(.*?)\",\"(.*?)\"", Pattern.DOTALL);
|
||||
Matcher matcher = pattern.matcher(strLine);
|
||||
if (matcher.find() && subCount < MagicNumbers.max_substitutions) {
|
||||
subs[subCount] = matcher.group(2);
|
||||
String quotedPattern = Pattern.quote(matcher.group(1));
|
||||
//log.info("quoted pattern="+quotedPattern);
|
||||
patterns[subCount] = Pattern.compile(quotedPattern, Pattern.CASE_INSENSITIVE);
|
||||
subCount++;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return subCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* read substitutions from a file
|
||||
*
|
||||
* @param filename name of substitution file
|
||||
* @param patterns array of patterns
|
||||
* @param subs array of substitution values
|
||||
* @return number of patterns and substitutions read
|
||||
*/
|
||||
int readSubstitutions(String filename, Pattern[] patterns, String[] subs) {
|
||||
int subCount = 0;
|
||||
try{
|
||||
|
||||
// Open the file that is the first
|
||||
// command line parameter
|
||||
File file = new File(filename);
|
||||
if (file.exists()) {
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object of DataInputStream
|
||||
subCount = readSubstitutionsFromInputStream(fstream, patterns, subs);
|
||||
//Close the input stream
|
||||
fstream.close();
|
||||
}
|
||||
}catch (Exception e){//Catch exception if any
|
||||
// log.error("Cannot read substitutions from '" + filename + "': " + e, e);
|
||||
}
|
||||
return (subCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split an input into an array of sentences based on sentence-splitting characters.
|
||||
*
|
||||
* @param line input text
|
||||
* @return array of sentences
|
||||
*/
|
||||
public String[] sentenceSplit(String line) {
|
||||
line = line.replace("。",".");
|
||||
line = line.replace("?","?");
|
||||
line = line.replace("ï¼<EFBFBD>","!");
|
||||
//log.info("Sentence split "+line);
|
||||
String result[] = line.split("[\\.!\\?]");
|
||||
for (int i = 0; i < result.length; i++) result[i] = result[i].trim();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* normalize a file consisting of sentences, one sentence per line.
|
||||
*
|
||||
* @param infile input file
|
||||
* @param outfile output file to write results
|
||||
*/
|
||||
public void normalizeFile (String infile, String outfile) {
|
||||
try{
|
||||
BufferedWriter bw = null;
|
||||
FileInputStream fstream = new FileInputStream(infile);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
|
||||
bw = new BufferedWriter(new FileWriter(outfile)) ;
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
strLine = normalize(strLine); //.toUpperCase();
|
||||
bw.write(strLine);
|
||||
bw.newLine();
|
||||
}
|
||||
bw.close();
|
||||
br.close();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Manage client predicates
|
||||
*
|
||||
*/
|
||||
public class Predicates extends HashMap<String, String> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
//private static final Logger log = LoggerFactory.getLogger(Predicates.class);
|
||||
|
||||
|
||||
/**
|
||||
* save a predicate value
|
||||
*
|
||||
* @param key predicate name
|
||||
* @param value predicate value
|
||||
* @return predicate value
|
||||
*/
|
||||
@Override
|
||||
public String put(String key, String value) {
|
||||
if (MagicBooleans.trace_mode) ;
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* get a predicate value
|
||||
*
|
||||
* @param key predicate name
|
||||
* @return predicate value
|
||||
*/
|
||||
public String get(String key) {
|
||||
String result = super.get(key);
|
||||
if (result == null) return MagicStrings.unknown_predicate_value;
|
||||
else return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read predicate default values from an input stream
|
||||
*
|
||||
* @param in input stream
|
||||
*/
|
||||
public void getPredicateDefaultsFromInputStream (InputStream in) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
String strLine;
|
||||
try {
|
||||
//Read File Line By Line
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
if (strLine.contains(":")) {
|
||||
String property = strLine.substring(0, strLine.indexOf(":"));
|
||||
String value = strLine.substring(strLine.indexOf(":")+1);
|
||||
put(property, value);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** read predicate defaults from a file
|
||||
*
|
||||
* @param filename name of file
|
||||
*/
|
||||
public void getPredicateDefaults (String filename) {
|
||||
try{
|
||||
// Open the file that is the first
|
||||
// command line parameter
|
||||
File file = new File(filename);
|
||||
if (file.exists()) {
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object
|
||||
getPredicateDefaultsFromInputStream(fstream);
|
||||
fstream.close();
|
||||
}
|
||||
}catch (Exception e){//Catch exception if any
|
||||
//log.error("Cannot get predicate defaults from '" + filename + "': " + e, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Bot Properties
|
||||
*/
|
||||
|
||||
public class Properties extends HashMap<String, String> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
//private static final Logger log = LoggerFactory.getLogger(Properties.class);
|
||||
/**
|
||||
* get the value of a bot property.
|
||||
*
|
||||
* @param key property name
|
||||
* @return property value or a string indicating the property is undefined
|
||||
*/
|
||||
public String get(String key) {
|
||||
String result = super.get(key);
|
||||
if (result == null) return MagicStrings.unknown_property_value;
|
||||
else return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read bot properties from an input stream.
|
||||
*
|
||||
* @param in Input stream
|
||||
*/
|
||||
public void getPropertiesFromInputStream(InputStream in) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
try {
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
if (strLine.contains(":")) {
|
||||
String property = strLine.substring(0, strLine.indexOf(":"));
|
||||
String value = strLine.substring(strLine.indexOf(":")+1);
|
||||
put(property, value);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read bot properties from a file.
|
||||
*
|
||||
* @param filename file containing bot properties
|
||||
*/
|
||||
public void getProperties (String filename) {
|
||||
// log.info("Get Properties: "+filename);
|
||||
try {
|
||||
// Open the file that is the first
|
||||
// command line parameter
|
||||
File file = new File(filename);
|
||||
if (file.exists()) {
|
||||
// log.info("Exists: "+filename);
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object
|
||||
getPropertiesFromInputStream(fstream);
|
||||
//Close the input stream
|
||||
fstream.close();
|
||||
}
|
||||
} catch (Exception e){//Catch exception if any
|
||||
// log.error("Cannot get properties from '" + filename + "': " + e, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.util.HashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alicebot.ab.utils.CalendarUtils;
|
||||
import org.alicebot.ab.utils.NetworkUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class Sraix {
|
||||
|
||||
// private static final Logger log = LoggerFactory.getLogger(Sraix.class);
|
||||
public static HashMap<String, String> custIdMap = new HashMap<String, String>();
|
||||
|
||||
private static String custid = "0"; // customer ID number for Pandorabots
|
||||
|
||||
public static String sraix(Chat chatSession, String input, String defaultResponse, String hint, String host, String botid, String apiKey, String limit) {
|
||||
String response;
|
||||
if (host != null && botid != null) {
|
||||
response = sraixPandorabots(input, chatSession, host, botid);
|
||||
}
|
||||
else response = sraixPannous(input, hint, chatSession);
|
||||
if (response.equals(MagicStrings.sraix_failed)) {
|
||||
if (chatSession != null && defaultResponse == null) response = AIMLProcessor.respond(MagicStrings.sraix_failed, "nothing", "nothing", chatSession);
|
||||
else if (defaultResponse != null) response = defaultResponse;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
public static String sraixPandorabots(String input, Chat chatSession, String host, String botid) {
|
||||
//log.info("Entering SRAIX with input="+input+" host ="+host+" botid="+botid);
|
||||
String responseContent = pandorabotsRequest(input, host, botid);
|
||||
if (responseContent == null) return MagicStrings.sraix_failed;
|
||||
else return pandorabotsResponse(responseContent, chatSession, host, botid);
|
||||
}
|
||||
public static String pandorabotsRequest(String input, String host, String botid) {
|
||||
try {
|
||||
custid = "0";
|
||||
String key = host+":"+botid;
|
||||
if (custIdMap.containsKey(key)) custid = custIdMap.get(key);
|
||||
//log.info("--> custid = "+custid);
|
||||
String spec = NetworkUtils.spec(host, botid, custid, input);
|
||||
//log.info("Spec = "+spec);
|
||||
String responseContent = NetworkUtils.responseContent(spec);
|
||||
return responseContent;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static String pandorabotsResponse (String sraixResponse, Chat chatSession, String host, String botid) {
|
||||
int n1 = sraixResponse.indexOf("<that>");
|
||||
int n2 = sraixResponse.indexOf("</that>");
|
||||
String botResponse = MagicStrings.sraix_failed;
|
||||
if (n2 > n1)
|
||||
botResponse = sraixResponse.substring(n1+"<that>".length(), n2);
|
||||
n1 = sraixResponse.indexOf("custid=");
|
||||
if (n1 > 0) {
|
||||
custid = sraixResponse.substring(n1+"custid=\"".length(), sraixResponse.length());
|
||||
n2 = custid.indexOf("\"");
|
||||
if (n2 > 0) custid = custid.substring(0, n2);
|
||||
else custid = "0";
|
||||
String key = host+":"+botid;
|
||||
//log.info("--> Map "+key+" --> "+custid);
|
||||
custIdMap.put(key, custid);
|
||||
}
|
||||
if (botResponse.endsWith(".")) botResponse = botResponse.substring(0, botResponse.length()-1); // snnoying Pandorabots extra "."
|
||||
return botResponse;
|
||||
}
|
||||
|
||||
public static String sraixPannous(String input, String hint, Chat chatSession) {
|
||||
try {
|
||||
if (hint == null) hint = MagicStrings.sraix_no_hint;
|
||||
input = " "+input+" ";
|
||||
input = input.replace(" point ", ".");
|
||||
input = input.replace(" rparen ", ")");
|
||||
input = input.replace(" lparen ","(");
|
||||
input = input.replace(" slash ","/");
|
||||
input = input.replace(" star ","*");
|
||||
input = input.replace(" dash ","-");
|
||||
input = input.trim();
|
||||
input = input.replace(" ","+");
|
||||
int offset = CalendarUtils.timeZoneOffset();
|
||||
//log.info("OFFSET = "+offset);
|
||||
String locationString = "";
|
||||
if (chatSession.locationKnown) {
|
||||
locationString = "&location="+chatSession.latitude+","+chatSession.longitude;
|
||||
}
|
||||
// https://weannie.pannous.com/api?input=when+is+daylight+savings+time+in+the+us&locale=en_US&login=pandorabots&ip=169.254.178.212&botid=0&key=CKNgaaVLvNcLhDupiJ1R8vtPzHzWc8mhIQDFSYWj&exclude=Dialogues,ChatBot&out=json
|
||||
String url = "https://weannie.pannous.com/api?input="+input+"&locale=en_US&timeZone="+offset+locationString+"&login="+MagicStrings.pannous_login+"&ip="+NetworkUtils.localIPAddress()+"&botid=0&key="+MagicStrings.pannous_api_key+"&exclude=Dialogues,ChatBot&out=json";
|
||||
// log.debug("Sraix url='"+url+"'");
|
||||
String page = NetworkUtils.responseContent(url);
|
||||
// log.debug( "Sraix: "+page);
|
||||
String text="";
|
||||
String imgRef="";
|
||||
if (page == null || page.length() == 0) {
|
||||
text = MagicStrings.sraix_failed;
|
||||
}
|
||||
else {
|
||||
JSONArray outputJson = new JSONObject(page).getJSONArray("output");
|
||||
if (outputJson.length() == 0) {
|
||||
text = MagicStrings.sraix_failed;
|
||||
}
|
||||
else {
|
||||
JSONObject firstHandler = outputJson.getJSONObject(0);
|
||||
JSONObject actions = firstHandler.getJSONObject("actions");
|
||||
if (actions.has("reminder")) {
|
||||
Object obj = actions.get("reminder");
|
||||
if (obj instanceof JSONObject) {
|
||||
JSONObject sObj = (JSONObject) obj;
|
||||
String date = sObj.getString("date");
|
||||
date = date.substring(0, "2012-10-24T14:32".length());
|
||||
//log.info("date="+date);
|
||||
String duration = sObj.getString("duration");
|
||||
//log.info("duration="+duration);
|
||||
|
||||
Pattern datePattern = Pattern.compile("(.*)-(.*)-(.*)T(.*):(.*)");
|
||||
Matcher m = datePattern.matcher(date);
|
||||
String year="", month="", day="", hour="", minute="";
|
||||
if (m.matches()) {
|
||||
year = m.group(1);
|
||||
month = String.valueOf(Integer.parseInt(m.group(2))-1);
|
||||
day = m.group(3);
|
||||
|
||||
hour = m.group(4);
|
||||
minute = m.group(5);
|
||||
text = "<year>"+year+"</year>" +
|
||||
"<month>"+month+"</month>" +
|
||||
"<day>"+day+"</day>" +
|
||||
"<hour>"+hour+"</hour>" +
|
||||
"<minute>"+minute+"</minute>" +
|
||||
"<duration>"+duration+"</duration>";
|
||||
|
||||
}
|
||||
else text = MagicStrings.schedule_error;
|
||||
}
|
||||
}
|
||||
else if (actions.has("say") && !hint.equals(MagicStrings.sraix_pic_hint)) {
|
||||
Object obj = actions.get("say");
|
||||
if (obj instanceof JSONObject) {
|
||||
JSONObject sObj = (JSONObject) obj;
|
||||
text = sObj.getString("text");
|
||||
if (sObj.has("moreText")) {
|
||||
JSONArray arr = sObj.getJSONArray("moreText");
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
text += " " + arr.getString(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text = obj.toString();
|
||||
}
|
||||
}
|
||||
if (actions.has("show") && !text.contains("Wolfram")
|
||||
&& actions.getJSONObject("show").has("images")) {
|
||||
JSONArray arr = actions.getJSONObject("show").getJSONArray(
|
||||
"images");
|
||||
int i = (int)(arr.length() * Math.random());
|
||||
//for (int j = 0; j < arr.length(); j++) log.info(arr.getString(j));
|
||||
imgRef = arr.getString(i);
|
||||
if (imgRef.startsWith("//")) imgRef = "http:"+imgRef;
|
||||
imgRef = "<a href=\""+imgRef+"\"><img src=\""+imgRef+"\"/></a>";
|
||||
//log.info("IMAGE REF="+imgRef);
|
||||
|
||||
}
|
||||
}
|
||||
if (hint.equals(MagicStrings.sraix_event_hint) && !text.startsWith("<year>")) return MagicStrings.sraix_failed;
|
||||
else if (text.equals(MagicStrings.sraix_failed)) return AIMLProcessor.respond(MagicStrings.sraix_failed, "nothing", "nothing", chatSession);
|
||||
else {
|
||||
text = text.replace("'","'");
|
||||
text = text.replace("'","'");
|
||||
text = text.replaceAll("\\[(.*)\\]", "");
|
||||
String[] sentences;
|
||||
sentences = text.split("\\. ");
|
||||
//log.info("Sraix: text has "+sentences.length+" sentences:");
|
||||
String clippedPage = sentences[0];
|
||||
for (int i = 1; i < sentences.length; i++) {
|
||||
if (clippedPage.length() < 500) clippedPage = clippedPage + ". "+sentences[i];
|
||||
//log.info(i+". "+sentences[i]);
|
||||
}
|
||||
|
||||
clippedPage = clippedPage + " " + imgRef;
|
||||
return clippedPage;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
// log.info("Sraix '" + input + "' failed");
|
||||
}
|
||||
return MagicStrings.sraix_failed;
|
||||
} // sraixPannous
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* structure to hold binding of wildcards in input pattern, that pattern and topicpattern
|
||||
*/
|
||||
public class StarBindings {
|
||||
public Stars inputStars;
|
||||
public Stars thatStars;
|
||||
public Stars topicStars;
|
||||
/** Constructor -- this class has public members
|
||||
*
|
||||
*/
|
||||
public StarBindings () {
|
||||
inputStars = new Stars();
|
||||
thatStars = new Stars();
|
||||
topicStars = new Stars();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* Array of values matching wildcards
|
||||
*/
|
||||
public class Stars extends ArrayList<String> {
|
||||
public String star (int i) {
|
||||
if (i < size())
|
||||
return get(i);
|
||||
else return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specialized timer function for program instrumentation
|
||||
*/
|
||||
public class Timer {
|
||||
private long startTimeMillis;
|
||||
|
||||
public Timer () {
|
||||
start();
|
||||
}
|
||||
public void start() {
|
||||
startTimeMillis = System.currentTimeMillis();
|
||||
}
|
||||
public long elapsedTimeMillis() {
|
||||
return System.currentTimeMillis()-startTimeMillis+1;
|
||||
}
|
||||
public long elapsedRestartMs() {
|
||||
long ms = System.currentTimeMillis()-startTimeMillis+1;
|
||||
start();
|
||||
return ms;
|
||||
}
|
||||
public float elapsedTimeSecs () {
|
||||
return elapsedTimeMillis()/1000F;
|
||||
}
|
||||
public float elapsedTimeMins () {
|
||||
return elapsedTimeSecs()/60F;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package org.alicebot.ab;
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.alicebot.ab.utils.CalendarUtils;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Utilities {
|
||||
//private static final Logger log = LoggerFactory.getLogger(Utilities.class);
|
||||
/**
|
||||
* Excel sometimes adds mysterious formatting to CSV files.
|
||||
* This function tries to clean it up.
|
||||
*
|
||||
* @param line line from AIMLIF file
|
||||
* @return reformatted line
|
||||
*/
|
||||
public static String fixCSV (String line) {
|
||||
while (line.endsWith(";")) line = line.substring(0, line.length()-1);
|
||||
if (line.startsWith("\"")) line = line.substring(1, line.length());
|
||||
if (line.endsWith("\"")) line = line.substring(0, line.length()-1);
|
||||
line = line.replaceAll("\"\"", "\"");
|
||||
return line;
|
||||
}
|
||||
public static String tagTrim(String xmlExpression, String tagName) {
|
||||
String stag = "<"+tagName+">";
|
||||
String etag = "</"+tagName+">";
|
||||
if (xmlExpression.length() >= (stag+etag).length()) {
|
||||
xmlExpression = xmlExpression.substring(stag.length());
|
||||
xmlExpression = xmlExpression.substring(0, xmlExpression.length()-etag.length());
|
||||
}
|
||||
return xmlExpression;
|
||||
}
|
||||
public static HashSet<String> stringSet(String... strings) {
|
||||
HashSet<String> set = new HashSet<String>();
|
||||
for (String s : strings) set.add(s);
|
||||
return set;
|
||||
}
|
||||
public static String getFileFromInputStream(InputStream in) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
String contents = "";
|
||||
try {
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
if (strLine.length() == 0) contents += "\n";
|
||||
else contents += strLine+"\n";
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return contents.trim();
|
||||
}
|
||||
public static String getFile (String filename) {
|
||||
String contents = "";
|
||||
try {
|
||||
File file = new File(filename);
|
||||
if (file.exists()) {
|
||||
//log.info("Found file "+filename);
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object
|
||||
contents = getFileFromInputStream(fstream) ;
|
||||
fstream.close();
|
||||
}
|
||||
} catch (Exception e){//Catch exception if any
|
||||
// log.error("Cannot get file '" + filename + "': " + e, e);
|
||||
}
|
||||
//log.info("getFile: "+contents);
|
||||
return contents;
|
||||
}
|
||||
public static String getCopyrightFromInputStream(InputStream in) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
String copyright = "";
|
||||
try {
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
if (strLine.length() == 0) copyright += "\n";
|
||||
else copyright += "<!-- "+strLine+" -->\n";
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return copyright;
|
||||
}
|
||||
public static String getCopyright (Bot bot, String AIMLFilename) {
|
||||
String copyright = "";
|
||||
String year = CalendarUtils.year();
|
||||
String date = CalendarUtils.date();
|
||||
try {
|
||||
copyright = getFile(MagicStrings.config_path+"/copyright.txt") ;
|
||||
String[] splitCopyright = copyright.split("\n");
|
||||
copyright = "";
|
||||
for (int i = 0; i < splitCopyright.length; i++) {
|
||||
copyright += "<!-- "+splitCopyright[i]+" -->\n";
|
||||
}
|
||||
copyright = copyright.replace("[url]", bot.properties.get("url"));
|
||||
copyright = copyright.replace("[date]", date);
|
||||
copyright = copyright.replace("[YYYY]", year);
|
||||
copyright = copyright.replace("[version]", bot.properties.get("version"));
|
||||
copyright = copyright.replace("[botname]", bot.name.toUpperCase());
|
||||
copyright = copyright.replace("[filename]", AIMLFilename);
|
||||
copyright = copyright.replace("[botmaster]", bot.properties.get("botmaster"));
|
||||
copyright = copyright.replace("[organization]", bot.properties.get("organization"));
|
||||
} catch (Exception e){//Catch exception if any
|
||||
// log.error("Cannot get copyright from '" + AIMLFilename + "': " + e, e);
|
||||
}
|
||||
//log.info("Copyright: "+copyright);
|
||||
return copyright;
|
||||
}
|
||||
|
||||
public static String getPannousAPIKey () {
|
||||
String apiKey = getFile(MagicStrings.config_path+"/pannous-apikey.txt");
|
||||
if (apiKey.equals("")) apiKey = MagicStrings.pannous_api_key;
|
||||
return apiKey;
|
||||
}
|
||||
public static String getPannousLogin () {
|
||||
String login = getFile(MagicStrings.config_path+"/pannous-login.txt");
|
||||
if (login.equals("")) login = MagicStrings.pannous_login;
|
||||
return login;
|
||||
}
|
||||
/**
|
||||
* Returns if a character is one of Chinese-Japanese-Korean characters.
|
||||
*
|
||||
* @param c
|
||||
* the character to be tested
|
||||
* @return true if CJK, false otherwise
|
||||
*/
|
||||
public static boolean isCharCJK(final char c) {
|
||||
if ((Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)
|
||||
|| (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A)
|
||||
|| (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B)
|
||||
|| (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS)
|
||||
|| (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS)
|
||||
|| (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT)
|
||||
|| (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION)
|
||||
|| (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
package org.alicebot.ab.cli;
|
||||
|
||||
/* Program AB Reference AIML 2.0 implementation
|
||||
Copyright (C) 2013 ALICE A.I. Foundation
|
||||
Contact: info@alicebot.org
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.alicebot.ab.AB;
|
||||
import org.alicebot.ab.AIMLProcessor;
|
||||
import org.alicebot.ab.Bot;
|
||||
import org.alicebot.ab.Category;
|
||||
import org.alicebot.ab.Chat;
|
||||
import org.alicebot.ab.Graphmaster;
|
||||
import org.alicebot.ab.MagicBooleans;
|
||||
import org.alicebot.ab.MagicStrings;
|
||||
import org.alicebot.ab.PCAIMLProcessorExtension;
|
||||
import org.alicebot.ab.Timer;
|
||||
import org.alicebot.ab.utils.IOUtils;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Main {
|
||||
// private static final Logger log = LoggerFactory.getLogger(Main.class);
|
||||
public static void main (String[] args) {
|
||||
MagicStrings.root_path = System.getProperty("user.dir");
|
||||
// log.info("Working Directory = " + MagicStrings.root_path);
|
||||
AIMLProcessor.extension = new PCAIMLProcessorExtension();
|
||||
mainFunction(args);
|
||||
}
|
||||
public static void mainFunction (String[] args) {
|
||||
String botName = "super";
|
||||
String action = "chat";
|
||||
// log.info(MagicStrings.programNameVersion);
|
||||
for (String s : args) {
|
||||
// log.info(s);
|
||||
String[] splitArg = s.split("=");
|
||||
if (splitArg.length >= 2) {
|
||||
String option = splitArg[0];
|
||||
String value = splitArg[1];
|
||||
if (option.equals("bot")) botName = value;
|
||||
if (option.equals("action")) action = value;
|
||||
if (option.equals("trace") && value.equals("true")) MagicBooleans.trace_mode = true;
|
||||
else MagicBooleans.trace_mode = false;
|
||||
}
|
||||
}
|
||||
// log.info("trace mode = "+MagicBooleans.trace_mode);
|
||||
Graphmaster.enableShortCuts = true;
|
||||
Timer timer = new Timer();
|
||||
Bot bot = new Bot(botName, MagicStrings.root_path, action); //
|
||||
//bot.preProcessor.normalizeFile("c:/ab/log1.txt", "c:/ab/data/lognormal.txt");
|
||||
if (bot.brain.getCategories().size() < 100) bot.brain.printgraph();
|
||||
if (action.equals("chat")) testChat(bot, MagicBooleans.trace_mode);
|
||||
else if (action.equals("test")) testSuite(bot, MagicStrings.root_path+"/data/find.txt");
|
||||
else if (action.equals("ab")) testAB(bot);
|
||||
else if (action.equals("aiml2csv") || action.equals("csv2aiml")) convert(bot, action);
|
||||
else if (action.equals("abwq")) AB.abwq(bot);
|
||||
}
|
||||
public static void convert(Bot bot, String action) {
|
||||
if (action.equals("aiml2csv")) bot.writeAIMLIFFiles();
|
||||
else if (action.equals("csv2aiml")) bot.writeAIMLFiles();
|
||||
}
|
||||
public static void testAB (Bot bot) {
|
||||
MagicBooleans.trace_mode = true;
|
||||
AB.ab(bot);
|
||||
AB.terminalInteraction(bot) ;
|
||||
}
|
||||
public static void testShortCuts () {
|
||||
//testChat(new Bot("alice"));
|
||||
//Graphmaster.enableShortCuts = false;
|
||||
//Bot bot = new Bot("alice");
|
||||
//bot.brain.printgraph();
|
||||
//bot.brain.nodeStats();
|
||||
//Graphmaster.enableShortCuts = true;
|
||||
//bot = new Bot("alice");
|
||||
//bot.brain.printgraph();
|
||||
//bot.brain.nodeStats();
|
||||
}
|
||||
public static void testChat (Bot bot, boolean traceMode) {
|
||||
Chat chatSession = new Chat(bot);
|
||||
// bot.preProcessor.normalizeFile("c:/ab/bots/super/aiml/thats.txt", "c:/ab/bots/super/aiml/normalthats.txt");
|
||||
bot.brain.nodeStats();
|
||||
MagicBooleans.trace_mode = traceMode;
|
||||
String textLine="";
|
||||
while (true) {
|
||||
System.out.print("Human: ");
|
||||
textLine = IOUtils.readInputTextLine();
|
||||
if (textLine == null || textLine.length() < 1) textLine = MagicStrings.null_input;
|
||||
if (textLine.equals("q")) System.exit(0);
|
||||
else if (textLine.equals("wq")) {
|
||||
bot.writeQuit();
|
||||
System.exit(0);
|
||||
}
|
||||
else if (textLine.equals("ab")) testAB(bot);
|
||||
else {
|
||||
String request = textLine;
|
||||
// log.debug("STATE="+request+":THAT="+chatSession.thatHistory.get(0).get(0)+":TOPIC="+chatSession.predicates.get("topic"));
|
||||
String response = chatSession.multisentenceRespond(request);
|
||||
while (response.contains("<")) response = response.replace("<","<");
|
||||
while (response.contains(">")) response = response.replace(">",">");
|
||||
// log.info("Robot: "+response);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public static void testBotChat () {
|
||||
Bot bot = new Bot("alice");
|
||||
// log.info(bot.brain.upgradeCnt+" brain upgrades");
|
||||
bot.brain.nodeStats();
|
||||
//bot.brain.printgraph();
|
||||
Chat chatSession = new Chat(bot);
|
||||
String request = "Hello. How are you? What is your name? Tell me about yourself.";
|
||||
String response = chatSession.multisentenceRespond(request);
|
||||
// log.info("Human: "+request);
|
||||
// log.info("Robot: "+response);
|
||||
}
|
||||
public static void testSuite (Bot bot, String filename) {
|
||||
try{
|
||||
AB.passed.readAIMLSet(bot);
|
||||
AB.testSet.readAIMLSet(bot);
|
||||
// log.info("Passed "+AB.passed.size()+" samples.");
|
||||
String textLine="";
|
||||
Chat chatSession = new Chat(bot);
|
||||
FileInputStream fstream = new FileInputStream(filename);
|
||||
// Get the object
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
|
||||
String strLine;
|
||||
//Read File Line By Line
|
||||
int count = 0;
|
||||
HashSet<String> samples = new HashSet<String>();
|
||||
while ((strLine = br.readLine())!= null) {
|
||||
samples.add(strLine);
|
||||
}
|
||||
ArrayList<String> sampleArray = new ArrayList<String>(samples);
|
||||
Collections.sort(sampleArray);
|
||||
for (String request : sampleArray) {
|
||||
if (request.startsWith("Human: ")) request = request.substring("Human: ".length(), request.length());
|
||||
Category c = new Category(0, bot.preProcessor.normalize(request), "*", "*", MagicStrings.blank_template, MagicStrings.null_aiml_file);
|
||||
if (AB.passed.contains(request)) ;
|
||||
else if (!bot.deletedGraph.existsCategory(c) && !AB.passed.contains(request)) {
|
||||
String response = chatSession.multisentenceRespond(request);
|
||||
// log.info(count+". Human: "+request);
|
||||
// log.info(count+". Robot: "+response);
|
||||
textLine = IOUtils.readInputTextLine();
|
||||
AB.terminalInteractionStep(bot, request, textLine, c);
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
//Close the input stream
|
||||
br.close();
|
||||
} catch (Exception e){//Catch exception if any
|
||||
// log.error("testSuite Error: " + e, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package org.alicebot.ab.utils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class CalendarUtils {
|
||||
//private static final Logger log = LoggerFactory.getLogger(CalendarUtils.class);
|
||||
|
||||
public static int timeZoneOffset() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int offset = (cal.get(Calendar.ZONE_OFFSET)+cal.get(Calendar.DST_OFFSET))/(60*1000);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
public static String year() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
return String.valueOf(cal.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
|
||||
public static String date() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int year = cal.get(Calendar.YEAR);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("MMMMMMMMM dd, yyyy");
|
||||
dateFormat.setCalendar(cal);
|
||||
return dateFormat.format(cal.getTime());
|
||||
}
|
||||
|
||||
|
||||
public static String date(String jformat, String locale, String timezone) {
|
||||
//HashSet<String> attributeNames = Utilities.stringSet("jformat","format","locale","timezone");
|
||||
if (jformat == null) jformat = "EEE MMM dd HH:mm:ss zzz yyyy";
|
||||
if (locale == null) locale = Locale.US.getISO3Country();
|
||||
if (timezone == null) timezone = TimeZone.getDefault().getDisplayName();
|
||||
//log.info("Format = "+format+" Locale = "+locale+" Timezone = "+timezone);
|
||||
String dateAsString = new Date().toString();
|
||||
try {
|
||||
SimpleDateFormat simpleDateFormat =
|
||||
new SimpleDateFormat(jformat);
|
||||
dateAsString = simpleDateFormat.format(new Date());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// log.info("CalendarUtils.date Bad date: Format = {} Locale = {} Timezone = {}",
|
||||
// jformat, locale, timezone);
|
||||
}
|
||||
// log.info("CalendarUtils.date: {}", dateAsString);
|
||||
return dateAsString;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package org.alicebot.ab.utils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
|
||||
public class DomUtils {
|
||||
//private static final Logger log = LoggerFactory.getLogger(DomUtils.class);
|
||||
|
||||
public static Node parseFile(String fileName) throws Exception {
|
||||
File file = new File(fileName);
|
||||
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
// from AIMLProcessor.evalTemplate and AIMLProcessor.validTemplate:
|
||||
// dbFactory.setIgnoringComments(true); // fix this
|
||||
Document doc = dBuilder.parse(file);
|
||||
doc.getDocumentElement().normalize();
|
||||
Node root = doc.getDocumentElement();
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
public static Node parseString(String string) throws Exception {
|
||||
InputStream is = new ByteArrayInputStream(string.getBytes("UTF-16"));
|
||||
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
// from AIMLProcessor.evalTemplate and AIMLProcessor.validTemplate:
|
||||
// dbFactory.setIgnoringComments(true); // fix this
|
||||
Document doc = dBuilder.parse(is);
|
||||
doc.getDocumentElement().normalize();
|
||||
Node root = doc.getDocumentElement();
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* convert an XML node to an XML statement
|
||||
* @param node current XML node
|
||||
* @return XML string
|
||||
*/
|
||||
public static String nodeToString(Node node) {
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
Transformer t = TransformerFactory.newInstance().newTransformer();
|
||||
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
t.setOutputProperty(OutputKeys.INDENT, "no");
|
||||
t.transform(new DOMSource(node), new StreamResult(sw));
|
||||
} catch (TransformerException te) {
|
||||
// log.error("nodeToString Transformer Exception: " + te, te);
|
||||
}
|
||||
return sw.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.alicebot.ab.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class IOUtils {
|
||||
//private static final Logger log = LoggerFactory.getLogger(IOUtils.class);
|
||||
|
||||
public static String readInputTextLine() {
|
||||
BufferedReader lineOfText = new BufferedReader(new InputStreamReader(System.in));
|
||||
String textLine = null;
|
||||
try {
|
||||
textLine = lineOfText.readLine();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return textLine;
|
||||
}
|
||||
|
||||
|
||||
public static String system(String evaluatedContents, String failedString) {
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
// log.info("System {}", evaluatedContents);
|
||||
try {
|
||||
Process p = rt.exec(evaluatedContents);
|
||||
InputStream istrm = p.getInputStream();
|
||||
InputStreamReader istrmrdr = new InputStreamReader(istrm);
|
||||
BufferedReader buffrdr = new BufferedReader(istrmrdr);
|
||||
String result = "";
|
||||
String data = "";
|
||||
while ((data = buffrdr.readLine()) != null) {
|
||||
result += data+"\n";
|
||||
}
|
||||
// log.info("Result = {}", result);
|
||||
return result;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return failedString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.alicebot.ab.utils;
|
||||
|
||||
|
||||
public class MemoryUtils {
|
||||
|
||||
|
||||
public static long totalMemory() {
|
||||
return Runtime.getRuntime().totalMemory();
|
||||
}
|
||||
|
||||
|
||||
public static long maxMemory() {
|
||||
return Runtime.getRuntime().maxMemory();
|
||||
}
|
||||
|
||||
|
||||
public static long freeMemory() {
|
||||
return Runtime.getRuntime().freeMemory();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package org.alicebot.ab.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Enumeration;
|
||||
|
||||
//import org.apache.http.client.HttpClient;
|
||||
//import org.apache.http.client.methods.HttpGet;
|
||||
//import org.apache.http.impl.client.DefaultHttpClient;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class NetworkUtils {
|
||||
//private static final Logger log = LoggerFactory
|
||||
//.getLogger(NetworkUtils.class);
|
||||
|
||||
public static String localIPAddress() {
|
||||
try {
|
||||
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
|
||||
NetworkInterface intf = en.nextElement();
|
||||
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
|
||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||
if (!inetAddress.isLoopbackAddress()) {
|
||||
String ipAddress = inetAddress.getHostAddress().toString();
|
||||
int p = ipAddress.indexOf("%");
|
||||
if (p > 0) ipAddress = ipAddress.substring(0, p);
|
||||
// log.info("--> localIPAddress = {}", ipAddress);
|
||||
return ipAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
|
||||
public static String responseContent(String url) throws Exception {
|
||||
//HttpClient client = new DefaultHttpClient();
|
||||
//HttpGet request = new HttpGet();
|
||||
//request.setURI(new URI(url));
|
||||
// InputStream is = client.execute(request).getEntity().getContent();
|
||||
//BufferedReader inb = new BufferedReader(new InputStreamReader(is));
|
||||
StringBuilder sb = new StringBuilder("");
|
||||
String line;
|
||||
String NL = System.getProperty("line.separator");
|
||||
// while ((line = inb.readLine()) != null) {
|
||||
// sb.append(line).append(NL);
|
||||
// }
|
||||
// inb.close();
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String spec(String host, String botid, String custid, String input) {
|
||||
// log.trace("--> custid = {}", custid);
|
||||
String spec = "";
|
||||
if (custid.equals("0")) // get custid on first transaction with Pandorabots
|
||||
spec = String.format("%s?botid=%s&input=%s",
|
||||
"http://" + host + "/pandora/talk-xml",
|
||||
botid,
|
||||
URLEncoder.encode(input));
|
||||
else spec = // re-use custid on each subsequent interaction
|
||||
String.format("%s?botid=%s&custid=%s&input=%s",
|
||||
"http://" + host + "/pandora/talk-xml",
|
||||
botid,
|
||||
custid,
|
||||
URLEncoder.encode(input));
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:drawable="@color/colorPrimary"/>
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@drawable/splash"/>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -0,0 +1,34 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
android:height="108dp"
|
||||
android:width="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
</vector>
|
|
@ -0,0 +1,6 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/gobutton_pressed"/>
|
||||
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/gobutton_pressed"/>
|
||||
<item android:state_focused="true" android:drawable="@drawable/gobutton_selected"/>
|
||||
<item android:state_focused="false" android:state_pressed="false" android:drawable="@drawable/gobutton"/>
|
||||
</selector>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".DisplayMessageActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="TextView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</android.support.constraint.ConstraintLayout>
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linearLayout4"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:focusableInTouchMode="true"
|
||||
tools:context="com.fpghoti.androidbotinterface.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/output"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/linearLayout3"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/linearLayout3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#fff"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/output">
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:ems="10"
|
||||
android:hint="Say Something!"
|
||||
android:inputType="text"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:text=""
|
||||
app:layout_constraintEnd_toStartOf="@+id/imageButton2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButton2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="@drawable/sendbutton"
|
||||
android:onClick="sendMessage"
|
||||
android:padding="20dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/editText"
|
||||
app:layout_constraintTop_toTopOf="@+id/editText" />
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
|
@ -0,0 +1,7 @@
|
|||
<resources>
|
||||
<string name="app_name">Android Bot Interface</string>
|
||||
<string name="edit_message">Enter a message</string>
|
||||
<string name="button_send">Send</string>
|
||||
<string name="EXTRA_MESSAGE"></string>
|
||||
<string name="more_extra">Say Hello!</string>
|
||||
</resources>
|
|
@ -0,0 +1,15 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="android:windowBackground">@drawable/background_splash</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,17 @@
|
|||
package com.fpghoti.androidbotinterface;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
|
@ -0,0 +1,172 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
|
@ -0,0 +1,84 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
|
@ -0,0 +1 @@
|
|||
include ':app'
|