├── [6]chatbot-project
├── firebase.json
├── .firebaserc
└── functions
│ ├── package.json
│ └── index.js
├── [5]chat-project
├── package-lock.json
├── polymer.json
├── database-rules.json
├── .firebaserc
├── manifest.json
├── storage.rules
├── firebase.json
├── functions
│ ├── package.json
│ └── index.js
├── index.html
├── bower.json
├── README.md
├── test
│ └── chat-project-app
│ │ └── chat-project-app_test.html
└── src
│ └── chat-project-app
│ ├── chat-msg.html
│ ├── chat-project-app.html
│ └── view-room.html
├── solid_cover.jpg
├── [2]pwa-youtube
├── polymer.json
├── manifest.json
├── index.html
├── bower.json
├── README.md
├── src
│ └── pwa-youtube-app
│ │ ├── video-page.html
│ │ ├── pwa-youtube-app.html
│ │ └── list-page.html
└── test
│ └── pwa-youtube-app
│ └── pwa-youtube-app_test.html
├── [8]music-project
├── client
│ ├── polymer.json
│ ├── manifest.json
│ ├── bower.json
│ ├── index.html
│ ├── README.md
│ ├── test
│ │ └── client-app
│ │ │ └── client-app_test.html
│ └── src
│ │ └── client-app
│ │ └── client-app.html
├── package.json
├── app.js
└── dialogflow.js
├── [7]mapbot-project
├── client
│ ├── polymer.json
│ ├── manifest.json
│ ├── bower.json
│ ├── index.html
│ ├── README.md
│ ├── test
│ │ └── client-app
│ │ │ └── client-app_test.html
│ └── src
│ │ └── client-app
│ │ └── client-app.html
├── package.json
├── app.js
├── api.js
├── dialogflow.js
└── dialogflowv2.js
├── README.md
├── [9]coin-project
├── package.json
├── app.js
├── api.js
└── clova.js
├── .gitignore
└── .gitattributes
/[6]chatbot-project/firebase.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/[5]chat-project/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "lockfileVersion": 1
3 | }
4 |
--------------------------------------------------------------------------------
/solid_cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bjpublic/easychatbot/master/solid_cover.jpg
--------------------------------------------------------------------------------
/[6]chatbot-project/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "bookproject-e57f3"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/[2]pwa-youtube/polymer.json:
--------------------------------------------------------------------------------
1 | {
2 | "lint": {
3 | "rules": [
4 | "polymer-2"
5 | ]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/[5]chat-project/polymer.json:
--------------------------------------------------------------------------------
1 | {
2 | "lint": {
3 | "rules": [
4 | "polymer-2"
5 | ]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/[8]music-project/client/polymer.json:
--------------------------------------------------------------------------------
1 | {
2 | "lint": {
3 | "rules": [
4 | "polymer-2"
5 | ]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/[7]mapbot-project/client/polymer.json:
--------------------------------------------------------------------------------
1 | {
2 | "lint": {
3 | "rules": [
4 | "polymer-2"
5 | ]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/[5]chat-project/database-rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | ".read": "auth != null",
4 | ".write": "auth != null"
5 | }
6 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 누구나 쉽게 배우는 챗봇 서비스
2 |
3 | 
4 |
--------------------------------------------------------------------------------
/[5]chat-project/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "testdemo-staging": "testdemo-d7b23",
4 | "default": "testdemo-d7b23"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/[2]pwa-youtube/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pwa-youtube",
3 | "short_name": "pwa-youtube",
4 | "start_url": "/",
5 | "display": "standalone"
6 | }
7 |
--------------------------------------------------------------------------------
/[7]mapbot-project/client/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "short_name": "client",
4 | "start_url": "/",
5 | "display": "standalone"
6 | }
7 |
--------------------------------------------------------------------------------
/[8]music-project/client/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "short_name": "client",
4 | "start_url": "/",
5 | "display": "standalone"
6 | }
7 |
--------------------------------------------------------------------------------
/[5]chat-project/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chat-project",
3 | "short_name": "chat-project",
4 | "start_url": "/",
5 | "display": "standalone"
6 | }
7 |
--------------------------------------------------------------------------------
/[5]chat-project/storage.rules:
--------------------------------------------------------------------------------
1 | service firebase.storage {
2 | match /b/{bucket}/o {
3 | match /{userId}/{fileName} {
4 | allow write: if request.auth.uid == userId;
5 | allow read;
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/[9]coin-project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "coin-project",
3 | "version": "1.0.0",
4 | "description": "coin-project",
5 | "main": "app.js",
6 | "author": "Will Park",
7 | "dependencies": {
8 | "body-parser": "^1.18.2",
9 | "express": "^4.16.2",
10 | "request": "^2.83.0"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/[8]music-project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "music-project",
3 | "version": "1.0.0",
4 | "description": "music-project",
5 | "main": "app.js",
6 | "author": "WillPark",
7 | "dependencies": {
8 | "body-parser": "^1.18.2",
9 | "express": "^4.16.3",
10 | "request": "^2.85.0"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows thumbnail cache files
2 | Thumbs.db
3 | ehthumbs.db
4 | ehthumbs_vista.db
5 |
6 | # Folder config file
7 | Desktop.ini
8 |
9 | # Recycle Bin used on file shares
10 | $RECYCLE.BIN/
11 |
12 | # Windows Installer files
13 | *.cab
14 | *.msi
15 | *.msm
16 | *.msp
17 |
18 | # Windows shortcuts
19 | *.lnk
20 |
21 | # =========================
22 | # Operating System Files
23 | # =========================
24 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/[8]music-project/client/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "main": "index.html",
4 | "dependencies": {
5 | "polymer": "Polymer/polymer#^2.0.0",
6 | "paper-input": "PolymerElements/paper-input#^2.2.0",
7 | "paper-button": "PolymerElements/paper-button#^2.1.0"
8 | },
9 | "devDependencies": {
10 | "web-component-tester": "Polymer/web-component-tester#^6.0.0",
11 | "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/[7]mapbot-project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mapbot-project",
3 | "version": "1.0.0",
4 | "description": "mapbot-project",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "WillPark",
10 | "dependencies": {
11 | "body-parser": "^1.18.2",
12 | "dialogflow": "^0.1.0",
13 | "express": "^4.16.3",
14 | "firebase-admin": "^5.11.0",
15 | "request": "^2.85.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/[5]chat-project/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | // If you went through the "Realtime Database Security Rules" step.
3 | "database": {
4 | "rules": "database-rules.json"
5 | },
6 | // If you went through the "Storage Security Rules" step.
7 | "storage": {
8 | "rules": "storage.rules"
9 | },
10 | "hosting": {
11 | "public": "./",
12 | "ignore": [
13 | "firebase.json",
14 | "database-rules.json",
15 | "storage.rules"
16 | ]
17 | }
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------
/[8]music-project/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const bodyParser = require('body-parser');
3 | const app = express();
4 | app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
5 | app.use(bodyParser.json());
6 |
7 | app.use((err, req, res, next) => next());
8 |
9 | app.use('/web', express.static(__dirname + '/client'));
10 |
11 | require('./dialogflow')(app);
12 |
13 | const server = app.listen(3000, function(){
14 | console.log("Express server has started on port 3000")
15 | });
--------------------------------------------------------------------------------
/[6]chatbot-project/functions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "functions",
3 | "description": "Cloud Functions for Firebase",
4 | "scripts": {
5 | "serve": "firebase serve --only functions",
6 | "shell": "firebase experimental:functions:shell",
7 | "start": "npm run shell",
8 | "deploy": "firebase deploy --only functions",
9 | "logs": "firebase functions:log"
10 | },
11 | "dependencies": {
12 | "actions-on-google": "^1.9.0",
13 | "firebase-admin": "~5.4.2",
14 | "firebase-functions": "^0.9.0"
15 | },
16 | "private": true
17 | }
18 |
--------------------------------------------------------------------------------
/[9]coin-project/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const bodyParser = require('body-parser');
3 | const app = express();
4 | app.use(bodyParser.json());
5 |
6 | app.use((err, req, res, next) => next());
7 |
8 | require('./api')(app);
9 | require('./clova')(app);
10 |
11 | // catch 404 and forward to error handler
12 | app.use((req, res, next) => {
13 | const err = new Error('Not Found');
14 | err.status = 404;
15 | next(err);
16 | });
17 |
18 | const server = app.listen(3000, function(){
19 | console.log("Express server has started on port 3000")
20 | });
--------------------------------------------------------------------------------
/[7]mapbot-project/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const bodyParser = require('body-parser');
3 | const app = express();
4 | app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
5 | app.use(bodyParser.json())
6 |
7 | app.use((err, req, res, next) => next());
8 |
9 | app.use('/web', express.static(__dirname + '/client'));
10 |
11 | // for setting data on server
12 | // require('./api')(app);
13 | // app.putGhData();
14 | require('./dialogflow')(app);
15 |
16 | app.listen(4000, () => {
17 | console.log('Express server listening on port 4000');
18 | });
19 |
--------------------------------------------------------------------------------
/[7]mapbot-project/client/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "main": "index.html",
4 | "dependencies": {
5 | "polymer": "Polymer/polymer#^2.0.0",
6 | "google-map": "GoogleWebComponents/google-map#^2.0.4",
7 | "polymerfire": "firebase/polymerfire#^2.2.1",
8 | "paper-input": "PolymerElements/paper-input#^2.2.0",
9 | "paper-button": "PolymerElements/paper-button#^2.1.0"
10 | },
11 | "devDependencies": {
12 | "web-component-tester": "Polymer/web-component-tester#^6.0.0",
13 | "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/[5]chat-project/functions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "functions",
3 | "description": "Cloud Functions for Firebase",
4 | "scripts": {
5 | "serve": "firebase serve --only functions",
6 | "shell": "firebase experimental:functions:shell",
7 | "start": "npm run shell",
8 | "deploy": "firebase deploy --only functions",
9 | "logs": "firebase functions:log"
10 | },
11 | "dependencies": {
12 | "@google-cloud/storage": "^1.6.0",
13 | "@google-cloud/vision": "^0.16.0",
14 | "firebase-admin": "^5.11.0",
15 | "firebase-functions": "^0.8.2"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/[2]pwa-youtube/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | pwa-youtube
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/[5]chat-project/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | chat-project
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/[5]chat-project/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chat-project",
3 | "main": "index.html",
4 | "dependencies": {
5 | "polymer": "Polymer/polymer#^2.0.0",
6 | "paper-input": "PolymerElements/paper-input#^2.0.5",
7 | "paper-button": "PolymerElements/paper-button#^2.0.0",
8 | "paper-fab": "PolymerElements/paper-fab#^2.0.0",
9 | "iron-list": "PolymerElements/iron-list#^2.0.12",
10 | "polymerfire": "firebase/polymerfire#^2.2.1",
11 | "iron-icons": "PolymerElements/iron-icons#^2.0.1",
12 | "iron-image": "PolymerElements/iron-image#^2.2.0"
13 | },
14 | "devDependencies": {
15 | "web-component-tester": "Polymer/web-component-tester#^6.0.0",
16 | "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/[8]music-project/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | client
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/[2]pwa-youtube/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pwa-youtube",
3 | "main": "index.html",
4 | "dependencies": {
5 | "polymer": "Polymer/polymer#^2.0.0",
6 | "app-layout": "PolymerElements/app-layout#^2.0.4",
7 | "app-route": "PolymerElements/app-route#^2.0.3",
8 | "iron-pages": "PolymerElements/iron-pages#^2.0.1",
9 | "iron-flex-layout": "PolymerElements/iron-flex-layout#^2.0.1",
10 | "iron-ajax": "PolymerElements/iron-ajax#^2.1.3",
11 | "iron-list": "PolymerElements/iron-list#^2.0.13",
12 | "iron-scroll-threshold": "PolymerElements/iron-scroll-threshold#^2.0.0",
13 | "google-youtube": "GoogleWebComponents/google-youtube#^2.0.0"
14 | },
15 | "devDependencies": {
16 | "web-component-tester": "Polymer/web-component-tester#^6.0.0",
17 | "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/[7]mapbot-project/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | mapbot-project
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/[5]chat-project/README.md:
--------------------------------------------------------------------------------
1 | # \
2 |
3 |
4 |
5 | ## Install the Polymer-CLI
6 |
7 | First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. Then run `polymer serve` to serve your application locally.
8 |
9 | ## Viewing Your Application
10 |
11 | ```
12 | $ polymer serve
13 | ```
14 |
15 | ## Building Your Application
16 |
17 | ```
18 | $ polymer build
19 | ```
20 |
21 | This will create builds of your application in the `build/` directory, optimized to be served in production. You can then serve the built versions by giving `polymer serve` a folder to serve from:
22 |
23 | ```
24 | $ polymer serve build/default
25 | ```
26 |
27 | ## Running Tests
28 |
29 | ```
30 | $ polymer test
31 | ```
32 |
33 | Your application is already set up to be tested via [web-component-tester](https://github.com/Polymer/web-component-tester). Run `polymer test` to run your application's test suite locally.
34 |
--------------------------------------------------------------------------------
/[7]mapbot-project/client/README.md:
--------------------------------------------------------------------------------
1 | # \
2 |
3 |
4 |
5 | ## Install the Polymer-CLI
6 |
7 | First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. Then run `polymer serve` to serve your application locally.
8 |
9 | ## Viewing Your Application
10 |
11 | ```
12 | $ polymer serve
13 | ```
14 |
15 | ## Building Your Application
16 |
17 | ```
18 | $ polymer build
19 | ```
20 |
21 | This will create builds of your application in the `build/` directory, optimized to be served in production. You can then serve the built versions by giving `polymer serve` a folder to serve from:
22 |
23 | ```
24 | $ polymer serve build/default
25 | ```
26 |
27 | ## Running Tests
28 |
29 | ```
30 | $ polymer test
31 | ```
32 |
33 | Your application is already set up to be tested via [web-component-tester](https://github.com/Polymer/web-component-tester). Run `polymer test` to run your application's test suite locally.
34 |
--------------------------------------------------------------------------------
/[8]music-project/client/README.md:
--------------------------------------------------------------------------------
1 | # \
2 |
3 |
4 |
5 | ## Install the Polymer-CLI
6 |
7 | First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. Then run `polymer serve` to serve your application locally.
8 |
9 | ## Viewing Your Application
10 |
11 | ```
12 | $ polymer serve
13 | ```
14 |
15 | ## Building Your Application
16 |
17 | ```
18 | $ polymer build
19 | ```
20 |
21 | This will create builds of your application in the `build/` directory, optimized to be served in production. You can then serve the built versions by giving `polymer serve` a folder to serve from:
22 |
23 | ```
24 | $ polymer serve build/default
25 | ```
26 |
27 | ## Running Tests
28 |
29 | ```
30 | $ polymer test
31 | ```
32 |
33 | Your application is already set up to be tested via [web-component-tester](https://github.com/Polymer/web-component-tester). Run `polymer test` to run your application's test suite locally.
34 |
--------------------------------------------------------------------------------
/[2]pwa-youtube/README.md:
--------------------------------------------------------------------------------
1 | # \
2 |
3 | # 2장 도구2. 폴리머(Polymer) - PWA 유투브 웹앱 만들기
4 |
5 | ## Install the Polymer-CLI
6 |
7 | First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. Then run `polymer serve` to serve your application locally.
8 |
9 | ## Viewing Your Application
10 |
11 | ```
12 | $ polymer serve
13 | ```
14 |
15 | ## Building Your Application
16 |
17 | ```
18 | $ polymer build
19 | ```
20 |
21 | This will create builds of your application in the `build/` directory, optimized to be served in production. You can then serve the built versions by giving `polymer serve` a folder to serve from:
22 |
23 | ```
24 | $ polymer serve build/default
25 | ```
26 |
27 | ## Running Tests
28 |
29 | ```
30 | $ polymer test
31 | ```
32 |
33 | Your application is already set up to be tested via [web-component-tester](https://github.com/Polymer/web-component-tester). Run `polymer test` to run your application's test suite locally.
34 |
--------------------------------------------------------------------------------
/[8]music-project/dialogflow.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 |
3 | const request = require('request');
4 | const TOKEN = '[dialogflow v1 TOKEN]';
5 |
6 |
7 | app.post('/process', (req, res) => {
8 | const query = req.body.query;
9 |
10 | if(!query){
11 | res.json({flag: 0});
12 | return;
13 | }
14 |
15 | const session_id = 'my_session_id';
16 | const language = 'ko'
17 |
18 | const api_url = `https://api.dialogflow.com/v1/query?v=20170712&lang=${language}&sessionId=${session_id}&query=${query}`
19 |
20 | const options = {
21 | url: encodeURI(api_url),
22 | headers: {
23 | 'Authorization': "Bearer "+TOKEN,
24 | 'Content-Type': 'application/x-www-form-urlencoded'
25 | }
26 | };
27 | request.get(options, function (error, response, body) {
28 | if (!error) {
29 | const objResult = JSON.parse(body);
30 | res.json({flag: 1, data: objResult.result.parameters});
31 |
32 | } else {
33 | console.error("e:"+error);
34 | }
35 | });
36 |
37 | });
38 |
39 | }
--------------------------------------------------------------------------------
/[2]pwa-youtube/src/pwa-youtube-app/video-page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
15 |
22 |
23 |
24 |
25 |
26 |
51 |
52 |
--------------------------------------------------------------------------------
/[5]chat-project/functions/index.js:
--------------------------------------------------------------------------------
1 | const functions = require('firebase-functions');
2 | const gcs = require('@google-cloud/storage')();
3 | const vision = require('@google-cloud/vision');
4 | const client = new vision.ImageAnnotatorClient();
5 | const admin = require('firebase-admin');
6 | admin.initializeApp(functions.config().firebase);
7 |
8 |
9 | exports.addWelcomeMessages = functions.auth.user().onCreate(event => {
10 | const user = event.data;
11 | const fullName = user.displayName || 'Anonymous';
12 |
13 | return admin.database().ref('messages').push({
14 | ctype: 0,
15 | username: 'notify',
16 | content: `${fullName} 님이 들어왔습니다!!`
17 | }).then(() => console.log('Complete...'));
18 | });
19 |
20 |
21 | exports.analyzeImage = functions.storage.object().onChange(event => {
22 | const object = event.data;
23 | if (object.resourceState === 'not_exists') {
24 | return console.log('deletion event.');
25 | } else if (!object.name) {
26 | return console.log('deploy event.');
27 | }
28 |
29 | const imageUri = `gs://${object.bucket}/${object.name}`;
30 |
31 | return client
32 | .labelDetection(imageUri)
33 | .then(results => {
34 | const labels = results[0].labelAnnotations;
35 |
36 | admin.database().ref('messages').push({
37 | ctype: 0,
38 | username: 'notify',
39 | content: `이 이미지는 ${labels[0].description} 입니다`
40 | });
41 |
42 | })
43 | .catch(err => {
44 | console.error('error:', err);
45 | });
46 |
47 | });
--------------------------------------------------------------------------------
/[2]pwa-youtube/src/pwa-youtube-app/pwa-youtube-app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
23 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
49 |
50 |
--------------------------------------------------------------------------------
/[7]mapbot-project/client/test/client-app/client-app_test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | client-app test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/[8]music-project/client/test/client-app/client-app_test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | client-app test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/[2]pwa-youtube/test/pwa-youtube-app/pwa-youtube-app_test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | pwa-youtube-app test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/[5]chat-project/test/chat-project-app/chat-project-app_test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | chat-project-app test
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/[5]chat-project/src/chat-project-app/chat-msg.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
41 |
42 |
43 |
44 |

45 |
[[username]] :
46 |
47 |
48 | [[content]]
49 |
50 |
51 |
52 |
53 |
54 |
[[currenttime]]
55 |
56 |
57 |
58 |
80 |
--------------------------------------------------------------------------------
/[9]coin-project/api.js:
--------------------------------------------------------------------------------
1 | module.exports = (app) => {
2 |
3 | const request = require('request');
4 |
5 | ///// korbit
6 | const getKorbitData = (symbol) => {
7 | return new Promise((resolve, reject) => {
8 | request.get(`https://api.korbit.co.kr/v1/ticker?currency_pair=${symbol}_krw`,
9 | function(error, response, body) {
10 | if(error){
11 | reject();
12 | return;
13 | }
14 |
15 | const data = JSON.parse(body);
16 |
17 | resolve(data.last);
18 | });
19 | });
20 | }
21 |
22 | const getBitfinanceData = (symbol) => {
23 | return new Promise((resolve, reject) => {
24 | request.get(`https://api.bitfinex.com/v1/pubticker/${symbol}usd`,
25 | function(error, response, body) {
26 | if(error) {
27 | reject();
28 | return;
29 | }
30 |
31 | const data = JSON.parse(body);
32 |
33 | resolve(data.last_price);
34 | });
35 | });
36 | }
37 |
38 |
39 | const getExchangeRate = () => {
40 | return new Promise((resolve, reject) => {
41 | request.get('https://api.fixer.io/latest?symbols=USD,KRW',
42 | function(error, response, body) {
43 | if(error) {
44 | reject();
45 | return;
46 | }
47 |
48 | const data = JSON.parse(body);
49 |
50 | resolve(data);
51 | });
52 | });
53 | }
54 |
55 |
56 | app.getPremium = () => {
57 | return new Promise((resolve, reject) => {
58 | Promise.all([getKorbitData('btc'), getBitfinanceData('btc'), getExchangeRate()]).then((values) => {
59 | const ko_krw = values[0];
60 | const en_usd = values[1];
61 |
62 | const krw_rate = values[2].rates.KRW;
63 | const usd_rate = values[2].rates.USD;
64 |
65 | const premium_price = ko_krw - (en_usd * krw_rate / usd_rate);
66 | const premium_percent = premium_price*100/ko_krw;
67 |
68 | const result = {premium_price, premium_percent};
69 | resolve(result);
70 | });
71 | });
72 |
73 | }
74 |
75 | app.getPrice = (symbol) => {
76 | return new Promise((resolve, reject) => {
77 | getKorbitData(symbol).then((value) => {
78 | const result = {value};
79 | resolve(result);
80 | });
81 | });
82 | }
83 |
84 | }
--------------------------------------------------------------------------------
/[5]chat-project/src/chat-project-app/chat-project-app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 | Hello [[prop1]]!
14 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | [[error.code]]: [[error.message]]
29 |
30 |
31 |
65 |
66 |
--------------------------------------------------------------------------------
/[6]chatbot-project/functions/index.js:
--------------------------------------------------------------------------------
1 | const functions = require('firebase-functions');
2 |
3 | const admin = require('firebase-admin');
4 | admin.initializeApp(functions.config().firebase);
5 |
6 | const DialogflowApp = require('actions-on-google').DialogflowApp;
7 |
8 |
9 | exports.assistant = functions.https
10 | .onRequest((request, response) => {
11 |
12 | const app = new DialogflowApp({request: request, response: response});
13 | app.handleRequest(handlerRequest);
14 |
15 |
16 | function handlerRequest(assistant) {
17 | const location = assistant.getArgument('location');
18 | const time = assistant.getArgument('time');
19 | const info = assistant.getArgument('info');
20 | const speakers = assistant.getArgument('speakers');
21 |
22 | const ticket = assistant.getArgument('ticket');
23 | const price = assistant.getArgument('price');
24 | const discount = assistant.getArgument('discount');
25 | const payment = assistant.getArgument('payment');
26 |
27 | let message,
28 | statements = [];
29 |
30 | getGroupInfo({
31 | onSuccess: function(data) {
32 |
33 | if(location && location.length>0){
34 | statements.push("행사 주소는 "+data.info.location + " 입니다.");
35 | }
36 |
37 | if(time && time.length>0) {
38 | statements.push("행사 시작 시간은 "+data.info.time + " 입니다.");
39 | }
40 |
41 | if(info && info.length>0) {
42 | statements.push("이 행사는 "+data.info.info + " 입니다.");
43 | }
44 |
45 | if(speakers && speakers.length>0){
46 | statements.push("행사 스피커 리스트는 "+data.info.speakers + " 입니다.");
47 | }
48 |
49 | if(ticket && ticket.length>0){
50 | statements.push("티켓 정보에 대해 알려드릴게요.");
51 | }
52 |
53 | if(price && price.length>0){
54 | statements.push("티켓 가격은 "+data.info.price + " 입니다.");
55 | }
56 |
57 | if(discount && discount.length>0){
58 | statements.push("할인 정보 : "+data.info.discount);
59 | }
60 |
61 | if(payment && payment.length>0){
62 | statements.push("결제 정보 : "+data.info.payment);
63 | }
64 |
65 | message = statements.join(" ");
66 |
67 | response.json({ 'speech': message, 'displayText': message });
68 | }
69 | });
70 | }
71 | });
72 |
73 |
74 | function getGroupInfo(options) {
75 | admin.database().ref('/group-info')
76 | .once('value')
77 | .then(function(snapshot){
78 | const info = snapshot.val();
79 | options.onSuccess({info: info});
80 | });
81 | }
82 |
--------------------------------------------------------------------------------
/[7]mapbot-project/api.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 |
3 | const admin = require("firebase-admin");
4 | const serviceAccount = require("./ghbot-762ee-firebase-adminsdk-d03q9-9a4e98e209.json");
5 |
6 | admin.initializeApp({
7 | credential: admin.credential.cert(serviceAccount),
8 | databaseURL: "https://ghbot-762ee.firebaseio.com/"
9 | });
10 |
11 | const request = require('request');
12 | const client_id = '[NAVER_CLIENT_ID]'; // NAVER CLIENT ID
13 | const client_secret = '[NAVER_SECRET_IT]'; // NAVER SECRET ID
14 |
15 |
16 | function getGeocode(address){
17 | return new Promise((resolve, reject) => {
18 | const api_url = 'https://openapi.naver.com/v1/map/geocode?query=' + encodeURI(address); // json
19 |
20 | const options = {
21 | url: api_url,
22 | headers: {'X-Naver-Client-Id':client_id, 'X-Naver-Client-Secret': client_secret}
23 | };
24 | request.get(options, function (error, response, body) {
25 | if (!error && response.statusCode == 200) {
26 | resolve(body);
27 | } else {
28 | reject(error);
29 | }
30 | });
31 | });
32 | }
33 |
34 | function getReverseGeocode(lat, lng){
35 | return new Promise((resolve, reject) => {
36 | const api_key = '[GOOGLE_API_KEY]'; // GOOGLE API KEY
37 | const api_url = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${api_key}`;
38 |
39 | request.get({url: api_url}, function (error, response, body) {
40 | if (!error && response.statusCode == 200) {
41 | resolve(body);
42 | } else {
43 | reject(error);
44 | }
45 | });
46 | });
47 | }
48 |
49 | app.putGhData = function() {
50 | const fs = require('fs');
51 |
52 | fs.readFile(__dirname+'/ghlist.json', 'utf8', function(err, data) {
53 |
54 | const jsonObj = JSON.parse(data);
55 | const rows = jsonObj.result.body.rows[0].row;
56 |
57 |
58 | for(var i=0; i {
68 | const resultObj = JSON.parse(result);
69 | const lat = resultObj.result.items[0].point.y;
70 | const lng = resultObj.result.items[0].point.x;
71 |
72 | getReverseGeocode(lat,lng).then((data) => {
73 | const jsonObj = JSON.parse(data);
74 | const gh_enaddress = jsonObj.results[0].formatted_address;
75 |
76 | writeData(gh_koname, gh_enname, gh_address, gh_enaddress, tel, lat, lng);
77 | }).catch((error) => {
78 | console.error(error);
79 | });
80 | }).catch((error) => {
81 | console.error(error);
82 | });
83 | }
84 |
85 | });
86 | }
87 |
88 | function writeData(name, enname, address, en_address, phone, lat, lng){
89 | admin.database().ref().child("guesthouses").push({
90 | name,
91 | enname,
92 | address,
93 | en_address,
94 | phone,
95 | lat,
96 | lng
97 | });
98 | }
99 |
100 |
101 | }
--------------------------------------------------------------------------------
/[7]mapbot-project/dialogflow.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 |
3 | const request = require('request');
4 | const admin = require("firebase-admin");
5 | const serviceAccount = require("[어드민 SDK JSON 패스]");
6 |
7 | admin.initializeApp({
8 | credential: admin.credential.cert(serviceAccount),
9 | databaseURL: "https://ghbot-762ee.firebaseio.com/"
10 | });
11 |
12 | const TOKEN = '[dialogflow v1 Token]';
13 |
14 | app.post('/process', (req, res) => {
15 | const query = req.body.query;
16 |
17 | if(!query){
18 | res.json({flag: 0});
19 | return;
20 | }
21 |
22 | const session_id = 'my_session_id';
23 | const language = 'en'
24 |
25 | const api_url = `https://api.dialogflow.com/v1/query?v=20170712&lang=${language}&sessionId=${session_id}&query=${query}`
26 |
27 | const options = {
28 | url: encodeURI(api_url),
29 | headers: {
30 | 'Authorization': "Bearer "+TOKEN,
31 | 'Content-Type': 'application/x-www-form-urlencoded'
32 | }
33 | };
34 | request.get(options, function (error, response, body) {
35 | if (!error) {
36 | const objResult = JSON.parse(body);
37 |
38 | const intentName = objResult.result.metadata.intentName;
39 |
40 | if(intentName=='near_location'){
41 | const location = objResult.result.parameters.location["street-address"];
42 |
43 | getGeocode(location).then((data) => {
44 | const jsonObj = JSON.parse(data);
45 |
46 | res.json({flag: 1, type: 0, data: jsonObj.results[0].geometry.location});
47 | }).catch((err) =>{
48 | console.error(err);
49 | res.json({flag: 0});
50 | });
51 |
52 | } else if(intentName=='find_location'){
53 | const ghname = objResult.result.parameters.gh_name;
54 |
55 | findGhInfo(ghname).then((data) => {
56 |
57 | res.json({flag: 1, type: 1, data: data})
58 | }).catch((err) =>{
59 | console.error(err);
60 | res.json({flag: 0});
61 | });
62 | } else {
63 | console.log(` No intent matched.`);
64 | res.json({flag: 0});
65 | }
66 |
67 | } else {
68 | console.error('error:', err);
69 | res.json({flag: 0});
70 | }
71 | });
72 |
73 | });
74 |
75 | function getGeocode(addr){
76 | return new Promise((resolve, reject) => {
77 | const address = encodeURI(addr);
78 |
79 | const api_key = '[맵 API 키]';
80 | const api_url = `https://maps.googleapis.com/maps/api/geocode/json?address=${address}&key=${api_key}`;
81 |
82 | request.get({url: api_url}, function (error, response, body) {
83 | if (!error && response.statusCode == 200) {
84 | resolve(body);
85 | } else {
86 | reject(error);
87 | }
88 | });
89 | });
90 | }
91 |
92 |
93 | function findGhInfo(ghname){
94 | return new Promise((resolve, reject) => {
95 | admin.database().ref('/guesthouses')
96 | .once('value', function(snapshot) {
97 | snapshot.forEach(function(childSnapshot) {
98 | var childKey = childSnapshot.key;
99 | var info = childSnapshot.val();
100 |
101 | if(info.enname == ghname){
102 | resolve(info);
103 | return;
104 | }
105 | });
106 |
107 | reject("no guesthouse");
108 | });
109 | });
110 | }
111 |
112 |
113 | }
--------------------------------------------------------------------------------
/[7]mapbot-project/client/src/client-app/client-app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
28 |
34 |
35 |
36 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 | {{marker.name}} - {{marker.enname}}
53 | {{marker.en_address}}
54 |
55 |
56 |
57 |
58 |
59 |
121 |
122 |
--------------------------------------------------------------------------------
/[7]mapbot-project/dialogflowv2.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 |
3 | const request = require('request');
4 | const admin = require("firebase-admin");
5 | const serviceAccount = require("[어드민 SDK JSON 패스]");
6 |
7 | admin.initializeApp({
8 | credential: admin.credential.cert(serviceAccount),
9 | databaseURL: "https://ghbot-762ee.firebaseio.com/"
10 | });
11 |
12 | const projectId = 'ghbot-762ee'; //https://dialogflow.com/docs/agents#settings
13 | const sessionId = 'my-session-id';
14 | const languageCode = 'en-US';
15 |
16 | const dialogflow = require('dialogflow');
17 | const sessionClient = new dialogflow.SessionsClient();
18 |
19 | const sessionPath = sessionClient.sessionPath(projectId, sessionId);
20 |
21 | app.post('/process', (req, res) => {
22 | const query = req.body.query;
23 |
24 | if(!query){
25 | res.json({flag: 0});
26 | return;
27 | }
28 |
29 | // The text query request.
30 | const textReq = {
31 | session: sessionPath,
32 | queryInput: {
33 | text: {
34 | text: query,
35 | languageCode: languageCode,
36 | },
37 | },
38 | };
39 |
40 |
41 | // Send request and log result
42 | sessionClient
43 | .detectIntent(textReq)
44 | .then(responses => {
45 | console.log('Detected intent');
46 | const result = responses[0].queryResult;
47 | console.log(` Query: ${result.queryText}`);
48 | console.log(` Response: ${result.fulfillmentText}`);
49 | if (result.intent) {
50 | console.log(` Intent: ${result.intent.displayName}`);
51 | const intent_name = result.intent.displayName;
52 |
53 | if(intent_name=='near_location'){
54 | const location = result.parameters.fields.location.structValue.fields["street-address"].stringValue;
55 | getGeocode(location).then((data) => {
56 | const jsonObj = JSON.parse(data);
57 |
58 | res.json({flag: 1, type: 0, data: jsonObj.results[0].geometry.location});
59 | }).catch((err) =>{
60 | console.error(err);
61 | res.json({flag: 0});
62 | });
63 | } else if(intent_name=='find_location'){
64 | const ghname = result.parameters.fields.gh_name.stringValue;
65 | findGhInfo(ghname).then((data) => {
66 |
67 | res.json({flag: 1, type: 1, data: data})
68 | }).catch((err) =>{
69 | console.error(err);
70 | res.json({flag: 0});
71 | });
72 | }
73 |
74 | } else {
75 | console.log(` No intent matched.`);
76 | res.json({flag: 0});
77 | }
78 | })
79 | .catch(err => {
80 | console.error('error:', err);
81 | res.json({flag: 0});
82 | });
83 |
84 | });
85 |
86 |
87 | function getGeocode(addr){
88 | return new Promise((resolve, reject) => {
89 | const address = encodeURI(addr);
90 |
91 | const api_key = '[맵 API 키]';
92 | const api_url = `https://maps.googleapis.com/maps/api/geocode/json?address=${address}&key=${api_key}`;
93 |
94 | request.get({url: api_url}, function (error, response, body) {
95 | if (!error && response.statusCode == 200) {
96 | resolve(body);
97 | } else {
98 | reject(error);
99 | }
100 | });
101 | });
102 | }
103 |
104 |
105 | function findGhInfo(ghname){
106 | return new Promise((resolve, reject) => {
107 | admin.database().ref('/guesthouses')
108 | .once('value', function(snapshot) {
109 | snapshot.forEach(function(childSnapshot) {
110 | var childKey = childSnapshot.key;
111 | var info = childSnapshot.val();
112 |
113 | if(info.enname == ghname){
114 | resolve(info);
115 | return;
116 | }
117 | });
118 |
119 | reject("no guesthouse");
120 | });
121 | });
122 | }
123 |
124 |
125 | }
--------------------------------------------------------------------------------
/[9]coin-project/clova.js:
--------------------------------------------------------------------------------
1 | module.exports = (app) => {
2 |
3 | class CEKRequest {
4 | constructor (req, res) {
5 | this.request = req.body.request;
6 | this.context = req.body.context;
7 | this.session = req.body.session;
8 | this.response = res;
9 | console.log(`CEK Request: ${JSON.stringify(this.context)}, ${JSON.stringify(this.session)}`)
10 | }
11 |
12 | do(response) {
13 | switch (this.request.type) {
14 | case 'LaunchRequest':
15 | return this.launchRequest(response);
16 | case 'IntentRequest':
17 | return this.intentRequest(response);
18 | case 'SessionEndedRequest':
19 | return this.sessionEndedRequest(response);
20 | }
21 | }
22 |
23 | launchRequest(response) {
24 | console.log('launchRequest');
25 | response.setSimpleSpeechText('코인 프리미엄 정보를 알려드립니다.');
26 | response.setMultiturn({
27 | intent: 'CoinCheckIntent',
28 | });
29 | }
30 |
31 | intentRequest(response) {
32 | console.log('intentRequest');
33 | console.dir(this.request);
34 | const intent = this.request.intent.name;
35 | const slots = this.request.intent.slots;
36 |
37 | switch (intent) {
38 | case 'CoinCheckIntent':
39 | default:
40 |
41 | if(slots.premium){
42 |
43 | app.getPremium().then((data) => {
44 | response.appendSpeechText(`김프 시세 차이는 ${data.premium_price}원, ${data.premium_percent}% 입니다.`);
45 | return this.response.send(response);
46 | });
47 | } else {
48 |
49 | if(slots.currency){
50 | const currency = slots.currency.value;
51 | if(currency=='비트코인' || currency=='비코'){
52 | app.getPrice('btc').then((data) => {
53 | response.appendSpeechText(`비트코인 가격은 ${data.value}원 입니다.`);
54 | return this.response.send(response);
55 | });
56 |
57 | } else if(currency=='이더리움' || currency=='이더'){
58 | app.getPrice('eth').then((data) => {
59 | response.appendSpeechText(`이더리움 가격은 ${data.value}원 입니다.`);
60 | return this.response.send(response);
61 | });
62 | } else if(currency=='리플'){
63 | app.getPrice('xrp').then((data) => {
64 | response.appendSpeechText(`리플 가격은 ${data.value}원 입니다.`);
65 | return this.response.send(response);
66 | });
67 | }
68 | }
69 | }
70 |
71 | break;
72 | }
73 |
74 | }
75 |
76 | sessionEndedRequest(response) {
77 | console.log('sessionEndedRequest');
78 | response.setSimpleSpeechText('코인 정보 봇을 종료합니다.');
79 | response.clearMultiturn();
80 | }
81 | }
82 |
83 | class CEKResponse {
84 | constructor () {
85 | console.log('CEKResponse constructor')
86 | this.response = {
87 | directives: [],
88 | shouldEndSession: true,
89 | outputSpeech: {},
90 | card: {},
91 | };
92 | this.version = '0.1.0';
93 | this.sessionAttributes = {};
94 | }
95 |
96 | setMultiturn(sessionAttributes) {
97 | this.response.shouldEndSession = false;
98 | this.sessionAttributes = Object.assign(this.sessionAttributes, sessionAttributes);
99 | }
100 |
101 | clearMultiturn() {
102 | this.response.shouldEndSession = true;
103 | this.sessionAttributes = {};
104 | }
105 |
106 | setSimpleSpeechText(outputText) {
107 | this.response.outputSpeech = {
108 | type: 'SimpleSpeech',
109 | values: {
110 | type: 'PlainText',
111 | lang: 'ko',
112 | value: outputText,
113 | },
114 | };
115 | }
116 |
117 | appendSpeechText(outputText) {
118 | const outputSpeech = this.response.outputSpeech;
119 | if (outputSpeech.type != 'SpeechList') {
120 | outputSpeech.type = 'SpeechList';
121 | outputSpeech.values = [];
122 | }
123 | if (typeof(outputText) == 'string') {
124 | outputSpeech.values.push({
125 | type: 'PlainText',
126 | lang: 'ko',
127 | value: outputText,
128 | });
129 | } else {
130 | outputSpeech.values.push(outputText);
131 | }
132 | }
133 | }
134 |
135 | app.post('/clova', (req, res, next) => {
136 | const cekResponse = new CEKResponse();
137 | const cekRequest = new CEKRequest(req, res);
138 | cekRequest.do(cekResponse);
139 | });
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/[2]pwa-youtube/src/pwa-youtube-app/list-page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
66 |
67 |
72 |
73 |
74 |
75 |
80 |
81 |
82 |
83 |
88 |
89 | 로딩중입니다...
90 |
91 |
92 |
145 |
--------------------------------------------------------------------------------
/[8]music-project/client/src/client-app/client-app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
21 |
22 |
26 |
27 |
35 |
36 |
37 |
153 |
154 |
--------------------------------------------------------------------------------
/[5]chat-project/src/chat-project-app/view-room.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
43 |
44 |
49 |
50 |
51 |
58 |
59 |
60 |
61 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
Send
82 |
83 |
87 |
88 |
89 |
90 |
91 |
204 |
--------------------------------------------------------------------------------