티스토리 뷰


package.json은 다음과 같다. 특별히 필요한 모듈이 없어서 설명할 것도 없을것 같다.



{

  "name": "LunaStratos",

  "engines": {

    "node": ">=4.3.2"

  },

  "description": "final russian roulette",

  "main":  "index.js",

  "devDependencies": {

    "@google-cloud/storage": "^1.4.0",

    "actions-on-google": "^1.5.1",

    "package": "^1.0.1",

    "package.json": "^2.0.1"

  },

  "scripts": {

    "deploy": "gcloud app deploy",

    "start": "node index.js",

    "lint": "samples lint",

    "pretest": "npm run lint",

    "system-test": "samples test app",

    "test": "npm run system-test",

    "e2e-test": "samples test deploy"

  },

  "private": "true",

  "license": "ISC",

  "dependencies": {

    "@google-cloud/storage": "^1.4.0",

    "actions-on-google": "^1.5.1",

    "package": "^1.0.1",

    "package.json": "^2.0.1"

  }

}






switch (request.method) {

        case 'GET': // policy를 위한 페이지임

            response.writeHead(200, {

                "Content-Type": "text/html; charset=utf-8"

            });


이 부분은 policy 페이지이다.

구글 어시스턴트 앱은 policy를 안쓰면 아마 reject되는 것으로 안다. (본인도 그랬다 ㅜㅜ)

물론 구글 문서로 만들고 모든사람이 보기로 만들면 되지만 그냥 하나로 합치는게 좋을거 같아서 GET으로 접속한 경우 하게 했다. 


const ApiAiAction = require('actions-on-google').ApiAiAssistant; // apiai

.

.

.

     

  default: // post


            const app = new ApiAiAction({

                request,

                response

            });


POST인 경우는 ApiAiAction이 request와 response를 받아줘서 app으로 사용을 한다. 



   let actionMap = new Map(); // intent map save list


            actionMap.set('input.welcome', welcome_func); // first : welcome intent

            actionMap.set('DefaultWelcomeIntent.DefaultWelcomeIntent-yes', startGame); // 게임시작

            actionMap.set('intent.gamestart', startGame); // 게임시작


            actionMap.set('DefaultWelcomeIntent.DefaultWelcomeIntent-no', welcome_func_no); // 게임종료


            actionMap.set('intent.end.gameflow', endGame); // 게임종료 (게임중)

            actionMap.set('intent.end', endGame); // 게임종료 (게임중이 아닐때)

            actionMap.set('intent.end.gameflow.end', endGame); // 게임종료 (게임중이 아닐때)


            // 러시안룰렛 게임중, 7이상의 숫자 처리

            actionMap.set('intent.number', russianRoulette);


            actionMap.set('intent.retry', retryGame); // 다시 시작

            actionMap.set('intent.retry.gameflow', retryGame); // // 게임중 다시시작


            actionMap.set('intentendgameflowend.intentendgameflowend-fallback', notGame); // 게임중인 아닐때

            actionMap.set('intentnumber.intentnumber-fallback', unknown_say); // 게임중 숫자 아닌걸 말할때

            actionMap.set('intent.end.gameflow.end.fallback', unknown_say); // 게임중

          

 app.handleRequest(actionMap); //   intent search


이 부분은 app의 intent를 맵핑하는 부분이다. 그리고 intent가 동작시 action의 이름을 받아서 각 맵에 찾는 부분이다.

const로 action의 이름을 만들어서 쓰는 방법도 있다. 



 // welcome function

            function welcome_func(app) {


                let welcomeText = '<speak><par>' +


                    '<media><break time="2s"/><speak>러시안 룰렛에 온걸 환영합니다. 게임에 대한 메뉴얼은 "메뉴얼"을 말하면 됩니다. 게임을 시작하겠습니까? 시작하려면 "게임시작", 종료하려면 "끝내기" 를 말해주세요</speak></media>' +

                    '<media>' +

                    '<audio src="https://storage.googleapis.com/finalrussianroulette.appspot.com/bgm/faces.ogg"/></media>' +

                    '</par></speak>';


                let welcomeTextDisplay = "러시안 룰렛에 온걸 환영합니다. 게임에 대한 설명은 '메뉴얼'을 말하면 됩니다. 게임을 시작하겠습니까? 시작하려면 '게임시작', 종료하려면 '끝내기' 를 말해주세요.";


                app.ask(app.buildRichResponse()

                    .addSimpleResponse({

                        speech: welcomeText,

                        displayText: welcomeTextDisplay

                    })

                );

            }


파이널 러시안룰렛에 연결하기 를 말하면 처음 동작하는 부분이다. 

이 부분은 ssml을 사용했는데 ssml에 대한 방법은 구글 링크를 참조하면 된다. 

참고로 speech와 displayText는 텍스트 내용이 일치해야 한다. 


app.ask부분에서 응답에 대한 텍스트와 음성을 답하는 부분이 된다.

ask로 물으면 앱이 종료되지 않고 이어진다. 


            // 게임 시작안하고 종료할때

            function welcome_func_no(app) {

                let noText = "잔넨, 게임을 하지 않고 끝내시다니. 다음에는 꼭! 이용해주세요!";

                app.tell(app.buildRichResponse()

                    .addSimpleResponse({

                        speech: noText,

                        displayText: noText

                    })

                );

            }


app.tell로 끝내면 앱은 종료된다. 주로 종료할때 쓰는 메소드이다. 


function startGame(app) {

                // 게임시작때 수를 생성함. 이후 그 수를 사용


                let starttext = '<speak> 그럼 게임을 시작합니다.<audio src="https://actions.google.com/sounds/v1/weapons/gun_reload.ogg" clipEnd ="2s"/> 지금 리볼버에는 총알이 한알 장전 되어 있습니다. ' +

                    '1부터 6까지의 숫자 중 하나를 말해주세요.</speak>';

                let starttextDidplay = '그럼 게임을 시작합니다. (찰칵) 지금 리볼버에는 총알이 한알 장전 돼어 있습니다. ' +

                    '1부터 6까지의 숫자 중 하나를 말해주세요.';



                let randomValue = Math.floor(Math.random() * 6) + 1;


                // make context

                let parameters = {};

                parameters['randomGun'] = randomValue;

                parameters['userValues'] = 0;

                app.setContext("random", 20, parameters);


                values = 0;

                let parameters2 = {};

                parameters2['numbers'] = 999;

                app.setContext("gameflow", 10, parameters2);


                app.ask(app.buildRichResponse()

                    .addSimpleResponse({

                        speech: starttext,

                        displayText: starttextDidplay

                    })

                    .addSuggestions(['1', '2', '3', '4', '5', '6'])

                );


            }


이 부분에서 봐야 할 점은 Context의 생성이다. 맞다. 코드로도 컨텍스트를 생성할 수있다. 

app.setContext를 이용하면 컨텍스트를 생성할 수 있다. 안에 값도 집어넣을 수 있다. 



.addSuggestions(['1', '2', '3', '4', '5', '6'])는 버튼형이다. 이미지에 있는 숫자 버튼을 생성하는 것이다. 



 // 게임 부분,

            function russianRoulette(app) {


                let number = app.getArgument('number'); // 파라메터의 숫자를 받는다.

                let randomGun = app.getContextArgument('random', 'randomGun').value; // 랜던숫자를 받는다 

                let contextValue = app.getContextArgument('gameflow', 'numbers').value; // 게임에서 불렀던 숫자를 받는다. 

       



app.getArgument를 쓰면 파라메터의 숫자를 받을 수 있다. 파라메터란 이전 intent에서 불렀던 말중 엔티티가 지정된 것을 의미한다.

파라메터의 이름은 dialogflow의 파라메터 이름을 쓰면 된다.

app.getContextArgument('random', 'randomGun').value;는 random이라는 Context이름에 있는 randomGun이라는 파라메터를 받겠다는 뜻이다.

이것은 object{value: 값 }형태 이기 때문에 value라는 이름을 뒤에 써줘야 한다. 


나머지 코드는 보면 이해가 될 것이다. 




















공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함