7 changed files with 281 additions and 0 deletions
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<module type="WEB_MODULE" version="4"> |
||||
<component name="NewModuleRootManager"> |
||||
<content url="file://$MODULE_DIR$" /> |
||||
<orderEntry type="inheritedJdk" /> |
||||
<orderEntry type="sourceFolder" forTests="false" /> |
||||
</component> |
||||
</module> |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="ProjectModuleManager"> |
||||
<modules> |
||||
<module fileurl="file://$PROJECT_DIR$/.idea/kara.iml" filepath="$PROJECT_DIR$/.idea/kara.iml" /> |
||||
</modules> |
||||
</component> |
||||
</project> |
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="ChangeListManager"> |
||||
<list default="true" id="e3f098f0-e98c-435a-af04-d153c9525633" name="Default Changelist" comment="" /> |
||||
<option name="SHOW_DIALOG" value="false" /> |
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" /> |
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> |
||||
<option name="LAST_RESOLUTION" value="IGNORE" /> |
||||
</component> |
||||
<component name="ComposerSettings"> |
||||
<execution /> |
||||
</component> |
||||
<component name="PhpDebugGeneral" listening_started="true" /> |
||||
<component name="ProjectId" id="1g0vdLKoCZC7Ep9S79Z434EvL8a" /> |
||||
<component name="ProjectViewState"> |
||||
<option name="hideEmptyMiddlePackages" value="true" /> |
||||
<option name="showLibraryContents" value="true" /> |
||||
</component> |
||||
<component name="PropertiesComponent"> |
||||
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" /> |
||||
<property name="WebServerToolWindowFactoryState" value="false" /> |
||||
<property name="last.edited.regexp" value="Why, ever, would you? Stupid! pf." /> |
||||
<property name="nodejs_package_manager_path" value="npm" /> |
||||
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" /> |
||||
</component> |
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" /> |
||||
<component name="TaskManager"> |
||||
<task active="true" id="Default" summary="Default task"> |
||||
<changelist id="e3f098f0-e98c-435a-af04-d153c9525633" name="Default Changelist" comment="" /> |
||||
<created>1597264410641</created> |
||||
<option name="number" value="Default" /> |
||||
<option name="presentableId" value="Default" /> |
||||
<updated>1597264410641</updated> |
||||
<workItem from="1597264411672" duration="27000" /> |
||||
<workItem from="1597264469454" duration="594000" /> |
||||
<workItem from="1597346228730" duration="1396000" /> |
||||
</task> |
||||
<servers /> |
||||
</component> |
||||
<component name="TypeScriptGeneratedFilesManager"> |
||||
<option name="version" value="3" /> |
||||
</component> |
||||
<component name="WindowStateProjectService"> |
||||
<state x="172" y="0" key="SettingsEditor" timestamp="1597346967163"> |
||||
<screen x="0" y="0" width="1366" height="720" /> |
||||
</state> |
||||
<state x="172" y="0" key="SettingsEditor/0.0.1366.720@0.0.1366.720" timestamp="1597346967163" /> |
||||
<state x="0" y="0" width="616" height="720" key="find.popup" timestamp="1597346688624"> |
||||
<screen x="0" y="0" width="1366" height="720" /> |
||||
</state> |
||||
<state x="0" y="0" width="616" height="720" key="find.popup/0.0.1366.720@0.0.1366.720" timestamp="1597346688624" /> |
||||
<state width="533" height="302" key="javadoc.popup.new" timestamp="1597347220132"> |
||||
<screen x="0" y="0" width="1366" height="720" /> |
||||
</state> |
||||
<state width="533" height="302" key="javadoc.popup.new/0.0.1366.720@0.0.1366.720" timestamp="1597347220132" /> |
||||
<state x="346" y="41" width="672" height="678" key="search.everywhere.popup" timestamp="1597346938306"> |
||||
<screen x="0" y="0" width="1366" height="720" /> |
||||
</state> |
||||
<state x="346" y="41" width="672" height="678" key="search.everywhere.popup/0.0.1366.720@0.0.1366.720" timestamp="1597346938306" /> |
||||
</component> |
||||
</project> |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
#kara { |
||||
margin: 2em auto auto auto; |
||||
width: 50em; |
||||
} |
||||
|
||||
#kara .card { |
||||
height: 40em; |
||||
} |
||||
|
||||
.message { |
||||
padding: 10px; |
||||
margin-bottom: 5px; |
||||
min-width: 55%; |
||||
max-width: 80%; |
||||
} |
||||
|
||||
.ai-message { |
||||
border-radius: 0px 15px 15px 15px; |
||||
background-color: lightgreen; |
||||
} |
||||
|
||||
.user-message { |
||||
border-radius: 15px 0px 15px 15px; |
||||
background-color: lightblue; |
||||
} |
||||
|
||||
#chat-box { |
||||
overflow-y: scroll; |
||||
height: 100% |
||||
} |
@ -0,0 +1,106 @@
@@ -0,0 +1,106 @@
|
||||
let kara = new Vue({ |
||||
el: '#kara', |
||||
data: { |
||||
messages: [], |
||||
name: 'Kara', |
||||
chatbox: null, |
||||
isTyping: false, |
||||
templates: { |
||||
initialGreeting: "Hi! I'm Kara. :)" |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.initialGreeting(); |
||||
document.getElementById('chatinput').focus(); |
||||
}, |
||||
methods: { |
||||
addMessage(body, ai) { |
||||
this.messages.push({ |
||||
body: body, |
||||
ai: ai, |
||||
time: Date.now() |
||||
}) |
||||
}, |
||||
aiMessage(body) { |
||||
this.addMessage(body, true); |
||||
}, |
||||
userMessage(body) { |
||||
this.addMessage(body, false); |
||||
}, |
||||
initialGreeting() { |
||||
this.aiMessage(this.templates.initialGreeting); |
||||
}, |
||||
sendMessage() { |
||||
this.userMessage(this.chatbox); |
||||
this.react(this.chatbox); |
||||
this.chatbox = ''; |
||||
}, |
||||
react(message) { |
||||
this.isTyping = true; |
||||
|
||||
setTimeout(() => { |
||||
this.isTyping = false; |
||||
document.getElementById('chatinput').focus(); |
||||
}, 2500); |
||||
|
||||
setTimeout(() => { |
||||
this.aiMessage( |
||||
this.getAnswer(message) |
||||
); |
||||
}, 3000); |
||||
|
||||
this.scrollDown(); |
||||
}, |
||||
getAnswer(message) { |
||||
let isQuestion = (message.indexOf('?') > 0); |
||||
|
||||
message = message.toLowerCase(); |
||||
message = this.clearMessage(message); |
||||
let phrases = message.split(' '); |
||||
|
||||
|
||||
|
||||
if (isQuestion) { |
||||
return 'This is a question!'; |
||||
} else { |
||||
if (message.indexOf('name') > 0) { |
||||
return 'Nice to meet you!'; |
||||
} else { |
||||
return "I don't know what to say."; |
||||
} |
||||
} |
||||
|
||||
return answer; |
||||
}, |
||||
scrollDown() { |
||||
$('#chat-box').stop().animate({ |
||||
scrollTop: $('#chat-box')[0].scrollHeight |
||||
}, 800); |
||||
}, |
||||
clearMessage(message) { |
||||
return message.replace('?', '') |
||||
.replace('!', '') |
||||
.replace('.', '') |
||||
.replace(',', '') |
||||
.replace('-', '') |
||||
.replace('_', '') |
||||
.replace('#', '') |
||||
.replace('\'', '') |
||||
.replace('"', '') |
||||
.replace('+', '') |
||||
.replace('*', '') |
||||
.replace('§', '') |
||||
.replace('$', '') |
||||
.replace('%', '') |
||||
.replace('&', '') |
||||
.replace('/', '') |
||||
.replace('(', '') |
||||
.replace(')', '') |
||||
.replace('=', '') |
||||
.replace('\\', '') |
||||
.replace('@', '') |
||||
.replace('~', '') |
||||
.replace('…', ''); |
||||
} |
||||
} |
||||
}) |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<title> |
||||
Kara AI |
||||
</title> |
||||
<link href="https://bootswatch.com/4/materia/bootstrap.min.css" rel="stylesheet" type="text/css"/> |
||||
<link href="app.css" rel="stylesheet" type="text/css"/> |
||||
</head> |
||||
<body> |
||||
<div class="container" id="kara"> |
||||
<div class="row"> |
||||
<div class="col-md-12"> |
||||
<div class="card"> |
||||
<div class="card-header"> |
||||
<h5 class="text-center"> |
||||
Kara |
||||
</h5> |
||||
</div> |
||||
<div class="card-body"> |
||||
<div id="chat-box"> |
||||
<template v-for="message in messages"> |
||||
<div class="message ai-message float-left" v-if="message.ai"> |
||||
{{ message.body }} |
||||
<br/> |
||||
</div> |
||||
<div class="message user-message float-right" v-else=""> |
||||
{{ message.body }} |
||||
<br/> |
||||
</div> |
||||
</template> |
||||
<div class="message ai-message typing float-left" v-if="isTyping"> |
||||
<div class="spinner-grow text-secondary" role="status"> |
||||
<span class="sr-only"> |
||||
Loading... |
||||
</span> |
||||
</div> |
||||
<div class="spinner-grow text-secondary" role="status"> |
||||
<span class="sr-only"> |
||||
Loading... |
||||
</span> |
||||
</div> |
||||
<div class="spinner-grow text-secondary" role="status"> |
||||
<span class="sr-only"> |
||||
Loading... |
||||
</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="card-footer"> |
||||
<input autofocus="true" class="form-control" id="chatinput" type="text" v-model="chatbox" v-on:keyup.enter="sendMessage()" v-if="!isTyping" autofocus> |
||||
<input autofocus="true" class="form-control" id="chatinput" type="text" v-else disabled> |
||||
</input> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<script src="https://code.jquery.com/jquery-3.5.1.js"> |
||||
</script> |
||||
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"> |
||||
</script> |
||||
<script src="app.js"> |
||||
</script> |
||||
</body> |
||||
</html> |
Loading…
Reference in new issue