forked from carrawao/SWE_Finanzen
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/carrawao/SWE_Finanzen into …
…feature/activities
- Loading branch information
Showing
19 changed files
with
764 additions
and
73 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
class ActionProvider { | ||
|
||
strategies = { | ||
BuyAndHold : {experience: 'false', risk: 'false', active: 'true', effort: 'false', duration: 'true'}, | ||
Index : {experience: 'false', risk: 'false', active: 'false', effort: 'false',duration: 'true'}, | ||
Size : {experience: 'false', risk: 'medium', active: 'true', effort: 'false', duration: undefined}, | ||
Growth : {experience: 'true', risk: 'medium', active: 'true', effort: 'true', duration: 'true'}, | ||
Value : {experience: 'true', risk: 'medium', active: 'true', effort: 'true', duration: 'true'}, | ||
Long : {experience: 'true', risk: 'medium', active: 'true', effort: 'true', duration: 'true'}, | ||
Short :{experience: 'true', risk: 'true', active: 'true', effort: 'true', duration: 'false'}, | ||
Trend : {experience: 'true', risk: 'medium', active: 'true', effort: 'true', duration: 'medium'} , | ||
Dividend : {experience: 'false', risk: 'medium', active: 'true', effort: 'medium', duration: undefined}, | ||
Anticyclical : {experience: 'true', risk: 'true', active: 'true', effort: 'true', duration: 'false'}, | ||
Cyclical : {experience: undefined, risk: 'true', active: 'true', effort: 'true', duration: undefined} | ||
}; | ||
|
||
strategieDescriptions = { | ||
BuyAndHold : 'In this strategy, you buy individual stocks and hold them for at least five to 20 years. The hope is for long-term growth through diversified single stock purchases. Short-term fluctuations are avoided by the long investment period.', | ||
Index : 'You do not invest in individual stocks, but in indices or so-called ETFs (Exchange Traded Fund). This strategy works in principle like the buy and hold method, but ETFs contain many different securities according to certain indices and are therefore already diversified. This saves you a lot of effort before and during your loading investment.', | ||
Size : 'In the size strategy you go by the size of the company. It is assumed that the larger the company, the more secure the price gain and the smaller the expected fluctuations. Thus, the strategy is based on stability.', | ||
Growth : 'In the growth strategy you invest in stocks that are likely to increase in price over the next few years. This is judged on the basis of stock market data.', | ||
Value : 'With the Growth strategy you invest in stocks that are likely to rise in price in the next few years. This is judged on the basis of a detailed analysis of the company.', | ||
Long : 'In the Go-Long strategy you buy a stock and hold it in the hope that it will rise in the long term.', | ||
Short :'You sell a stock from your holdings and try to buy it again shortly after at the low. The difference can therefore be considered a profit.', | ||
Trend : 'In the trend determined strategy you try to predict the development of the stock by drawing certain trend lines, average values or by market technical theories.', | ||
Dividend : 'You bet on dividend payments and price gains.', | ||
Anticyclical : 'When everyone is buying, you sell and vice versa. You try to buy at the low and sell at the high, against the current.', | ||
Cyclical : 'You try to go with the flow and invest in securities that will predictably perform well.' | ||
}; | ||
|
||
questions = | ||
[ | ||
`Are you a beginner, intermediate or advanced investor?`, | ||
`How much risk are you willing to take?`, | ||
`Would you like to invest active?`, | ||
`How much effort do you want to put into your investing?`, | ||
`Do you want to invest shortterm, mediumterm or longterm?` | ||
]; | ||
|
||
answerAfterQuestion = | ||
[ | ||
{true: `Nice to hear, let's start!`, medium:`Let's give it a try anyway!`, false: `Okay, you can come back any time!`}, | ||
{true:`So you alreay have a lot of experience, impressive!`, medium: `So you are an intermediate investor!`, false: `No problem, there are also great strategies for beginners!`}, | ||
{true: `Okay so you are a risk taker!`, medium:`Medium risk, nice choice!`, false: `Just a tiny bit of risk, okay!`}, | ||
{true: `Okay, so you are an active investor!`, medium:`Then let's go with investing passivly!`, false: `Passive investing, nice choice!`}, | ||
{true: `So you don't mind getting your hands dirty!`, medium:`Medium effort it is!`, false: `So you would rather chill at the beach than look through company reports!`}, | ||
{true: `All things come to him who waits!`, medium:`Okay, we're going with mediumterm investing!`, false: `Looks like you're looking for quick money!`}, | ||
]; | ||
|
||
preferencesArray = ['experience', 'risk', 'active', 'effort', 'duration']; | ||
|
||
constructor( | ||
createChatBotMessage, | ||
setStateFunc, | ||
createClientMessage, | ||
stateRef, | ||
createCustomMessage, | ||
...rest | ||
) { | ||
this.createChatBotMessage = createChatBotMessage; | ||
this.setState = setStateFunc; | ||
this.createClientMessage = createClientMessage; | ||
this.stateRef = stateRef; | ||
this.createCustomMessage = createCustomMessage; | ||
} | ||
|
||
handleChitChat(answer) { | ||
const botMessage = this.createChatBotMessage(answer); | ||
|
||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botMessage], | ||
})); | ||
} | ||
|
||
handleAnswer(answer, questionNr, userPreferences) { | ||
if (questionNr === undefined) { | ||
questionNr = 0; | ||
userPreferences = {experience: '', risk: '', active: false, effort: '', duration: ''}; | ||
} | ||
if (questionNr === -1) { | ||
const botAnswer = this.createChatBotMessage(`Hi! I'm Benchi! Are you interested in finding the right investment strategy for you together?`); | ||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botAnswer], | ||
'questionNr': (questionNr + 1) | ||
})); | ||
return; | ||
} | ||
if (questionNr === 5) { | ||
userPreferences = {...userPreferences, duration: answer}; | ||
const Strategy = this.findStrategyForUser(userPreferences); | ||
const botAnswer = this.createChatBotMessage(this.answerAfterQuestion[questionNr][answer]); | ||
const botStrategy = this.createChatBotMessage(`The best strategy for you is ${Strategy}`); | ||
const botStrategyExplanation = this.createChatBotMessage(this.strategieDescriptions[Strategy]); | ||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botAnswer, botStrategy, botStrategyExplanation], | ||
questionNr: questionNr + 1 | ||
})); | ||
return; | ||
} | ||
if (questionNr > 5) { | ||
userPreferences = {...userPreferences, duration: answer}; | ||
const Strategy = this.findStrategyForUser(userPreferences); | ||
const botStrategy = this.createChatBotMessage(`The best strategy for you is ${Strategy}`); | ||
const botStrategyExplanation = this.createChatBotMessage(this.strategieDescriptions[Strategy]); | ||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botStrategy, botStrategyExplanation], | ||
questionNr: questionNr + 1 | ||
})); | ||
return; | ||
} | ||
|
||
if (this.preferencesArray[questionNr-1] === 'active') { | ||
answer = answer === 'medium' ? false : answer; | ||
} | ||
const botAnswer = this.createChatBotMessage(this.answerAfterQuestion[questionNr][answer]); | ||
const botNewQuestion = this.createChatBotMessage(this.questions[questionNr]); | ||
|
||
if (questionNr > 0 && questionNr < 5) { | ||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botAnswer, botNewQuestion], | ||
'questionNr': questionNr + 1, | ||
'userPreferences': {...userPreferences, [this.preferencesArray[questionNr-1]]: answer} | ||
})); | ||
} else { | ||
if (questionNr === 0 && answer === 'false') { | ||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botAnswer], | ||
'questionNr': -1, | ||
})); | ||
return; | ||
} | ||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botAnswer, botNewQuestion], | ||
questionNr: questionNr + 1 | ||
})); | ||
} | ||
} | ||
|
||
findStrategyForUser(userPreferences) { | ||
let strategiesFit = {}; | ||
const strategiesKeys = Object.keys(this.strategies); | ||
for (let index = 0; index < strategiesKeys.length; index++) { | ||
const strategieKey = strategiesKeys[index]; | ||
const strategy = this.strategies[strategieKey]; | ||
let fit = 0; | ||
for (let i = 0; i < this.preferencesArray.length; i++) { | ||
const preference = this.preferencesArray[i]; | ||
if (strategy[preference] === undefined || strategy[preference] === userPreferences[preference]) { | ||
fit++; | ||
} | ||
} | ||
strategiesFit[strategieKey] = fit; | ||
} | ||
console.log(strategiesFit); | ||
let bestStrategy = ''; | ||
let bestFit = 0; | ||
for (let index = 0; index < strategiesKeys.length; index++) { | ||
const strategieKey = strategiesKeys[index]; | ||
if (bestFit < strategiesFit[strategieKey]) { | ||
bestFit = strategiesFit[strategieKey]; | ||
bestStrategy = strategieKey; | ||
} | ||
} | ||
console.log(bestStrategy); | ||
return bestStrategy; | ||
} | ||
|
||
handleNoAnswer() { | ||
const botMessage = this.createChatBotMessage(`Sorry, but I didn't understand you.`); | ||
|
||
this.setState((prev) => ({ | ||
...prev, | ||
messages: [...prev.messages, botMessage], | ||
})); | ||
this.messageCnt = this.messageCnt + 1; | ||
} | ||
} | ||
|
||
export default ActionProvider; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
class MessageParser { | ||
constructor(actionProvider, state) { | ||
this.actionProvider = actionProvider; | ||
this.state = {...state}; | ||
} | ||
|
||
parse(message) { | ||
console.log(this.state) | ||
this.fetchAnswer(message); | ||
} | ||
|
||
interpret(data) { | ||
const chitChatAnswer = data[0].answer; | ||
const answer = data[1] !== undefined ? data[1].answer : undefined; | ||
if (answer !== undefined) { | ||
this.actionProvider.handleAnswer(answer, this.state.questionNr, this.state.userPreferences); | ||
return; | ||
} | ||
if (chitChatAnswer === 'true' || chitChatAnswer === 'false' || chitChatAnswer === 'medium') { | ||
this.actionProvider.handleAnswer(chitChatAnswer, this.state.questionNr, this.state.userPreferences); | ||
return; | ||
} | ||
if (chitChatAnswer === 'No answer found') { | ||
this.actionProvider.handleNoAnswer(); | ||
return; | ||
} | ||
this.actionProvider.handleChitChat(chitChatAnswer); | ||
} | ||
|
||
fetchAnswer(message) { | ||
var url = "https://westeurope.api.cognitive.microsoft.com/language/:query-knowledgebases?projectName=benchi-QnA&api-version=2021-10-01&deploymentName=production"; | ||
|
||
var xhr = new XMLHttpRequest(); | ||
xhr.open("POST", url); | ||
xhr.responseType = 'json'; | ||
|
||
xhr.setRequestHeader("Ocp-Apim-Subscription-Key", "6ee6c9b8f982470abc210317cbf8d89c"); | ||
xhr.setRequestHeader("Content-Type", "application/json"); | ||
|
||
xhr.onreadystatechange = () => { | ||
if (xhr.readyState === 4) { | ||
this.interpret(xhr.response.answers); | ||
} | ||
}; | ||
|
||
var data = `{"top":3,"question":"${message}","includeUnstructuredSources":true,"confidenceScoreThreshold":"0.5","answerSpanRequest":{"enable":true,"topAnswersWithSpan":1,"confidenceScoreThreshold":"0.5"}}`; | ||
|
||
xhr.send(data); | ||
} | ||
} | ||
|
||
export default MessageParser; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { createChatBotMessage } from 'react-chatbot-kit'; | ||
|
||
const botName = 'Benchi'; | ||
|
||
const config = { | ||
initialMessages: [createChatBotMessage(`Hi! I'm ${botName}! Are you interested in finding the right investment strategy for you together?`)], | ||
customComponents: { | ||
// Replaces the default header | ||
header: () => <div style={{ backgroundColor: '#493f35', padding: '5px', borderRadius: '3px' , color: 'white'}}>Talk to Benchi!</div> | ||
}, | ||
botName: botName, | ||
customStyles: { | ||
botMessageBox: { | ||
backgroundColor: '#493f35', | ||
}, | ||
chatButton: { | ||
backgroundColor: '#5ccc9d', | ||
}, | ||
}, | ||
}; | ||
|
||
export default config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import React, {useState} from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
Box, | ||
Modal, | ||
Container, | ||
Typography, | ||
Avatar, | ||
IconButton, | ||
Grid, | ||
Paper | ||
} from '@mui/material'; | ||
|
||
import Chatbot from 'react-chatbot-kit'; | ||
import 'react-chatbot-kit/build/main.css'; | ||
import config from '../../benchi/config.js'; | ||
import MessageParser from '../../benchi/MessageParser.js'; | ||
import ActionProvider from '../../benchi/ActionProvider.js'; | ||
|
||
/** | ||
* Template to show modals throughout the app | ||
* @param props | ||
* @returns {JSX.Element} | ||
* @constructor | ||
*/ | ||
const Benchi = props => { | ||
const [showBot, toggleBot] = useState(false); | ||
|
||
const saveMessages = (messages, HTMLString) => { | ||
console.log(messages) | ||
localStorage.setItem('chatMessages', JSON.stringify(HTMLString)); | ||
}; | ||
|
||
const loadMessages = () => { | ||
const messages = JSON.parse(localStorage.getItem('chatMessages')); | ||
return messages; | ||
}; | ||
|
||
return ( | ||
<React.Fragment> | ||
<Grid container direction='column' alignItems='flex-end'> | ||
<Grid item> | ||
{showBot && ( | ||
<Paper elevation={6}> | ||
<Chatbot | ||
config={config} | ||
actionProvider={ActionProvider} | ||
messageHistory={loadMessages()} | ||
messageParser={MessageParser} | ||
saveMessages={saveMessages} | ||
/> | ||
</Paper> | ||
)} | ||
</Grid> | ||
<Grid item> | ||
<IconButton | ||
aria-label='Open Benchi Chat' | ||
size='small' | ||
onClick={() => toggleBot((prev) => !prev)} | ||
sx={{ | ||
|
||
}} | ||
> | ||
<Avatar | ||
className='me-xs-2 me-md-0' | ||
alt={`Benchi-icon`} | ||
src={`${process.env.PUBLIC_URL}/assets/images/chatbot.png`} | ||
sx={{ | ||
backgroundColor: 'white', | ||
border: '1px solid #493f35', | ||
width: { | ||
xs: '4rem', | ||
md: '5rem' | ||
}, | ||
height: { | ||
xs: '4rem', | ||
md: '5rem' | ||
}, | ||
}} | ||
/> | ||
</IconButton> | ||
</Grid> | ||
</Grid> | ||
</React.Fragment> | ||
); | ||
} | ||
|
||
export default Benchi; |
Oops, something went wrong.