Showing
71 changed files
with
2175 additions
and
0 deletions
final/.gitignore
0 → 100644
1 | +node_modules/ |
final/LICENSE
0 → 100644
1 | +MIT License | ||
2 | + | ||
3 | +Copyright (c) 2016 Jerry Wang (https://jw84.co) | ||
4 | + | ||
5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | +of this software and associated documentation files (the "Software"), to deal | ||
7 | +in the Software without restriction, including without limitation the rights | ||
8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | +copies of the Software, and to permit persons to whom the Software is | ||
10 | +furnished to do so, subject to the following conditions: | ||
11 | + | ||
12 | +The above copyright notice and this permission notice shall be included in all | ||
13 | +copies or substantial portions of the Software. | ||
14 | + | ||
15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | +SOFTWARE. |
final/Procfile
0 → 100644
1 | +web: node index.js |
final/Seq2Seq.py
0 → 100644
This diff is collapsed. Click to expand it.
final/Word2Vec.py
0 → 100644
1 | +import tensorflow as tf | ||
2 | +import numpy as np | ||
3 | +import re | ||
4 | +from collections import Counter | ||
5 | +import sys | ||
6 | +import math | ||
7 | +from random import randint | ||
8 | +import pickle | ||
9 | +import os | ||
10 | +import sys | ||
11 | +sys.stdout.reconfigure(encoding='utf-8') | ||
12 | + | ||
13 | +# This Word2Vec implementation is largely based on this paper | ||
14 | +# https://papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf | ||
15 | +# It's a bit old, but Word2Vec is still SOTA and relatively simple, so I'm going with it | ||
16 | + | ||
17 | +# Check out Tensorflow's documentation which is pretty good for Word2Vec | ||
18 | +# https://www.tensorflow.org/tutorials/word2vec | ||
19 | + | ||
20 | +wordVecDimensions = 100 | ||
21 | +batchSize = 128 | ||
22 | +numNegativeSample = 64 | ||
23 | +windowSize = 5 | ||
24 | +numIterations = 100000 | ||
25 | + | ||
26 | +# This function just takes in the conversation data and makes it | ||
27 | +# into one huge string, and then uses a Counter to identify words | ||
28 | +# and the number of occurences | ||
29 | +def processDataset(filename): | ||
30 | + openedFile = open(filename, 'r', encoding='UTF8') | ||
31 | + allLines = openedFile.readlines() | ||
32 | + myStr = "" | ||
33 | + for line in allLines: | ||
34 | + myStr += line | ||
35 | + finalDict = Counter(myStr.split()) | ||
36 | + return myStr, finalDict | ||
37 | + | ||
38 | +def createTrainingMatrices(dictionary, corpus): | ||
39 | + allUniqueWords = list(dictionary.keys()) | ||
40 | + allWords = corpus.split() | ||
41 | + numTotalWords = len(allWords) | ||
42 | + xTrain=[] | ||
43 | + yTrain=[] | ||
44 | + for i in range(numTotalWords): | ||
45 | + if i % 100000 == 0: | ||
46 | + print ('Finished %d/%d total words' % (i, numTotalWords)) | ||
47 | + wordsAfter = allWords[i + 1:i + windowSize + 1] | ||
48 | + wordsBefore = allWords[max(0, i - windowSize):i] | ||
49 | + wordsAdded = wordsAfter + wordsBefore | ||
50 | + for word in wordsAdded: | ||
51 | + xTrain.append(allUniqueWords.index(allWords[i])) | ||
52 | + yTrain.append(allUniqueWords.index(word)) | ||
53 | + return xTrain, yTrain | ||
54 | + | ||
55 | +def getTrainingBatch(): | ||
56 | + num = randint(0,numTrainingExamples - batchSize - 1) | ||
57 | + arr = xTrain[num:num + batchSize] | ||
58 | + labels = yTrain[num:num + batchSize] | ||
59 | + return arr, labels[:,np.newaxis] | ||
60 | + | ||
61 | +continueWord2Vec = True | ||
62 | +# Loading the data structures if they are present in the directory | ||
63 | +if (os.path.isfile('Word2VecXTrain.npy') and os.path.isfile('Word2VecYTrain.npy') and os.path.isfile('wordList.txt')): | ||
64 | + xTrain = np.load('Word2VecXTrain.npy') | ||
65 | + yTrain = np.load('Word2VecYTrain.npy') | ||
66 | + print ('Finished loading training matrices') | ||
67 | + with open("wordList.txt", "rb") as fp: | ||
68 | + wordList = pickle.load(fp) | ||
69 | + print ('Finished loading word list') | ||
70 | + | ||
71 | +else: | ||
72 | + fullCorpus, datasetDictionary = processDataset(r'C:\Users\dlgpd\Desktop\20-1\oss\term-project\Learn_for_yourself\final\conversationData.txt') | ||
73 | + print ('Finished parsing and cleaning dataset') | ||
74 | + wordList = list(datasetDictionary.keys()) | ||
75 | + createOwnVectors = 'y' | ||
76 | + if (createOwnVectors == 'y'): | ||
77 | + xTrain, yTrain = createTrainingMatrices(datasetDictionary, fullCorpus) | ||
78 | + print ('Finished creating training matrices') | ||
79 | + np.save(r'C:\Users\dlgpd\Desktop\20-1\oss\term-project\Learn_for_yourself\final\Word2VecXTrain.npy', xTrain) | ||
80 | + np.save(r'C:\Users\dlgpd\Desktop\20-1\oss\term-project\Learn_for_yourself\final\Word2VecYTrain.npy', yTrain) | ||
81 | + else: | ||
82 | + continueWord2Vec = False | ||
83 | + with open(r"C:\Users\dlgpd\Desktop\20-1\oss\term-project\Learn_for_yourself\final\wordList.txt", "wb") as fp: | ||
84 | + pickle.dump(wordList, fp) |
final/app.js
0 → 100644
1 | +// call all the required packages | ||
2 | +var express = require('express') | ||
3 | +var bodyParser= require('body-parser') | ||
4 | +var multer = require('multer'); | ||
5 | +let { PythonShell } = require ( 'python-shell' ) | ||
6 | + | ||
7 | +//CREATE EXPRESS APP | ||
8 | +var app = express(); | ||
9 | + | ||
10 | +app.use(bodyParser.urlencoded({extended: true})) | ||
11 | +app.use('/users', express.static('uploads')) | ||
12 | + | ||
13 | +var options = { | ||
14 | + mode: 'text', | ||
15 | + pythonPath: '', | ||
16 | + pythonOptions: ['-u'], | ||
17 | + scriptPath: '', | ||
18 | + // args: ['value1', 'value2', 'value3'], | ||
19 | + encoding: 'utf8' | ||
20 | + }; | ||
21 | + | ||
22 | + | ||
23 | +//ROUTES WILL GO HERE | ||
24 | +app.get('/',function(req,res){ | ||
25 | + res.sendFile(__dirname + '/index.html'); | ||
26 | + }); | ||
27 | + | ||
28 | +var storage = multer.diskStorage({ | ||
29 | + destination: function (req, file, cb) { | ||
30 | + cb(null, 'uploads') | ||
31 | + }, | ||
32 | + filename: function (req, file, cb) { | ||
33 | + cb(null, "dataset.txt") | ||
34 | + } | ||
35 | + }) | ||
36 | + | ||
37 | +var upload = multer({ storage: storage }) | ||
38 | + | ||
39 | +app.post('/uploadfile', upload.single('myFile'), (req, res, next) => { | ||
40 | +const file = req.file | ||
41 | + if (!file) { | ||
42 | + const error = new Error('Please upload a file') | ||
43 | + error.httpStatusCode = 400 | ||
44 | + return next(error) | ||
45 | + } | ||
46 | + res.send(file) | ||
47 | + }) | ||
48 | + | ||
49 | +var upload = multer({ storage: storage }) | ||
50 | + | ||
51 | +app.get('/makebot', (req, res) => { | ||
52 | + res.sendFile(__dirname + '/index.html'); | ||
53 | + | ||
54 | + PythonShell.run('createDataset.py', options, (err, results) => { | ||
55 | + if (err) throw err; | ||
56 | + console.log('results: %j', results); | ||
57 | + }); | ||
58 | + res.send("create Data set") | ||
59 | + | ||
60 | + PythonShell.run('Word2Vec.py', options, (err, results) => { | ||
61 | + if (err) throw err; | ||
62 | + console.log('results: %j', results); | ||
63 | + }); | ||
64 | + res.send("word to vector") | ||
65 | + | ||
66 | + PythonShell.run('Seq2Seq.py', options, (err, results) => { | ||
67 | + if (err) throw err; | ||
68 | + console.log('results: %j', results); | ||
69 | + res.send("seq 2 seq") | ||
70 | + | ||
71 | + | ||
72 | + | ||
73 | + | ||
74 | + }); | ||
75 | + }) | ||
76 | + | ||
77 | + | ||
78 | +app.listen(3000, () => console.log('Server started on port 3000')); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/createDataset.py
0 → 100644
1 | +import pandas as pd | ||
2 | +import numpy as np | ||
3 | +import os | ||
4 | +import re | ||
5 | +from datetime import datetime | ||
6 | +import sys | ||
7 | +sys.stdout.reconfigure(encoding='utf-8') | ||
8 | + | ||
9 | +currentPath = os.getcwd() | ||
10 | + | ||
11 | + | ||
12 | +def getFacebookData(): | ||
13 | + print("function active") | ||
14 | + personName = "이혜연" | ||
15 | + personName = personName.rstrip('\r') | ||
16 | + responseDictionary = dict() | ||
17 | + with open(r'C:\Users\dlgpd\Desktop\20-1\oss\term-project\Learn_for_yourself\final\uploads\dataset.txt', 'r', encoding='UTF8') as fbFile: | ||
18 | + allLines = fbFile.readlines() | ||
19 | + | ||
20 | + myMessage, otherPersonsMessage, currentSpeaker = "","","" | ||
21 | + | ||
22 | + for index,lines in enumerate(allLines): | ||
23 | + rightBracket = lines.find(':') + 5 | ||
24 | + justMessage = lines[rightBracket:] | ||
25 | + colon = justMessage.find(':') | ||
26 | + # Find messages that I sent | ||
27 | + | ||
28 | + | ||
29 | + if (justMessage[:colon-1] == personName): | ||
30 | + if not myMessage: | ||
31 | + # Want to find the first message that I send (if I send multiple | ||
32 | + # in a row) | ||
33 | + startMessageIndex = index - 1 | ||
34 | + myMessage += justMessage[colon + 2:] | ||
35 | + | ||
36 | + elif myMessage: | ||
37 | + # Now go and see what message the other person sent by looking at | ||
38 | + # previous messages | ||
39 | + for counter in range(startMessageIndex, 0, -1): | ||
40 | + currentLine = allLines[counter] | ||
41 | + rightBracket = currentLine.find(':') + 5 | ||
42 | + justMessage = currentLine[rightBracket:] | ||
43 | + colon = justMessage.find(':') | ||
44 | + if not currentSpeaker: | ||
45 | + # The first speaker not named me | ||
46 | + currentSpeaker = justMessage[:colon] | ||
47 | + elif (currentSpeaker != justMessage[:colon] and otherPersonsMessage): | ||
48 | + # A different person started speaking, so now I know that the | ||
49 | + # first person's message is done | ||
50 | + otherPersonsMessage = cleanMessage(otherPersonsMessage) | ||
51 | + myMessage = cleanMessage(myMessage) | ||
52 | + responseDictionary[otherPersonsMessage] = myMessage | ||
53 | + break | ||
54 | + otherPersonsMessage = justMessage[colon + 2:] + otherPersonsMessage | ||
55 | + myMessage, otherPersonsMessage, currentSpeaker = "","","" | ||
56 | + | ||
57 | + return responseDictionary | ||
58 | + | ||
59 | + | ||
60 | + | ||
61 | +def cleanMessage(message): | ||
62 | + # Remove new lines within message | ||
63 | + cleanedMessage = message.replace('\n',' ').lower() | ||
64 | + # Deal with some weird tokens | ||
65 | + cleanedMessage = cleanedMessage.replace("\xc2\xa0", "") | ||
66 | + # Remove punctuation | ||
67 | + cleanedMessage = re.sub('([.,!?])','', cleanedMessage) | ||
68 | + # Remove multiple spaces in message | ||
69 | + cleanedMessage = re.sub(' +',' ', cleanedMessage) | ||
70 | + return cleanedMessage | ||
71 | + | ||
72 | +combinedDictionary = {} | ||
73 | + | ||
74 | +combinedDictionary.update(getFacebookData()) | ||
75 | + | ||
76 | +print ('Total len of dictionary', len(combinedDictionary)) | ||
77 | + | ||
78 | +print('Saving conversation data dictionary') | ||
79 | +np.save(r'C:\Users\dlgpd\Desktop\20-1\oss\term-project\Learn_for_yourself\final\conversationDictionary.npy', combinedDictionary) | ||
80 | + | ||
81 | +conversationFile = open(r'C:\Users\dlgpd\Desktop\20-1\oss\term-project\Learn_for_yourself\final\conversationData.txt', 'w', encoding='UTF8') | ||
82 | +for key, value in combinedDictionary.items(): | ||
83 | + if (not key.strip() or not value.strip()): | ||
84 | + # If there are empty strings | ||
85 | + continue | ||
86 | + conversationFile.write(key.strip() + value.strip()) |
final/flask/server.py
0 → 100644
1 | +import numpy as np | ||
2 | +import pickle | ||
3 | +import tensorflow as tf | ||
4 | +from flask import Flask, jsonify, render_template, request | ||
5 | +import model | ||
6 | + | ||
7 | +# Load in data structures | ||
8 | +with open("data/wordList.txt", "rb") as fp: | ||
9 | + wordList = pickle.load(fp) | ||
10 | +wordList.append('<pad>') | ||
11 | +wordList.append('<EOS>') | ||
12 | + | ||
13 | +# Load in hyperparamters | ||
14 | +vocabSize = len(wordList) | ||
15 | +batchSize = 24 | ||
16 | +maxEncoderLength = 15 | ||
17 | +maxDecoderLength = 15 | ||
18 | +lstmUnits = 112 | ||
19 | +numLayersLSTM = 3 | ||
20 | + | ||
21 | +# Create placeholders | ||
22 | +encoderInputs = [tf.placeholder(tf.int32, shape=(None,)) for i in range(maxEncoderLength)] | ||
23 | +decoderLabels = [tf.placeholder(tf.int32, shape=(None,)) for i in range(maxDecoderLength)] | ||
24 | +decoderInputs = [tf.placeholder(tf.int32, shape=(None,)) for i in range(maxDecoderLength)] | ||
25 | +feedPrevious = tf.placeholder(tf.bool) | ||
26 | + | ||
27 | +encoderLSTM = tf.nn.rnn_cell.BasicLSTMCell(lstmUnits, state_is_tuple=True) | ||
28 | +#encoderLSTM = tf.nn.rnn_cell.MultiRNNCell([singleCell]*numLayersLSTM, state_is_tuple=True) | ||
29 | +decoderOutputs, decoderFinalState = tf.contrib.legacy_seq2seq.embedding_rnn_seq2seq(encoderInputs, decoderInputs, encoderLSTM, | ||
30 | + vocabSize, vocabSize, lstmUnits, feed_previous=feedPrevious) | ||
31 | + | ||
32 | +decoderPrediction = tf.argmax(decoderOutputs, 2) | ||
33 | + | ||
34 | +# Start session and get graph | ||
35 | +sess = tf.Session() | ||
36 | +#y, variables = model.getModel(encoderInputs, decoderLabels, decoderInputs, feedPrevious) | ||
37 | + | ||
38 | +# Load in pretrained model | ||
39 | +saver = tf.train.Saver() | ||
40 | +saver.restore(sess, tf.train.latest_checkpoint('models')) | ||
41 | +zeroVector = np.zeros((1), dtype='int32') | ||
42 | + | ||
43 | +def pred(inputString): | ||
44 | + inputVector = model.getTestInput(inputString, wordList, maxEncoderLength) | ||
45 | + feedDict = {encoderInputs[t]: inputVector[t] for t in range(maxEncoderLength)} | ||
46 | + feedDict.update({decoderLabels[t]: zeroVector for t in range(maxDecoderLength)}) | ||
47 | + feedDict.update({decoderInputs[t]: zeroVector for t in range(maxDecoderLength)}) | ||
48 | + feedDict.update({feedPrevious: True}) | ||
49 | + ids = (sess.run(decoderPrediction, feed_dict=feedDict)) | ||
50 | + return model.idsToSentence(ids, wordList) | ||
51 | + | ||
52 | +# webapp | ||
53 | +app = Flask(__name__, template_folder='./') | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/index.html
0 → 100644
1 | +<!DOCTYPE html> | ||
2 | +<html lang="en"> | ||
3 | +<head> | ||
4 | + <meta charset="UTF-8"> | ||
5 | + <title>MY APP</title> | ||
6 | +</head> | ||
7 | +<body> | ||
8 | + | ||
9 | +<div> | ||
10 | + <script type ="text/javascript"> | ||
11 | + function movepage() { | ||
12 | + location.href = "/makebot"; | ||
13 | + } | ||
14 | + </script> | ||
15 | + | ||
16 | +<form action="/uploadfile" enctype="multipart/form-data" method="POST"> | ||
17 | + <input type="file" name="myFile" /> | ||
18 | + <input type="submit" value="Upload a file"/> | ||
19 | +</form> | ||
20 | + <input type="button" value="make chatbot" onclick="movepage()"/> | ||
21 | +</div> | ||
22 | + | ||
23 | + | ||
24 | +</body> | ||
25 | +</html> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/management/.gitignore
0 → 100644
1 | +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
2 | + | ||
3 | +# database | ||
4 | +/database.json | ||
5 | + | ||
6 | +# dependencies | ||
7 | +/node_modules | ||
8 | +/.pnp | ||
9 | +.pnp.js | ||
10 | + | ||
11 | +# testing | ||
12 | +/coverage | ||
13 | + | ||
14 | +# production | ||
15 | +/build | ||
16 | + | ||
17 | +# misc | ||
18 | +.DS_Store | ||
19 | +.env.local | ||
20 | +.env.development.local | ||
21 | +.env.test.local | ||
22 | +.env.production.local | ||
23 | + | ||
24 | +npm-debug.log* | ||
25 | +yarn-debug.log* | ||
26 | +yarn-error.log* |
final/management/client/.gitignore
0 → 100644
1 | +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
2 | + | ||
3 | +# dependencies | ||
4 | +/node_modules | ||
5 | +/.pnp | ||
6 | +.pnp.js | ||
7 | + | ||
8 | +# testing | ||
9 | +/coverage | ||
10 | + | ||
11 | +# production | ||
12 | +/build | ||
13 | + | ||
14 | +# misc | ||
15 | +.DS_Store | ||
16 | +.env.local | ||
17 | +.env.development.local | ||
18 | +.env.test.local | ||
19 | +.env.production.local | ||
20 | + | ||
21 | +npm-debug.log* | ||
22 | +yarn-debug.log* | ||
23 | +yarn-error.log* |
final/management/client/README.md
0 → 100644
1 | +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). | ||
2 | + | ||
3 | +## Available Scripts | ||
4 | + | ||
5 | +In the project directory, you can run: | ||
6 | + | ||
7 | +### `npm start` | ||
8 | + | ||
9 | +Runs the app in the development mode.<br /> | ||
10 | +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. | ||
11 | + | ||
12 | +The page will reload if you make edits.<br /> | ||
13 | +You will also see any lint errors in the console. | ||
14 | + | ||
15 | +### `npm test` | ||
16 | + | ||
17 | +Launches the test runner in the interactive watch mode.<br /> | ||
18 | +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. | ||
19 | + | ||
20 | +### `npm run build` | ||
21 | + | ||
22 | +Builds the app for production to the `build` folder.<br /> | ||
23 | +It correctly bundles React in production mode and optimizes the build for the best performance. | ||
24 | + | ||
25 | +The build is minified and the filenames include the hashes.<br /> | ||
26 | +Your app is ready to be deployed! | ||
27 | + | ||
28 | +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. | ||
29 | + | ||
30 | +### `npm run eject` | ||
31 | + | ||
32 | +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** | ||
33 | + | ||
34 | +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. | ||
35 | + | ||
36 | +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. | ||
37 | + | ||
38 | +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. | ||
39 | + | ||
40 | +## Learn More | ||
41 | + | ||
42 | +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). | ||
43 | + | ||
44 | +To learn React, check out the [React documentation](https://reactjs.org/). | ||
45 | + | ||
46 | +### Code Splitting | ||
47 | + | ||
48 | +This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting | ||
49 | + | ||
50 | +### Analyzing the Bundle Size | ||
51 | + | ||
52 | +This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size | ||
53 | + | ||
54 | +### Making a Progressive Web App | ||
55 | + | ||
56 | +This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app | ||
57 | + | ||
58 | +### Advanced Configuration | ||
59 | + | ||
60 | +This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration | ||
61 | + | ||
62 | +### Deployment | ||
63 | + | ||
64 | +This section has moved here: https://facebook.github.io/create-react-app/docs/deployment | ||
65 | + | ||
66 | +### `npm run build` fails to minify | ||
67 | + | ||
68 | +This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify |
final/management/client/package-lock.json
0 → 100644
This diff could not be displayed because it is too large.
final/management/client/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "management", | ||
3 | + "version": "0.1.0", | ||
4 | + "private": true, | ||
5 | + "dependencies": { | ||
6 | + "@material-ui/core": "^4.10.2", | ||
7 | + "@testing-library/jest-dom": "^4.2.4", | ||
8 | + "@testing-library/react": "^9.5.0", | ||
9 | + "@testing-library/user-event": "^7.2.1", | ||
10 | + "react": "^16.13.1", | ||
11 | + "react-dom": "^16.13.1", | ||
12 | + "react-scripts": "3.4.1" | ||
13 | + }, | ||
14 | + "scripts": { | ||
15 | + "start": "react-scripts start", | ||
16 | + "build": "react-scripts build", | ||
17 | + "test": "react-scripts test", | ||
18 | + "eject": "react-scripts eject" | ||
19 | + }, | ||
20 | + "eslintConfig": { | ||
21 | + "extends": "react-app" | ||
22 | + }, | ||
23 | + "browserslist": { | ||
24 | + "production": [ | ||
25 | + ">0.2%", | ||
26 | + "not dead", | ||
27 | + "not op_mini all" | ||
28 | + ], | ||
29 | + "development": [ | ||
30 | + "last 1 chrome version", | ||
31 | + "last 1 firefox version", | ||
32 | + "last 1 safari version" | ||
33 | + ] | ||
34 | + }, | ||
35 | + "proxy": "http://localhost:5000/" | ||
36 | +} |
final/management/client/public/favicon.ico
0 → 100644
No preview for this file type
final/management/client/public/index.html
0 → 100644
1 | +<!DOCTYPE html> | ||
2 | +<html lang="en"> | ||
3 | + <head> | ||
4 | + <meta charset="utf-8" /> | ||
5 | + <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> | ||
6 | + <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
7 | + <meta name="theme-color" content="#000000" /> | ||
8 | + <meta | ||
9 | + name="description" | ||
10 | + content="Web site created using create-react-app" | ||
11 | + /> | ||
12 | + <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> | ||
13 | + <!-- | ||
14 | + manifest.json provides metadata used when your web app is installed on a | ||
15 | + user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ | ||
16 | + --> | ||
17 | + <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> | ||
18 | + <!-- | ||
19 | + Notice the use of %PUBLIC_URL% in the tags above. | ||
20 | + It will be replaced with the URL of the `public` folder during the build. | ||
21 | + Only files inside the `public` folder can be referenced from the HTML. | ||
22 | + | ||
23 | + Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will | ||
24 | + work correctly both with client-side routing and a non-root public URL. | ||
25 | + Learn how to configure a non-root public URL by running `npm run build`. | ||
26 | + --> | ||
27 | + <title>React App</title> | ||
28 | + </head> | ||
29 | + <body> | ||
30 | + <noscript>You need to enable JavaScript to run this app.</noscript> | ||
31 | + <div id="root"></div> | ||
32 | + <!-- | ||
33 | + This HTML file is a template. | ||
34 | + If you open it directly in the browser, you will see an empty page. | ||
35 | + | ||
36 | + You can add webfonts, meta tags, or analytics to this file. | ||
37 | + The build step will place the bundled scripts into the <body> tag. | ||
38 | + | ||
39 | + To begin the development, run `npm start` or `yarn start`. | ||
40 | + To create a production bundle, use `npm run build` or `yarn build`. | ||
41 | + --> | ||
42 | + </body> | ||
43 | +</html> |
final/management/client/public/logo192.png
0 → 100644
5.22 KB
final/management/client/public/logo512.png
0 → 100644
9.44 KB
final/management/client/public/manifest.json
0 → 100644
1 | +{ | ||
2 | + "short_name": "React App", | ||
3 | + "name": "Create React App Sample", | ||
4 | + "icons": [ | ||
5 | + { | ||
6 | + "src": "favicon.ico", | ||
7 | + "sizes": "64x64 32x32 24x24 16x16", | ||
8 | + "type": "image/x-icon" | ||
9 | + }, | ||
10 | + { | ||
11 | + "src": "logo192.png", | ||
12 | + "type": "image/png", | ||
13 | + "sizes": "192x192" | ||
14 | + }, | ||
15 | + { | ||
16 | + "src": "logo512.png", | ||
17 | + "type": "image/png", | ||
18 | + "sizes": "512x512" | ||
19 | + } | ||
20 | + ], | ||
21 | + "start_url": ".", | ||
22 | + "display": "standalone", | ||
23 | + "theme_color": "#000000", | ||
24 | + "background_color": "#ffffff" | ||
25 | +} |
final/management/client/public/robots.txt
0 → 100644
final/management/client/src/App.css
0 → 100644
1 | +.App { | ||
2 | + text-align: center; | ||
3 | +} | ||
4 | + | ||
5 | +.App-logo { | ||
6 | + height: 40vmin; | ||
7 | + pointer-events: none; | ||
8 | +} | ||
9 | + | ||
10 | +@media (prefers-reduced-motion: no-preference) { | ||
11 | + .App-logo { | ||
12 | + animation: App-logo-spin infinite 20s linear; | ||
13 | + } | ||
14 | +} | ||
15 | + | ||
16 | +.App-header { | ||
17 | + background-color: #282c34; | ||
18 | + min-height: 100vh; | ||
19 | + display: flex; | ||
20 | + flex-direction: column; | ||
21 | + align-items: center; | ||
22 | + justify-content: center; | ||
23 | + font-size: calc(10px + 2vmin); | ||
24 | + color: white; | ||
25 | +} | ||
26 | + | ||
27 | +.App-link { | ||
28 | + color: #61dafb; | ||
29 | +} | ||
30 | + | ||
31 | +@keyframes App-logo-spin { | ||
32 | + from { | ||
33 | + transform: rotate(0deg); | ||
34 | + } | ||
35 | + to { | ||
36 | + transform: rotate(360deg); | ||
37 | + } | ||
38 | +} |
final/management/client/src/App.js
0 → 100644
1 | +import React, { Component } from 'react'; | ||
2 | +import './App.css'; | ||
3 | +import Customer from './components/Customer'; | ||
4 | +import Paper from '@material-ui/core/Paper'; | ||
5 | +import Table from '@material-ui/core/Table'; | ||
6 | +import TableHead from '@material-ui/core/TableHead'; | ||
7 | +import TableBody from '@material-ui/core/TableBody'; | ||
8 | +import TableRow from '@material-ui/core/TableRow'; | ||
9 | +import TableCell from '@material-ui/core/TableCell'; | ||
10 | +import { withStyles } from '@material-ui/core/styles'; | ||
11 | +import CircularProgress from '@material-ui/core/CircularProgress'; | ||
12 | + | ||
13 | +const styles = theme => ({ | ||
14 | + root: { | ||
15 | + width: '100%', | ||
16 | + marginTop: theme.spacing.unit*3, | ||
17 | + overflowX: "auto" | ||
18 | + }, | ||
19 | + table: { | ||
20 | + minWidth: 1080 | ||
21 | + }, | ||
22 | + progress: { | ||
23 | + margine: theme.spacing.unit*2 | ||
24 | + } | ||
25 | +}) | ||
26 | + | ||
27 | +class App extends Component { | ||
28 | + state = { | ||
29 | + customers: "", | ||
30 | + completed: 0 | ||
31 | + } | ||
32 | + | ||
33 | + //모든 컴포넌트 준비 완료일 때 실행 -- react가 라이브러리이기 때문 ! | ||
34 | + componentDidMount() { | ||
35 | + this.timer = setInterval(this.progress,20); | ||
36 | + this.callApi() | ||
37 | + .then(res => this.setState({customers: res})) | ||
38 | + .catch(err => console.log(err)); | ||
39 | + } | ||
40 | + | ||
41 | + callApi = async() => { | ||
42 | + //local의/api/customers에 접속해 response로 받아오고 이를 body변수에 담아주겠다 | ||
43 | + const response = await fetch('/api/customers'); | ||
44 | + const body = await response.json(); | ||
45 | + return body; | ||
46 | + } | ||
47 | + | ||
48 | + progress = () => { | ||
49 | + const { completed } = this.state; | ||
50 | + this.setState({completed : completed >=100 ? 0: completed +1}); | ||
51 | + } | ||
52 | + | ||
53 | + render() { | ||
54 | + const { classes } = this.props; | ||
55 | + return ( | ||
56 | + <Paper className = {classes.root}> | ||
57 | + <Table className = {classes.table}> | ||
58 | + <TableHead> | ||
59 | + <TableRow> | ||
60 | + <TableCell>번호</TableCell> | ||
61 | + <TableCell>이미지</TableCell> | ||
62 | + <TableCell>이름</TableCell> | ||
63 | + <TableCell>생년월일</TableCell> | ||
64 | + <TableCell>성별</TableCell> | ||
65 | + <TableCell>직업</TableCell> | ||
66 | + </TableRow> | ||
67 | + </TableHead> | ||
68 | + | ||
69 | + <TableBody> | ||
70 | + {this.state.customers ? this.state.customers.map (c=> { | ||
71 | + return (<Customer key={c.id} id={c.id} image={c.image} name={c.name} birthday={c.birthday} gender={c.gender} job={c.job} />) | ||
72 | + }) : | ||
73 | + <TableRow> | ||
74 | + <TableCell colSpan="6" align="center"> | ||
75 | + <CircularProgress className={classes.progress} varient="determinate" value={this.state.completed}/> | ||
76 | + </TableCell> | ||
77 | + </TableRow> | ||
78 | + } | ||
79 | + </TableBody> | ||
80 | + </Table> | ||
81 | + </Paper> | ||
82 | + ); | ||
83 | + } | ||
84 | +} | ||
85 | + | ||
86 | +export default withStyles(styles)(App); |
final/management/client/src/App.test.js
0 → 100644
1 | +import React from 'react'; | ||
2 | +import { render } from '@testing-library/react'; | ||
3 | +import App from './App'; | ||
4 | + | ||
5 | +test('renders learn react link', () => { | ||
6 | + const { getByText } = render(<App />); | ||
7 | + const linkElement = getByText(/learn react/i); | ||
8 | + expect(linkElement).toBeInTheDocument(); | ||
9 | +}); |
1 | +import React from 'react'; | ||
2 | +import TableRow from '@material-ui/core/TableRow'; | ||
3 | +import TableCell from '@material-ui/core/TableCell'; | ||
4 | + | ||
5 | +class Customer extends React.Component { | ||
6 | + render(){ | ||
7 | + return( | ||
8 | + <TableRow> | ||
9 | + <TableCell>{this.props.id}</TableCell> | ||
10 | + <TableCell><img src={this.props.image} alt="profile"/></TableCell> | ||
11 | + <TableCell>{this.props.name}</TableCell> | ||
12 | + <TableCell>{this.props.birthday}</TableCell> | ||
13 | + <TableCell>{this.props.gender}</TableCell> | ||
14 | + <TableCell>{this.props.job}</TableCell> | ||
15 | + </TableRow> | ||
16 | + ); | ||
17 | + } | ||
18 | +} | ||
19 | + | ||
20 | + | ||
21 | + | ||
22 | +export default Customer; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/management/client/src/index.css
0 → 100644
1 | +body { | ||
2 | + margin: 0; | ||
3 | + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', | ||
4 | + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', | ||
5 | + sans-serif; | ||
6 | + -webkit-font-smoothing: antialiased; | ||
7 | + -moz-osx-font-smoothing: grayscale; | ||
8 | +} | ||
9 | + | ||
10 | +code { | ||
11 | + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', | ||
12 | + monospace; | ||
13 | +} |
final/management/client/src/index.js
0 → 100644
1 | +import React from 'react'; | ||
2 | +import ReactDOM from 'react-dom'; | ||
3 | +import './index.css'; | ||
4 | +import App from './App'; | ||
5 | +import * as serviceWorker from './serviceWorker'; | ||
6 | + | ||
7 | +ReactDOM.render( | ||
8 | + <React.StrictMode> | ||
9 | + <App /> | ||
10 | + </React.StrictMode>, | ||
11 | + document.getElementById('root') | ||
12 | +); | ||
13 | + | ||
14 | +// If you want your app to work offline and load faster, you can change | ||
15 | +// unregister() to register() below. Note this comes with some pitfalls. | ||
16 | +// Learn more about service workers: https://bit.ly/CRA-PWA | ||
17 | +serviceWorker.unregister(); |
final/management/client/src/logo.svg
0 → 100644
1 | +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"> | ||
2 | + <g fill="#61DAFB"> | ||
3 | + <path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/> | ||
4 | + <circle cx="420.9" cy="296.5" r="45.7"/> | ||
5 | + <path d="M520.5 78.1z"/> | ||
6 | + </g> | ||
7 | +</svg> |
final/management/client/src/serviceWorker.js
0 → 100644
1 | +// This optional code is used to register a service worker. | ||
2 | +// register() is not called by default. | ||
3 | + | ||
4 | +// This lets the app load faster on subsequent visits in production, and gives | ||
5 | +// it offline capabilities. However, it also means that developers (and users) | ||
6 | +// will only see deployed updates on subsequent visits to a page, after all the | ||
7 | +// existing tabs open on the page have been closed, since previously cached | ||
8 | +// resources are updated in the background. | ||
9 | + | ||
10 | +// To learn more about the benefits of this model and instructions on how to | ||
11 | +// opt-in, read https://bit.ly/CRA-PWA | ||
12 | + | ||
13 | +const isLocalhost = Boolean( | ||
14 | + window.location.hostname === 'localhost' || | ||
15 | + // [::1] is the IPv6 localhost address. | ||
16 | + window.location.hostname === '[::1]' || | ||
17 | + // 127.0.0.0/8 are considered localhost for IPv4. | ||
18 | + window.location.hostname.match( | ||
19 | + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ | ||
20 | + ) | ||
21 | +); | ||
22 | + | ||
23 | +export function register(config) { | ||
24 | + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { | ||
25 | + // The URL constructor is available in all browsers that support SW. | ||
26 | + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); | ||
27 | + if (publicUrl.origin !== window.location.origin) { | ||
28 | + // Our service worker won't work if PUBLIC_URL is on a different origin | ||
29 | + // from what our page is served on. This might happen if a CDN is used to | ||
30 | + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 | ||
31 | + return; | ||
32 | + } | ||
33 | + | ||
34 | + window.addEventListener('load', () => { | ||
35 | + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; | ||
36 | + | ||
37 | + if (isLocalhost) { | ||
38 | + // This is running on localhost. Let's check if a service worker still exists or not. | ||
39 | + checkValidServiceWorker(swUrl, config); | ||
40 | + | ||
41 | + // Add some additional logging to localhost, pointing developers to the | ||
42 | + // service worker/PWA documentation. | ||
43 | + navigator.serviceWorker.ready.then(() => { | ||
44 | + console.log( | ||
45 | + 'This web app is being served cache-first by a service ' + | ||
46 | + 'worker. To learn more, visit https://bit.ly/CRA-PWA' | ||
47 | + ); | ||
48 | + }); | ||
49 | + } else { | ||
50 | + // Is not localhost. Just register service worker | ||
51 | + registerValidSW(swUrl, config); | ||
52 | + } | ||
53 | + }); | ||
54 | + } | ||
55 | +} | ||
56 | + | ||
57 | +function registerValidSW(swUrl, config) { | ||
58 | + navigator.serviceWorker | ||
59 | + .register(swUrl) | ||
60 | + .then(registration => { | ||
61 | + registration.onupdatefound = () => { | ||
62 | + const installingWorker = registration.installing; | ||
63 | + if (installingWorker == null) { | ||
64 | + return; | ||
65 | + } | ||
66 | + installingWorker.onstatechange = () => { | ||
67 | + if (installingWorker.state === 'installed') { | ||
68 | + if (navigator.serviceWorker.controller) { | ||
69 | + // At this point, the updated precached content has been fetched, | ||
70 | + // but the previous service worker will still serve the older | ||
71 | + // content until all client tabs are closed. | ||
72 | + console.log( | ||
73 | + 'New content is available and will be used when all ' + | ||
74 | + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' | ||
75 | + ); | ||
76 | + | ||
77 | + // Execute callback | ||
78 | + if (config && config.onUpdate) { | ||
79 | + config.onUpdate(registration); | ||
80 | + } | ||
81 | + } else { | ||
82 | + // At this point, everything has been precached. | ||
83 | + // It's the perfect time to display a | ||
84 | + // "Content is cached for offline use." message. | ||
85 | + console.log('Content is cached for offline use.'); | ||
86 | + | ||
87 | + // Execute callback | ||
88 | + if (config && config.onSuccess) { | ||
89 | + config.onSuccess(registration); | ||
90 | + } | ||
91 | + } | ||
92 | + } | ||
93 | + }; | ||
94 | + }; | ||
95 | + }) | ||
96 | + .catch(error => { | ||
97 | + console.error('Error during service worker registration:', error); | ||
98 | + }); | ||
99 | +} | ||
100 | + | ||
101 | +function checkValidServiceWorker(swUrl, config) { | ||
102 | + // Check if the service worker can be found. If it can't reload the page. | ||
103 | + fetch(swUrl, { | ||
104 | + headers: { 'Service-Worker': 'script' }, | ||
105 | + }) | ||
106 | + .then(response => { | ||
107 | + // Ensure service worker exists, and that we really are getting a JS file. | ||
108 | + const contentType = response.headers.get('content-type'); | ||
109 | + if ( | ||
110 | + response.status === 404 || | ||
111 | + (contentType != null && contentType.indexOf('javascript') === -1) | ||
112 | + ) { | ||
113 | + // No service worker found. Probably a different app. Reload the page. | ||
114 | + navigator.serviceWorker.ready.then(registration => { | ||
115 | + registration.unregister().then(() => { | ||
116 | + window.location.reload(); | ||
117 | + }); | ||
118 | + }); | ||
119 | + } else { | ||
120 | + // Service worker found. Proceed as normal. | ||
121 | + registerValidSW(swUrl, config); | ||
122 | + } | ||
123 | + }) | ||
124 | + .catch(() => { | ||
125 | + console.log( | ||
126 | + 'No internet connection found. App is running in offline mode.' | ||
127 | + ); | ||
128 | + }); | ||
129 | +} | ||
130 | + | ||
131 | +export function unregister() { | ||
132 | + if ('serviceWorker' in navigator) { | ||
133 | + navigator.serviceWorker.ready | ||
134 | + .then(registration => { | ||
135 | + registration.unregister(); | ||
136 | + }) | ||
137 | + .catch(error => { | ||
138 | + console.error(error.message); | ||
139 | + }); | ||
140 | + } | ||
141 | +} |
final/management/client/src/setupTests.js
0 → 100644
final/management/package-lock.json
0 → 100644
This diff is collapsed. Click to expand it.
final/management/package.json
0 → 100644
1 | +{ | ||
2 | + "name" : "management", | ||
3 | + "version": "1.0.0", | ||
4 | + "scripts":{ | ||
5 | + "client": "cd client && yarn start", | ||
6 | + "server": "node server.js", | ||
7 | + "dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\"" | ||
8 | + }, | ||
9 | + "dependencies": { | ||
10 | + "body-parser": "^1.18.3", | ||
11 | + "express": "^4.16.4" | ||
12 | + }, | ||
13 | + "devDependencies": { | ||
14 | + "concurrently":"^" | ||
15 | + } | ||
16 | +} |
final/management/server.js
0 → 100644
1 | +const fs = require('fs'); | ||
2 | +const express = require('express'); | ||
3 | +const bodyParser = require('body-parser'); | ||
4 | +const app = express(); | ||
5 | +const port = process.env.PORT || 5000; | ||
6 | + | ||
7 | +app.use(bodyParser.json()); | ||
8 | +app.use(bodyParser.urlencoded({ exrended : true })); | ||
9 | + | ||
10 | +const data = fs.readFileSync('./database.json'); | ||
11 | +const conf = JSON.parse(data); | ||
12 | +const mysql = require('mysql'); | ||
13 | + | ||
14 | +const connection = mysql.createConnection({ | ||
15 | + host: conf.host, | ||
16 | + user: conf.user, | ||
17 | + password: conf.password, | ||
18 | + port: conf.port, | ||
19 | + database: conf.databse | ||
20 | +}); | ||
21 | +connection.connect(); | ||
22 | + | ||
23 | + | ||
24 | +app.get('/api/customers', (req, res) => { | ||
25 | + connection.query( | ||
26 | + "SELECT * FROM CUSTOMER", | ||
27 | + (err,rows,fields) => { | ||
28 | + res.send(rows); | ||
29 | + } | ||
30 | + ) | ||
31 | +}) | ||
32 | + | ||
33 | +app.listen(port, () => console.log(`Listening on port ${port}`)); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/models/checkpoint
0 → 100644
1 | +model_checkpoint_path: "pretrained_seq2seq.ckpt-108300" | ||
2 | +all_model_checkpoint_paths: "pretrained_seq2seq.ckpt-107900" | ||
3 | +all_model_checkpoint_paths: "pretrained_seq2seq.ckpt-108000" | ||
4 | +all_model_checkpoint_paths: "pretrained_seq2seq.ckpt-108100" | ||
5 | +all_model_checkpoint_paths: "pretrained_seq2seq.ckpt-108200" | ||
6 | +all_model_checkpoint_paths: "pretrained_seq2seq.ckpt-108300" |
This file is too large to display.
No preview for this file type
No preview for this file type
This file is too large to display.
No preview for this file type
No preview for this file type
This file is too large to display.
No preview for this file type
No preview for this file type
This file is too large to display.
No preview for this file type
No preview for this file type
This file is too large to display.
No preview for this file type
No preview for this file type
final/myJsBots/my-own-bot/.eslintrc.js
0 → 100644
1 | +/* eslint-disable */ | ||
2 | +module.exports = { | ||
3 | + "extends": "standard", | ||
4 | + "rules": { | ||
5 | + "semi": [2, "always"], | ||
6 | + "indent": [2, 4], | ||
7 | + "no-return-await": 0, | ||
8 | + "space-before-function-paren": [2, { | ||
9 | + "named": "never", | ||
10 | + "anonymous": "never", | ||
11 | + "asyncArrow": "always" | ||
12 | + }], | ||
13 | + "template-curly-spacing": [2, "always"] | ||
14 | + } | ||
15 | +}; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/myJsBots/my-own-bot/.gitignore
0 → 100644
final/myJsBots/my-own-bot/README.md
0 → 100644
1 | +# my-own-bot | ||
2 | + | ||
3 | +like me | ||
4 | + | ||
5 | +This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a simple bot that accepts input from the user and echoes it back. | ||
6 | + | ||
7 | +## Prerequisites | ||
8 | + | ||
9 | +- [Node.js](https://nodejs.org) version 10.14.1 or higher | ||
10 | + | ||
11 | + ```bash | ||
12 | + # determine node version | ||
13 | + node --version | ||
14 | + ``` | ||
15 | + | ||
16 | +## To run the bot | ||
17 | + | ||
18 | +- Install modules | ||
19 | + | ||
20 | + ```bash | ||
21 | + npm install | ||
22 | + ``` | ||
23 | + | ||
24 | +- Start the bot | ||
25 | + | ||
26 | + ```bash | ||
27 | + npm start | ||
28 | + ``` | ||
29 | + | ||
30 | +## Testing the bot using Bot Framework Emulator | ||
31 | + | ||
32 | +[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. | ||
33 | + | ||
34 | +- Install the Bot Framework Emulator version 4.9.0 or greater from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) | ||
35 | + | ||
36 | +### Connect to the bot using Bot Framework Emulator | ||
37 | + | ||
38 | +- Launch Bot Framework Emulator | ||
39 | +- File -> Open Bot | ||
40 | +- Enter a Bot URL of `http://localhost:3978/api/messages` | ||
41 | + | ||
42 | +## Deploy the bot to Azure | ||
43 | + | ||
44 | +To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions. | ||
45 | + | ||
46 | + | ||
47 | +## Further reading | ||
48 | + | ||
49 | +- [Bot Framework Documentation](https://docs.botframework.com) | ||
50 | +- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0) | ||
51 | +- [Dialogs](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-dialog?view=azure-bot-service-4.0) | ||
52 | +- [Gathering Input Using Prompts](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-prompts?view=azure-bot-service-4.0) | ||
53 | +- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0) | ||
54 | +- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0) | ||
55 | +- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0) | ||
56 | +- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest) | ||
57 | +- [Azure Portal](https://portal.azure.com) | ||
58 | +- [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/) | ||
59 | +- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0) | ||
60 | +- [Restify](https://www.npmjs.com/package/restify) | ||
61 | +- [dotenv](https://www.npmjs.com/package/dotenv) |
final/myJsBots/my-own-bot/bot.js
0 → 100644
1 | +// Copyright (c) Microsoft Corporation. All rights reserved. | ||
2 | +// Licensed under the MIT License. | ||
3 | + | ||
4 | +const { ActivityHandler, MessageFactory } = require('botbuilder'); | ||
5 | + | ||
6 | +class EchoBot extends ActivityHandler { | ||
7 | + constructor() { | ||
8 | + super(); | ||
9 | + // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types. | ||
10 | + this.onMessage(async (context, next) => { | ||
11 | + const replyText = `Echo: ${ context.activity.text }`; | ||
12 | + await context.sendActivity(MessageFactory.text(replyText, replyText)); | ||
13 | + // By calling next() you ensure that the next BotHandler is run. | ||
14 | + await next(); | ||
15 | + }); | ||
16 | + | ||
17 | + this.onMembersAdded(async (context, next) => { | ||
18 | + const membersAdded = context.activity.membersAdded; | ||
19 | + const welcomeText = 'Hello and welcome!'; | ||
20 | + for (let cnt = 0; cnt < membersAdded.length; ++cnt) { | ||
21 | + if (membersAdded[cnt].id !== context.activity.recipient.id) { | ||
22 | + await context.sendActivity(MessageFactory.text(welcomeText, welcomeText)); | ||
23 | + } | ||
24 | + } | ||
25 | + // By calling next() you ensure that the next BotHandler is run. | ||
26 | + await next(); | ||
27 | + }); | ||
28 | + } | ||
29 | +} | ||
30 | + | ||
31 | +module.exports.EchoBot = EchoBot; |
1 | +{ | ||
2 | + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", | ||
3 | + "contentVersion": "1.0.0.0", | ||
4 | + "parameters": { | ||
5 | + "groupLocation": { | ||
6 | + "value": "" | ||
7 | + }, | ||
8 | + "groupName": { | ||
9 | + "value": "" | ||
10 | + }, | ||
11 | + "appId": { | ||
12 | + "value": "" | ||
13 | + }, | ||
14 | + "appSecret": { | ||
15 | + "value": "" | ||
16 | + }, | ||
17 | + "botId": { | ||
18 | + "value": "" | ||
19 | + }, | ||
20 | + "botSku": { | ||
21 | + "value": "" | ||
22 | + }, | ||
23 | + "newAppServicePlanName": { | ||
24 | + "value": "" | ||
25 | + }, | ||
26 | + "newAppServicePlanSku": { | ||
27 | + "value": { | ||
28 | + "name": "S1", | ||
29 | + "tier": "Standard", | ||
30 | + "size": "S1", | ||
31 | + "family": "S", | ||
32 | + "capacity": 1 | ||
33 | + } | ||
34 | + }, | ||
35 | + "newAppServicePlanLocation": { | ||
36 | + "value": "" | ||
37 | + }, | ||
38 | + "newWebAppName": { | ||
39 | + "value": "" | ||
40 | + } | ||
41 | + } | ||
42 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", | ||
3 | + "contentVersion": "1.0.0.0", | ||
4 | + "parameters": { | ||
5 | + "appId": { | ||
6 | + "value": "" | ||
7 | + }, | ||
8 | + "appSecret": { | ||
9 | + "value": "" | ||
10 | + }, | ||
11 | + "botId": { | ||
12 | + "value": "" | ||
13 | + }, | ||
14 | + "botSku": { | ||
15 | + "value": "" | ||
16 | + }, | ||
17 | + "newAppServicePlanName": { | ||
18 | + "value": "" | ||
19 | + }, | ||
20 | + "newAppServicePlanSku": { | ||
21 | + "value": { | ||
22 | + "name": "S1", | ||
23 | + "tier": "Standard", | ||
24 | + "size": "S1", | ||
25 | + "family": "S", | ||
26 | + "capacity": 1 | ||
27 | + } | ||
28 | + }, | ||
29 | + "appServicePlanLocation": { | ||
30 | + "value": "" | ||
31 | + }, | ||
32 | + "existingAppServicePlan": { | ||
33 | + "value": "" | ||
34 | + }, | ||
35 | + "newWebAppName": { | ||
36 | + "value": "" | ||
37 | + } | ||
38 | + } | ||
39 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", | ||
3 | + "contentVersion": "1.0.0.0", | ||
4 | + "parameters": { | ||
5 | + "groupLocation": { | ||
6 | + "type": "string", | ||
7 | + "metadata": { | ||
8 | + "description": "Specifies the location of the Resource Group." | ||
9 | + } | ||
10 | + }, | ||
11 | + "groupName": { | ||
12 | + "type": "string", | ||
13 | + "metadata": { | ||
14 | + "description": "Specifies the name of the Resource Group." | ||
15 | + } | ||
16 | + }, | ||
17 | + "appId": { | ||
18 | + "type": "string", | ||
19 | + "metadata": { | ||
20 | + "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." | ||
21 | + } | ||
22 | + }, | ||
23 | + "appSecret": { | ||
24 | + "type": "string", | ||
25 | + "metadata": { | ||
26 | + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings." | ||
27 | + } | ||
28 | + }, | ||
29 | + "botId": { | ||
30 | + "type": "string", | ||
31 | + "metadata": { | ||
32 | + "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." | ||
33 | + } | ||
34 | + }, | ||
35 | + "botSku": { | ||
36 | + "type": "string", | ||
37 | + "metadata": { | ||
38 | + "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." | ||
39 | + } | ||
40 | + }, | ||
41 | + "newAppServicePlanName": { | ||
42 | + "type": "string", | ||
43 | + "metadata": { | ||
44 | + "description": "The name of the App Service Plan." | ||
45 | + } | ||
46 | + }, | ||
47 | + "newAppServicePlanSku": { | ||
48 | + "type": "object", | ||
49 | + "defaultValue": { | ||
50 | + "name": "S1", | ||
51 | + "tier": "Standard", | ||
52 | + "size": "S1", | ||
53 | + "family": "S", | ||
54 | + "capacity": 1 | ||
55 | + }, | ||
56 | + "metadata": { | ||
57 | + "description": "The SKU of the App Service Plan. Defaults to Standard values." | ||
58 | + } | ||
59 | + }, | ||
60 | + "newAppServicePlanLocation": { | ||
61 | + "type": "string", | ||
62 | + "metadata": { | ||
63 | + "description": "The location of the App Service Plan. Defaults to \"westus\"." | ||
64 | + } | ||
65 | + }, | ||
66 | + "newWebAppName": { | ||
67 | + "type": "string", | ||
68 | + "defaultValue": "", | ||
69 | + "metadata": { | ||
70 | + "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." | ||
71 | + } | ||
72 | + } | ||
73 | + }, | ||
74 | + "variables": { | ||
75 | + "appServicePlanName": "[parameters('newAppServicePlanName')]", | ||
76 | + "resourcesLocation": "[parameters('newAppServicePlanLocation')]", | ||
77 | + "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", | ||
78 | + "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", | ||
79 | + "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]" | ||
80 | + }, | ||
81 | + "resources": [ | ||
82 | + { | ||
83 | + "name": "[parameters('groupName')]", | ||
84 | + "type": "Microsoft.Resources/resourceGroups", | ||
85 | + "apiVersion": "2018-05-01", | ||
86 | + "location": "[parameters('groupLocation')]", | ||
87 | + "properties": { | ||
88 | + } | ||
89 | + }, | ||
90 | + { | ||
91 | + "type": "Microsoft.Resources/deployments", | ||
92 | + "apiVersion": "2018-05-01", | ||
93 | + "name": "storageDeployment", | ||
94 | + "resourceGroup": "[parameters('groupName')]", | ||
95 | + "dependsOn": [ | ||
96 | + "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" | ||
97 | + ], | ||
98 | + "properties": { | ||
99 | + "mode": "Incremental", | ||
100 | + "template": { | ||
101 | + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", | ||
102 | + "contentVersion": "1.0.0.0", | ||
103 | + "parameters": {}, | ||
104 | + "variables": {}, | ||
105 | + "resources": [ | ||
106 | + { | ||
107 | + "comments": "Create a new App Service Plan", | ||
108 | + "type": "Microsoft.Web/serverfarms", | ||
109 | + "name": "[variables('appServicePlanName')]", | ||
110 | + "apiVersion": "2018-02-01", | ||
111 | + "location": "[variables('resourcesLocation')]", | ||
112 | + "sku": "[parameters('newAppServicePlanSku')]", | ||
113 | + "properties": { | ||
114 | + "name": "[variables('appServicePlanName')]" | ||
115 | + } | ||
116 | + }, | ||
117 | + { | ||
118 | + "comments": "Create a Web App using the new App Service Plan", | ||
119 | + "type": "Microsoft.Web/sites", | ||
120 | + "apiVersion": "2015-08-01", | ||
121 | + "location": "[variables('resourcesLocation')]", | ||
122 | + "kind": "app", | ||
123 | + "dependsOn": [ | ||
124 | + "[resourceId('Microsoft.Web/serverfarms/', variables('appServicePlanName'))]" | ||
125 | + ], | ||
126 | + "name": "[variables('webAppName')]", | ||
127 | + "properties": { | ||
128 | + "name": "[variables('webAppName')]", | ||
129 | + "serverFarmId": "[variables('appServicePlanName')]", | ||
130 | + "siteConfig": { | ||
131 | + "appSettings": [ | ||
132 | + { | ||
133 | + "name": "WEBSITE_NODE_DEFAULT_VERSION", | ||
134 | + "value": "10.14.1" | ||
135 | + }, | ||
136 | + { | ||
137 | + "name": "MicrosoftAppId", | ||
138 | + "value": "[parameters('appId')]" | ||
139 | + }, | ||
140 | + { | ||
141 | + "name": "MicrosoftAppPassword", | ||
142 | + "value": "[parameters('appSecret')]" | ||
143 | + } | ||
144 | + ], | ||
145 | + "cors": { | ||
146 | + "allowedOrigins": [ | ||
147 | + "https://botservice.hosting.portal.azure.net", | ||
148 | + "https://hosting.onecloud.azure-test.net/" | ||
149 | + ] | ||
150 | + } | ||
151 | + } | ||
152 | + } | ||
153 | + }, | ||
154 | + { | ||
155 | + "apiVersion": "2017-12-01", | ||
156 | + "type": "Microsoft.BotService/botServices", | ||
157 | + "name": "[parameters('botId')]", | ||
158 | + "location": "global", | ||
159 | + "kind": "bot", | ||
160 | + "sku": { | ||
161 | + "name": "[parameters('botSku')]" | ||
162 | + }, | ||
163 | + "properties": { | ||
164 | + "name": "[parameters('botId')]", | ||
165 | + "displayName": "[parameters('botId')]", | ||
166 | + "endpoint": "[variables('botEndpoint')]", | ||
167 | + "msaAppId": "[parameters('appId')]", | ||
168 | + "developerAppInsightsApplicationId": null, | ||
169 | + "developerAppInsightKey": null, | ||
170 | + "publishingCredentials": null, | ||
171 | + "storageResourceId": null | ||
172 | + }, | ||
173 | + "dependsOn": [ | ||
174 | + "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" | ||
175 | + ] | ||
176 | + } | ||
177 | + ], | ||
178 | + "outputs": {} | ||
179 | + } | ||
180 | + } | ||
181 | + } | ||
182 | + ] | ||
183 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", | ||
3 | + "contentVersion": "1.0.0.0", | ||
4 | + "parameters": { | ||
5 | + "appId": { | ||
6 | + "type": "string", | ||
7 | + "metadata": { | ||
8 | + "description": "Active Directory App ID, set as MicrosoftAppId in the Web App's Application Settings." | ||
9 | + } | ||
10 | + }, | ||
11 | + "appSecret": { | ||
12 | + "type": "string", | ||
13 | + "metadata": { | ||
14 | + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Defaults to \"\"." | ||
15 | + } | ||
16 | + }, | ||
17 | + "botId": { | ||
18 | + "type": "string", | ||
19 | + "metadata": { | ||
20 | + "description": "The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable." | ||
21 | + } | ||
22 | + }, | ||
23 | + "botSku": { | ||
24 | + "defaultValue": "F0", | ||
25 | + "type": "string", | ||
26 | + "metadata": { | ||
27 | + "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." | ||
28 | + } | ||
29 | + }, | ||
30 | + "newAppServicePlanName": { | ||
31 | + "type": "string", | ||
32 | + "defaultValue": "", | ||
33 | + "metadata": { | ||
34 | + "description": "The name of the new App Service Plan." | ||
35 | + } | ||
36 | + }, | ||
37 | + "newAppServicePlanSku": { | ||
38 | + "type": "object", | ||
39 | + "defaultValue": { | ||
40 | + "name": "S1", | ||
41 | + "tier": "Standard", | ||
42 | + "size": "S1", | ||
43 | + "family": "S", | ||
44 | + "capacity": 1 | ||
45 | + }, | ||
46 | + "metadata": { | ||
47 | + "description": "The SKU of the App Service Plan. Defaults to Standard values." | ||
48 | + } | ||
49 | + }, | ||
50 | + "appServicePlanLocation": { | ||
51 | + "type": "string", | ||
52 | + "metadata": { | ||
53 | + "description": "The location of the App Service Plan." | ||
54 | + } | ||
55 | + }, | ||
56 | + "existingAppServicePlan": { | ||
57 | + "type": "string", | ||
58 | + "defaultValue": "", | ||
59 | + "metadata": { | ||
60 | + "description": "Name of the existing App Service Plan used to create the Web App for the bot." | ||
61 | + } | ||
62 | + }, | ||
63 | + "newWebAppName": { | ||
64 | + "type": "string", | ||
65 | + "defaultValue": "", | ||
66 | + "metadata": { | ||
67 | + "description": "The globally unique name of the Web App. Defaults to the value passed in for \"botId\"." | ||
68 | + } | ||
69 | + } | ||
70 | + }, | ||
71 | + "variables": { | ||
72 | + "defaultAppServicePlanName": "[if(empty(parameters('existingAppServicePlan')), 'createNewAppServicePlan', parameters('existingAppServicePlan'))]", | ||
73 | + "useExistingAppServicePlan": "[not(equals(variables('defaultAppServicePlanName'), 'createNewAppServicePlan'))]", | ||
74 | + "servicePlanName": "[if(variables('useExistingAppServicePlan'), parameters('existingAppServicePlan'), parameters('newAppServicePlanName'))]", | ||
75 | + "resourcesLocation": "[parameters('appServicePlanLocation')]", | ||
76 | + "webAppName": "[if(empty(parameters('newWebAppName')), parameters('botId'), parameters('newWebAppName'))]", | ||
77 | + "siteHost": "[concat(variables('webAppName'), '.azurewebsites.net')]", | ||
78 | + "botEndpoint": "[concat('https://', variables('siteHost'), '/api/messages')]" | ||
79 | + }, | ||
80 | + "resources": [ | ||
81 | + { | ||
82 | + "comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.", | ||
83 | + "type": "Microsoft.Web/serverfarms", | ||
84 | + "condition": "[not(variables('useExistingAppServicePlan'))]", | ||
85 | + "name": "[variables('servicePlanName')]", | ||
86 | + "apiVersion": "2018-02-01", | ||
87 | + "location": "[variables('resourcesLocation')]", | ||
88 | + "sku": "[parameters('newAppServicePlanSku')]", | ||
89 | + "properties": { | ||
90 | + "name": "[variables('servicePlanName')]" | ||
91 | + } | ||
92 | + }, | ||
93 | + { | ||
94 | + "comments": "Create a Web App using an App Service Plan", | ||
95 | + "type": "Microsoft.Web/sites", | ||
96 | + "apiVersion": "2015-08-01", | ||
97 | + "location": "[variables('resourcesLocation')]", | ||
98 | + "kind": "app", | ||
99 | + "dependsOn": [ | ||
100 | + "[resourceId('Microsoft.Web/serverfarms/', variables('servicePlanName'))]" | ||
101 | + ], | ||
102 | + "name": "[variables('webAppName')]", | ||
103 | + "properties": { | ||
104 | + "name": "[variables('webAppName')]", | ||
105 | + "serverFarmId": "[variables('servicePlanName')]", | ||
106 | + "siteConfig": { | ||
107 | + "appSettings": [ | ||
108 | + { | ||
109 | + "name": "WEBSITE_NODE_DEFAULT_VERSION", | ||
110 | + "value": "10.14.1" | ||
111 | + }, | ||
112 | + { | ||
113 | + "name": "MicrosoftAppId", | ||
114 | + "value": "[parameters('appId')]" | ||
115 | + }, | ||
116 | + { | ||
117 | + "name": "MicrosoftAppPassword", | ||
118 | + "value": "[parameters('appSecret')]" | ||
119 | + } | ||
120 | + ], | ||
121 | + "cors": { | ||
122 | + "allowedOrigins": [ | ||
123 | + "https://botservice.hosting.portal.azure.net", | ||
124 | + "https://hosting.onecloud.azure-test.net/" | ||
125 | + ] | ||
126 | + } | ||
127 | + } | ||
128 | + } | ||
129 | + }, | ||
130 | + { | ||
131 | + "apiVersion": "2017-12-01", | ||
132 | + "type": "Microsoft.BotService/botServices", | ||
133 | + "name": "[parameters('botId')]", | ||
134 | + "location": "global", | ||
135 | + "kind": "bot", | ||
136 | + "sku": { | ||
137 | + "name": "[parameters('botSku')]" | ||
138 | + }, | ||
139 | + "properties": { | ||
140 | + "name": "[parameters('botId')]", | ||
141 | + "displayName": "[parameters('botId')]", | ||
142 | + "endpoint": "[variables('botEndpoint')]", | ||
143 | + "msaAppId": "[parameters('appId')]", | ||
144 | + "developerAppInsightsApplicationId": null, | ||
145 | + "developerAppInsightKey": null, | ||
146 | + "publishingCredentials": null, | ||
147 | + "storageResourceId": null | ||
148 | + }, | ||
149 | + "dependsOn": [ | ||
150 | + "[resourceId('Microsoft.Web/sites/', variables('webAppName'))]" | ||
151 | + ] | ||
152 | + } | ||
153 | + ] | ||
154 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/myJsBots/my-own-bot/index.js
0 → 100644
1 | +//This is still work in progress | ||
2 | +/* | ||
3 | +Please report any bugs to nicomwaks@gmail.com | ||
4 | + | ||
5 | +i have added console.log on line 48 | ||
6 | + | ||
7 | + | ||
8 | + | ||
9 | + | ||
10 | + */ | ||
11 | +'use strict' | ||
12 | + | ||
13 | +const express = require('express') | ||
14 | +const bodyParser = require('body-parser') | ||
15 | +const request = require('request') | ||
16 | +const app = express() | ||
17 | + | ||
18 | +app.set('port', (process.env.PORT || 5000)) | ||
19 | + | ||
20 | +// parse application/x-www-form-urlencoded | ||
21 | +app.use(bodyParser.urlencoded({extended: false})) | ||
22 | + | ||
23 | +// parse application/json | ||
24 | +app.use(bodyParser.json()) | ||
25 | + | ||
26 | +// index | ||
27 | +app.get('/', function (req, res) { | ||
28 | + res.send('hello world i am a secret bot') | ||
29 | +}) | ||
30 | + | ||
31 | +// for facebook verification | ||
32 | +app.get('/webhook/', function (req, res) { | ||
33 | + if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') { | ||
34 | + res.send(req.query['hub.challenge']) | ||
35 | + } else { | ||
36 | + res.send('Error, wrong token') | ||
37 | + } | ||
38 | +}) | ||
39 | + | ||
40 | +// to post data | ||
41 | +app.post('/webhook/', function (req, res) { | ||
42 | + let messaging_events = req.body.entry[0].messaging | ||
43 | + for (let i = 0; i < messaging_events.length; i++) { | ||
44 | + let event = req.body.entry[0].messaging[i] | ||
45 | + let sender = event.sender.id | ||
46 | + if (event.message && event.message.text) { | ||
47 | + let text = event.message.text | ||
48 | + if (text === 'Generic'){ | ||
49 | + console.log("welcome to chatbot") | ||
50 | + //sendGenericMessage(sender) | ||
51 | + continue | ||
52 | + } | ||
53 | + sendTextMessage(sender, "Text received, echo: " + text.substring(0, 200)) | ||
54 | + } | ||
55 | + if (event.postback) { | ||
56 | + let text = JSON.stringify(event.postback) | ||
57 | + sendTextMessage(sender, "Postback received: "+text.substring(0, 200), token) | ||
58 | + continue | ||
59 | + } | ||
60 | + } | ||
61 | + res.sendStatus(200) | ||
62 | +}) | ||
63 | + | ||
64 | + | ||
65 | +// recommended to inject access tokens as environmental variables, e.g. | ||
66 | +// const token = process.env.FB_PAGE_ACCESS_TOKEN | ||
67 | +const token = "EAAupaHJrQWABAEqni9O28fmMkpTvq5TO9T9OdPVlEBbj7ZCodF9B8rKeChVGduhGNjxr4zSPXWZA6LKdWZBkCxkuHoYZBmgrmQsrol7RiPoeh8NgvHy60VTcAu5TxdcQdBVSaZBaJIEA8cBbJKuP84CMa8UnroXdZAqALIK8gj1VKGNY3JNvWG" | ||
68 | + | ||
69 | +function sendTextMessage(sender, text) { | ||
70 | + let messageData = { text:text } | ||
71 | + | ||
72 | + request({ | ||
73 | + url: 'https://graph.facebook.com/v2.6/me/messages', | ||
74 | + qs: {access_token:token}, | ||
75 | + method: 'POST', | ||
76 | + json: { | ||
77 | + recipient: {id:sender}, | ||
78 | + message: messageData, | ||
79 | + } | ||
80 | + }, function(error, response, body) { | ||
81 | + if (error) { | ||
82 | + console.log('Error sending messages: ', error) | ||
83 | + } else if (response.body.error) { | ||
84 | + console.log('Error: ', response.body.error) | ||
85 | + } | ||
86 | + }) | ||
87 | +} | ||
88 | + | ||
89 | +function sendGenericMessage(sender) { | ||
90 | + let messageData = { | ||
91 | + "attachment": { | ||
92 | + "type": "template", | ||
93 | + "payload": { | ||
94 | + "template_type": "generic", | ||
95 | + "elements": [{ | ||
96 | + "title": "First card", | ||
97 | + "subtitle": "Element #1 of an hscroll", | ||
98 | + "image_url": "http://messengerdemo.parseapp.com/img/rift.png", | ||
99 | + "buttons": [{ | ||
100 | + "type": "web_url", | ||
101 | + "url": "https://www.messenger.com", | ||
102 | + "title": "web url" | ||
103 | + }, { | ||
104 | + "type": "postback", | ||
105 | + "title": "Postback", | ||
106 | + "payload": "Payload for first element in a generic bubble", | ||
107 | + }], | ||
108 | + }, { | ||
109 | + "title": "Second card", | ||
110 | + "subtitle": "Element #2 of an hscroll", | ||
111 | + "image_url": "http://messengerdemo.parseapp.com/img/gearvr.png", | ||
112 | + "buttons": [{ | ||
113 | + "type": "postback", | ||
114 | + "title": "Postback", | ||
115 | + "payload": "Payload for second element in a generic bubble", | ||
116 | + }], | ||
117 | + }] | ||
118 | + } | ||
119 | + } | ||
120 | + } | ||
121 | + request({ | ||
122 | + url: 'https://graph.facebook.com/v2.6/me/messages', | ||
123 | + qs: {access_token:token}, | ||
124 | + method: 'POST', | ||
125 | + json: { | ||
126 | + recipient: {id:sender}, | ||
127 | + message: messageData, | ||
128 | + } | ||
129 | + }, function(error, response, body) { | ||
130 | + if (error) { | ||
131 | + console.log('Error sending messages: ', error) | ||
132 | + } else if (response.body.error) { | ||
133 | + console.log('Error: ', response.body.error) | ||
134 | + } | ||
135 | + }) | ||
136 | +} | ||
137 | + | ||
138 | +// spin spin sugar | ||
139 | +app.listen(app.get('port'), function() { | ||
140 | + console.log('running on port', app.get('port')) | ||
141 | +}) |
final/myJsBots/my-own-bot/package-lock.json
0 → 100644
This diff could not be displayed because it is too large.
final/myJsBots/my-own-bot/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "my-own-bot", | ||
3 | + "version": "1.0.0", | ||
4 | + "description": "like me", | ||
5 | + "author": "Generated using Microsoft Bot Builder Yeoman generator v4.9.0", | ||
6 | + "license": "MIT", | ||
7 | + "main": "index.js", | ||
8 | + "scripts": { | ||
9 | + "start": "node ./index.js", | ||
10 | + "watch": "nodemon ./index.js", | ||
11 | + "lint": "eslint .", | ||
12 | + "test": "echo \"Error: no test specified\" && exit 1" | ||
13 | + }, | ||
14 | + "repository": { | ||
15 | + "type": "git", | ||
16 | + "url": "https://github.com" | ||
17 | + }, | ||
18 | + "dependencies": { | ||
19 | + "botbuilder": "~4.9.0", | ||
20 | + "dotenv": "^8.2.0", | ||
21 | + "restify": "~8.5.1" | ||
22 | + }, | ||
23 | + "devDependencies": { | ||
24 | + "eslint": "^7.0.0", | ||
25 | + "eslint-config-standard": "^14.1.1", | ||
26 | + "eslint-plugin-import": "^2.20.2", | ||
27 | + "eslint-plugin-node": "^11.1.0", | ||
28 | + "eslint-plugin-promise": "^4.2.1", | ||
29 | + "eslint-plugin-standard": "^4.0.1", | ||
30 | + "nodemon": "~2.0.4" | ||
31 | + } | ||
32 | +} |
final/package-lock.json
0 → 100644
This diff is collapsed. Click to expand it.
final/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "secretbots", | ||
3 | + "version": "1.0.0", | ||
4 | + "description": "", | ||
5 | + "main": "index.js", | ||
6 | + "scripts": { | ||
7 | + "test": "echo \"Error: no test specified\" && exit 1" | ||
8 | + }, | ||
9 | + "author": "", | ||
10 | + "license": "ISC", | ||
11 | + "dependencies": { | ||
12 | + "body-parser": "^1.15.0", | ||
13 | + "express": "^4.13.4", | ||
14 | + "request": "^2.71.0" | ||
15 | + } | ||
16 | +} |
final/server.js
0 → 100644
1 | +"use strict"; | ||
2 | + | ||
3 | +const moment = require('moment'); | ||
4 | +const process = require('process'); | ||
5 | +const async = require('async'); | ||
6 | + | ||
7 | +const express = require('express'); | ||
8 | + | ||
9 | +const AWS = require('aws-sdk'); | ||
10 | +const s3 = new AWS.S3({ | ||
11 | + region: 'us-east-1', | ||
12 | + accessKeyId: 'ASIA265JP6JAKK4AAZFL', | ||
13 | + secretAccessKey: 'CuomIr3gEgtwPcOWSN94mC54iIMMWfXTVSFJXDUf', | ||
14 | + sessionToken: 'FwoGZXIvYXdzEMX//////////wEaDLD1Yk1xhWixp9ZSByK/AbDcW6LYR1EpPLNIqCteTtZtXCoIIFr7b2olxXkKyQUVQGUnf4YJVcmk8PD1/1T9O/MaJIuO0c0tAO2ir31Oa5nsc1QomKEFpAy/girMM3JML5azImFhjMKDGYahUiZWTfiP8oksDWoeEM+HjwEvWzSa5nBBoTlKxa33Gjo/15LL/oHDgN75K/fiHWAJ6Uvey0I1Lu26CjohLbEE9tQ61ymtq4GiO96DSjgSTW4gyrp5R+tn0oLH1A51oLNBfFxsKOvfxu8FMi2RufVY3HSu2JsFVyXMXkMrgDhVA5lZngj2ZW7SQx8No0vfb9zPKuHXxGKjkQY=' | ||
15 | + }); | ||
16 | +var BUCKET = 'oss-project-image-storage'; | ||
17 | +var S3UPparam = { | ||
18 | + Bucket:BUCKET, | ||
19 | + Key:null, | ||
20 | + ACL:'public-read', | ||
21 | + Body:null | ||
22 | +}; | ||
23 | +var S3DOWNparam = { | ||
24 | + Bucket:BUCKET, | ||
25 | + Prefix:null | ||
26 | +}; | ||
27 | + | ||
28 | +const multer = require('multer'); | ||
29 | + | ||
30 | +// tensorflow의 data folder에 저장할 때 multer 설정 | ||
31 | +var storage_data = multer.diskStorage({ | ||
32 | + destination: function (req, file, cb) { | ||
33 | + var dir = req.params.directoryName; | ||
34 | + cb(null, dataFolder + dir + '/'); | ||
35 | + }, | ||
36 | + filename: function (req, file, cb) { | ||
37 | + cb(null, new Date().valueOf() + "_" + file.originalname); | ||
38 | + } | ||
39 | +}); | ||
40 | +var upload_data = multer({ | ||
41 | + storage: storage_data | ||
42 | +}); | ||
43 | + | ||
44 | +// tensorflow의 test folder에 저장할 때 multer 설정 | ||
45 | +var storage_test = multer.diskStorage({ | ||
46 | + destination: function (req, file, cb) { | ||
47 | + var dir = req.params.directoryName; | ||
48 | + cb(null, testFolder); | ||
49 | + }, | ||
50 | + filename: function (req, file, cb) { | ||
51 | + cb(null, "test.jpg"); | ||
52 | + } | ||
53 | +}); | ||
54 | +var upload_test = multer({ | ||
55 | + storage: storage_test | ||
56 | +}); | ||
57 | + | ||
58 | +const bodyParser = require('body-parser'); | ||
59 | +const fs = require('fs'); | ||
60 | +const path = require('path'); | ||
61 | +const pyShell = require('python-shell'); | ||
62 | + | ||
63 | +const PORT = 8080; | ||
64 | +const HOST = '0.0.0.0'; | ||
65 | + | ||
66 | +const app = express(); | ||
67 | + | ||
68 | +const dataFolder = './tensorflow/data/'; | ||
69 | +const testFolder = './tensorflow/test/'; | ||
70 | + | ||
71 | + | ||
72 | +app.set('view engine', 'pug'); | ||
73 | +app.set('views', './views'); | ||
74 | +app.locals.pretty = true | ||
75 | + | ||
76 | +app.use(bodyParser.urlencoded({extended:false})); | ||
77 | + | ||
78 | + | ||
79 | +// tensorflow 학습을 완료한 시간 | ||
80 | +var LearnTime = undefined; | ||
81 | + | ||
82 | + | ||
83 | +// Redirect Root to Home | ||
84 | +app.get('/', (req, res) => { | ||
85 | + res.redirect('./home/'); | ||
86 | +}); | ||
87 | + | ||
88 | + | ||
89 | +// Main Page | ||
90 | +app.get('/home/', (req, res) => { | ||
91 | + // data 폴더 목록을 읽어서 home 화면에 넘겨줌 | ||
92 | + fs.readdir(dataFolder, function(error, filelist){ | ||
93 | + if(error) | ||
94 | + console.log(error); | ||
95 | + res.render('home', {fileList:filelist, learntime:LearnTime}); | ||
96 | + }); | ||
97 | +}); | ||
98 | + | ||
99 | + | ||
100 | +// Directory existence checking | ||
101 | +app.post('/directory_check', (req, res) => { | ||
102 | + | ||
103 | + var dir = req.body.directoryName; // 입력받은 새로운 directory name | ||
104 | + | ||
105 | + // Directory exists | ||
106 | + if(fs.existsSync(dataFolder + dir)) | ||
107 | + { | ||
108 | + // Go back page | ||
109 | + res.render('error_directoryAdd'); | ||
110 | + } | ||
111 | + // Directory doesn't exist | ||
112 | + else | ||
113 | + { | ||
114 | + // Make directory | ||
115 | + fs.mkdirSync(dataFolder + dir); | ||
116 | + console.log('Directory Create: ' + dir); | ||
117 | + res.redirect('/home/' + dir + '/'); | ||
118 | + } | ||
119 | +}); | ||
120 | + | ||
121 | + | ||
122 | +// Basic Directory Page | ||
123 | +app.get('/home/:directoryName/', (req, res) => { | ||
124 | + | ||
125 | + // 임시로 이미지 파일명 목록을 보여주는 코드 | ||
126 | + var directoryName = req.params.directoryName; // 접속한 directory name | ||
127 | + var filelist = new Array(); | ||
128 | + var imagelist = new Array(); | ||
129 | + | ||
130 | + // read directory's file list | ||
131 | + fs.readdirSync(dataFolder + directoryName).forEach(function(file, index){ | ||
132 | + // 확장자 추출 및 이미지 파일인지 체크 | ||
133 | + var fileType = path.extname(file); | ||
134 | + if(fileType == ".jpg" || fileType == ".jpeg") { | ||
135 | + filelist.push(file); | ||
136 | + } | ||
137 | + }); | ||
138 | + S3DOWNparam.Prefix = directoryName + '/'; | ||
139 | + s3.listObjects(S3DOWNparam, function (err, data) { | ||
140 | + if (err) | ||
141 | + console.log(err); | ||
142 | + else { | ||
143 | + data.Contents.forEach(function(image) { | ||
144 | + imagelist.push('https://' + BUCKET + '.s3.amazonaws.com/' + image.Key.replace(' ', '+')); | ||
145 | + }); | ||
146 | + } | ||
147 | + res.render('directory', {directoryName:directoryName, fileList:filelist, imageList:imagelist}); | ||
148 | + }); | ||
149 | +}); | ||
150 | + | ||
151 | + | ||
152 | +// Image Upload Directory Page | ||
153 | +app.post('/home/:directoryName/upload/', upload_data.array('userImage'), (req, res) => { | ||
154 | + var directoryName = req.params.directoryName; | ||
155 | + | ||
156 | + req.files.forEach(function(file) { | ||
157 | + S3UPparam.Key = directoryName + '/' + new Date().valueOf() + "_" + file.originalname; | ||
158 | + S3UPparam.Body = fs.createReadStream(file.path); | ||
159 | + s3.upload(S3UPparam, function (err, result) { | ||
160 | + if (err) | ||
161 | + console.log(err); | ||
162 | + }); | ||
163 | + }); | ||
164 | + | ||
165 | + res.redirect('/home/' + directoryName + '/'); | ||
166 | +}); | ||
167 | + | ||
168 | + | ||
169 | +// Modify Directory name | ||
170 | +app.get('/home/:directoryName/modify/', (req, res) => { | ||
171 | + var directoryName = req.params.directoryName; // 본래 directory 이름 | ||
172 | + var newName = req.query.newName; // 입력받은 수정할 이름 | ||
173 | + | ||
174 | + // exist query.newName | ||
175 | + if (req.query.newName) { | ||
176 | + // modify Directory name | ||
177 | + var Path = dataFolder + directoryName; | ||
178 | + fs.rename(Path, dataFolder + newName, function (err) { | ||
179 | + if (err) { | ||
180 | + console.log("Directory Rename error: " + err); | ||
181 | + } else { | ||
182 | + console.log("Directory Rename: " + directoryName + " -> " + newName); | ||
183 | + } | ||
184 | + }); | ||
185 | + s3.listObjects({Bucket:BUCKET, Prefix: directoryName + '/'}, function(err, data) { | ||
186 | + if (data.Contents.length) { | ||
187 | + async.each(data.Contents, function(file, cb) { | ||
188 | + s3.copyObject({ | ||
189 | + Bucket: BUCKET, | ||
190 | + CopySource: BUCKET + '/' + file.Key, | ||
191 | + Key: file.Key.replace(directoryName, newName) | ||
192 | + }) | ||
193 | + .promise() | ||
194 | + .then(() => | ||
195 | + s3.deleteObject({ | ||
196 | + Bucket: BUCKET, | ||
197 | + Key: file.Key | ||
198 | + }).promise() | ||
199 | + ).catch ((e) => console.error(e)); | ||
200 | + }); | ||
201 | + } | ||
202 | + s3.deleteObject({ | ||
203 | + Bucket: BUCKET, | ||
204 | + Key: directoryName | ||
205 | + }, function(err, data) { | ||
206 | + if (err) console.log(err); | ||
207 | + }); | ||
208 | + }); | ||
209 | + res.redirect('/'); | ||
210 | + } | ||
211 | + else { | ||
212 | + res.render('directoryModifyCheck', {directoryName:JSON.stringify(directoryName)}); | ||
213 | + } | ||
214 | +}); | ||
215 | + | ||
216 | + | ||
217 | +// Delete Directory | ||
218 | +app.get('/home/:directoryName/delete/', (req, res) => { | ||
219 | + var directoryName = req.params.directoryName; | ||
220 | + // exist query.real | ||
221 | + if (req.query.real) { | ||
222 | + // Remove Directory and Files | ||
223 | + var path = dataFolder + directoryName; | ||
224 | + fs.readdirSync(path).forEach(function(file,index){ | ||
225 | + var curPath = path + "/" + file; | ||
226 | + fs.unlinkSync(curPath); | ||
227 | + }); | ||
228 | + fs.rmdirSync(path); | ||
229 | + // Remove S3 Directory and Files | ||
230 | + s3.listObjects({Bucket:BUCKET, Prefix: directoryName + '/'}, function(err, data) { | ||
231 | + if (data.Contents.length) { | ||
232 | + async.each(data.Contents, function(file, cb) { | ||
233 | + s3.deleteObject({ | ||
234 | + Bucket: BUCKET, | ||
235 | + Key: file.Key | ||
236 | + }, function(err, data) { | ||
237 | + if (err) console.log(err); | ||
238 | + }); | ||
239 | + }); | ||
240 | + } | ||
241 | + }); | ||
242 | + | ||
243 | + console.log('Directory Delete: ' + directoryName); | ||
244 | + res.redirect('/'); | ||
245 | + } | ||
246 | + else { | ||
247 | + res.render('directoryDeleteCheck', {directoryName:JSON.stringify(directoryName)}); | ||
248 | + } | ||
249 | +}); | ||
250 | + | ||
251 | + | ||
252 | +// Image Test Page | ||
253 | +app.post('/test', upload_test.single('TestImage'), (req, res) => { | ||
254 | + var results = new Array(); | ||
255 | + | ||
256 | + console.log("Test Start"); | ||
257 | + process.chdir('./tensorflow/'); // move working directory | ||
258 | + | ||
259 | + // retrain_run_inference.py로 test | ||
260 | + pyShell.PythonShell.run('retrain_run_inference.py', null, function (err, result) { | ||
261 | + if (err) { | ||
262 | + console.log('Test error: '+ err); | ||
263 | + } | ||
264 | + else { | ||
265 | + var strArr = result.toString().split('\n'); // result를 줄바꿈 기준으로 자름 | ||
266 | + // 결과만 results에 저장 | ||
267 | + strArr.forEach(function(str) { | ||
268 | + if (str.indexOf('score') > -1) { | ||
269 | + str = str.split('\\n').join(''); | ||
270 | + results = str.split(','); | ||
271 | + for(var i = 0; i < results.length; i++){ | ||
272 | + results[i] = results[i].substring(1); | ||
273 | + } | ||
274 | + } | ||
275 | + }); | ||
276 | + } | ||
277 | + process.chdir('../'); // move working directory | ||
278 | + console.log(results); | ||
279 | + console.log("Test Complete"); | ||
280 | + res.render('testResult', {result:results}); | ||
281 | + }); | ||
282 | +}); | ||
283 | + | ||
284 | + | ||
285 | +// Image Learning | ||
286 | +app.get('/imageLearning', (req, res) => { | ||
287 | + var results = new Array(); | ||
288 | + var tmp = LearnTime; | ||
289 | + | ||
290 | + res.redirect('/home/'); | ||
291 | + | ||
292 | + console.log("Learning Start"); | ||
293 | + process.chdir('./tensorflow/'); // move working directory | ||
294 | + | ||
295 | + // retrain.py로 학습 | ||
296 | + LearnTime = "학습 중..."; | ||
297 | + pyShell.PythonShell.run('retrain.py', null, function (err, result) { | ||
298 | + if (err) { | ||
299 | + console.log('Learning error: '+ err); | ||
300 | + LearnTime = tmp + ', error: 다시 학습 버튼을 눌러주세요'; | ||
301 | + } | ||
302 | + else { | ||
303 | + LearnTime = moment().format('YYYY-MM-DD HH:mm:ss'); // 학습 완료한 시간 저장 | ||
304 | + console.log("Learning Complete"); | ||
305 | + } | ||
306 | + }); | ||
307 | + process.chdir('../'); // move working directory | ||
308 | +}); | ||
309 | + | ||
310 | + | ||
311 | +app.listen(PORT, HOST); | ||
312 | +console.log('Running on http://${HOST}:${POST}'); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/tensorflow/retrain.py
0 → 100644
This diff is collapsed. Click to expand it.
final/tensorflow/retrain_run_inference.py
0 → 100644
1 | +# -*- coding: utf-8 -*- | ||
2 | + | ||
3 | +"""Inception v3 architecture 모델을 retraining한 모델을 이용해서 이미지에 대한 추론(inference)을 진행하는 예제""" | ||
4 | + | ||
5 | +import sys | ||
6 | +import numpy as np | ||
7 | +import tensorflow as tf | ||
8 | + | ||
9 | +imagePath = '' | ||
10 | +modelFullPath = '' | ||
11 | +labelsFullPath = '' | ||
12 | + | ||
13 | +if (len(sys.argv) > 1): | ||
14 | + imagePath = sys.argv[1] + '/test/test.jpg' | ||
15 | + modelFullPath = sys.argv[1] + '/test/output_graph.pb' | ||
16 | + labelsFullPath = sys.argv[1] + '/test/output_labels.txt' | ||
17 | +else: | ||
18 | + imagePath = './test/test.jpg' # 추론을 진행할 이미지 경로 | ||
19 | + modelFullPath = './test/output_graph.pb' # 읽어들일 graph 파일 경로 | ||
20 | + labelsFullPath = './test/output_labels.txt' # 읽어들일 labels 파일 경로 | ||
21 | + | ||
22 | + | ||
23 | +def create_graph(): | ||
24 | + """저장된(saved) GraphDef 파일로부터 graph를 생성하고 saver를 반환한다.""" | ||
25 | + # 저장된(saved) graph_def.pb로부터 graph를 생성한다. | ||
26 | + with tf.gfile.FastGFile(modelFullPath, 'rb') as f: | ||
27 | + graph_def = tf.GraphDef() | ||
28 | + graph_def.ParseFromString(f.read()) | ||
29 | + _ = tf.import_graph_def(graph_def, name='') | ||
30 | + | ||
31 | + | ||
32 | +def run_inference_on_image(): | ||
33 | + answer = None | ||
34 | + | ||
35 | + if not tf.gfile.Exists(imagePath): | ||
36 | + tf.logging.fatal('File does not exist %s', imagePath) | ||
37 | + answer = 'File does not exist ' + imagePath | ||
38 | + return answer | ||
39 | + | ||
40 | + image_data = tf.gfile.FastGFile(imagePath, 'rb').read() | ||
41 | + | ||
42 | + # 저장된(saved) GraphDef 파일로부터 graph를 생성한다. | ||
43 | + create_graph() | ||
44 | + | ||
45 | + with tf.Session() as sess: | ||
46 | + | ||
47 | + softmax_tensor = sess.graph.get_tensor_by_name('final_result:0') | ||
48 | + predictions = sess.run(softmax_tensor, | ||
49 | + {'DecodeJpeg/contents:0': image_data}) | ||
50 | + predictions = np.squeeze(predictions) | ||
51 | + | ||
52 | + top_k = predictions.argsort()[-5:][::-1] # 가장 높은 확률을 가진 5개(top 5)의 예측값(predictions)을 얻는다. | ||
53 | + f = open(labelsFullPath, 'rb') | ||
54 | + lines = f.readlines() | ||
55 | + labels = [str(w).replace("\n", "") for w in lines] | ||
56 | + for node_id in top_k: | ||
57 | + human_string = labels[node_id] | ||
58 | + score = predictions[node_id] | ||
59 | + print('%s (score = %.5f)' % (human_string, score)) | ||
60 | + | ||
61 | + answer = labels[top_k[0]] | ||
62 | + return answer | ||
63 | + | ||
64 | + | ||
65 | +if __name__ == '__main__': | ||
66 | + run_inference_on_image() | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/views/directory.pug
0 → 100644
1 | +doctype html | ||
2 | +html | ||
3 | + head | ||
4 | + meta(charset='utf-8') | ||
5 | + title 파일 업로드 | ||
6 | + | ||
7 | + style | ||
8 | + img | ||
9 | + | display="block" | ||
10 | + | max-width="200px" | ||
11 | + | max-height="200px" | ||
12 | + | width="auto" | ||
13 | + | height="auto" | ||
14 | + | ||
15 | + | ||
16 | + body | ||
17 | + - var DirectoryName=directoryName; | ||
18 | + h1=DirectoryName | ||
19 | + br | ||
20 | + h2 파일 업로드 | ||
21 | + form(action="./upload/" method="POST" enctype="multipart/form-data") | ||
22 | + input(type="file", name="userImage", multiple="multiple", accept=".jpg, .jpeg") | ||
23 | + input(type="submit", value="업로드") | ||
24 | + br | ||
25 | + br | ||
26 | + ul | ||
27 | + - var ImageList=imageList | ||
28 | + - var filelist=fileList | ||
29 | + - var iter=0 | ||
30 | + each Image in ImageList | ||
31 | + div(style="margin-right:10px;") | ||
32 | + img(src=Image) | ||
33 | + li=filelist[iter] | ||
34 | + - iter=iter+1 | ||
35 | + br | ||
36 | + br | ||
37 | + | ||
38 | + | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/views/directoryDeleteCheck.pug
0 → 100644
final/views/directoryModifyCheck.pug
0 → 100644
1 | +script. | ||
2 | + var directoryName= !{directoryName}; | ||
3 | + var result = prompt('새 분류명을 입력하세요. (기존: ' + directoryName + ')'); | ||
4 | + | ||
5 | + if (result) { | ||
6 | + location.href = '.?newName=' + result; | ||
7 | + } else { | ||
8 | + alert('분류명을 수정하지 않습니다.'); | ||
9 | + history.back(); | ||
10 | + } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/views/error_directoryAdd.pug
0 → 100644
final/views/home.pug
0 → 100644
1 | +doctype html | ||
2 | +html | ||
3 | + head | ||
4 | + meta(charset='utf-8') | ||
5 | + title 분류 리스트 | ||
6 | + | ||
7 | + | ||
8 | + | ||
9 | + body | ||
10 | + form(action="../directory_check" method="post") | ||
11 | + p 새로 만들 분류명: | ||
12 | + input(name="directoryName", type="text") | ||
13 | + input(type="submit", value="생성") | ||
14 | + br | ||
15 | + br | ||
16 | + | ||
17 | + form(action="../test" method="post" enctype="multipart/form-data") | ||
18 | + p 테스트할 이미지: | ||
19 | + input(name="TestImage", type="file", accept=".jpg, .jpeg") | ||
20 | + input(type="submit", value="테스트") | ||
21 | + br | ||
22 | + br | ||
23 | + br | ||
24 | + | ||
25 | + div(style="margin-right:10px; float:left;") | ||
26 | + form(action="../imageLearning" method="get") | ||
27 | + input(type="submit", value="이미지 학습시키기" style="font-size:24px; font-weight:bold") | ||
28 | + | ||
29 | + - var learnTime=learntime | ||
30 | + div(style="margin-right:30px;") | ||
31 | + p="(최근 학습 시간: " + learnTime + ")" | ||
32 | + | ||
33 | + br | ||
34 | + | ||
35 | + ul | ||
36 | + - var folderList=fileList | ||
37 | + each folder in folderList | ||
38 | + div(style="margin-right:30px; float:left;") | ||
39 | + li | ||
40 | + a(href="./"+folder+"/")=folder | ||
41 | + | ||
42 | + div(style="margin-right:5px; float:left;") | ||
43 | + form(action="./"+folder+"/modify/" method="get") | ||
44 | + input(type="submit", value="수정") | ||
45 | + | ||
46 | + div | ||
47 | + form(action="./"+folder+"/delete/" method="get") | ||
48 | + input(type="submit", value="삭제") | ||
49 | + br | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
final/views/testResult.pug
0 → 100644
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment