Ejemplo n.º 1
0
        public override async Task <SkillResponse> ProcessMessageAsync(SkillRequest skill, ILambdaContext context)
        {
            try {
                // load adventure from S3
                string source;
                try {
                    using (var s3Response = await _s3Client.GetObjectAsync(_adventureFileBucket, _adventureFileKey)) {
                        var memory = new MemoryStream();
                        await s3Response.ResponseStream.CopyToAsync(memory);

                        source = Encoding.UTF8.GetString(memory.ToArray());
                    }
                } catch (AmazonS3Exception e) when(e.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new Exception($"unable to load file from 's3://{_adventureFileBucket}/{_adventureFileKey}'");
                }

                // process adventure file
                var adventure = Adventure.Parse(source, Path.GetExtension(_adventureFileKey));

                // restore player object from session
                var state = await RestoreAdventureState(adventure, skill.Session);

                var engine = new AdventureEngine(adventure, state);
                LogInfo($"player status: {state.Status}");

                // decode skill request
                IOutputSpeech response = null;
                IOutputSpeech reprompt = null;
                switch (skill.Request)
                {
                // skill was activated without an intent
                case LaunchRequest launch:
                    LogInfo("launch");

                    // kick off the adventure!
                    if (state.Status == AdventureStatus.New)
                    {
                        state.Status = AdventureStatus.InProgress;
                        response     = Do(engine, AdventureCommandType.Restart, new XElement("speak", new XElement("p", new XText(PROMPT_WELCOME))));
                    }
                    else
                    {
                        response = Do(engine, AdventureCommandType.Describe, new XElement("speak", new XElement("p", new XText(PROMPT_WELCOME_BACK))));
                    }
                    reprompt = Do(engine, AdventureCommandType.Help);
                    break;

                // skill was activated with an intent
                case IntentRequest intent:
                    var isAdventureCommand = Enum.TryParse(intent.Intent.Name, true, out AdventureCommandType command);

                    // check if the intent is an adventure intent
                    if (isAdventureCommand)
                    {
                        LogInfo($"adventure intent ({intent.Intent.Name})");
                        response = Do(engine, command);
                        reprompt = Do(engine, AdventureCommandType.Help);
                    }
                    else
                    {
                        // built-in intents
                        switch (intent.Intent.Name)
                        {
                        case BuiltInIntent.Help:
                            LogInfo($"built-in help intent ({intent.Intent.Name})");
                            response = Do(engine, AdventureCommandType.Help);
                            reprompt = Do(engine, AdventureCommandType.Help);
                            break;

                        case BuiltInIntent.Stop:
                        case BuiltInIntent.Cancel:
                            LogInfo($"built-in stop/cancel intent ({intent.Intent.Name})");
                            response = Do(engine, AdventureCommandType.Quit);
                            break;

                        default:

                            // unknown & unsupported intents
                            LogWarn("intent not recognized");
                            response = new PlainTextOutputSpeech {
                                Text = PROMPT_MISUNDERSTOOD
                            };
                            reprompt = Do(engine, AdventureCommandType.Help);
                            break;
                        }
                    }
                    break;

                // skill session ended (no response expected)
                case SessionEndedRequest ended:
                    LogInfo("session ended");
                    return(ResponseBuilder.Empty());

                // exception reported on previous response (no response expected)
                case SystemExceptionRequest error:
                    LogWarn($"skill request exception: {JsonConvert.SerializeObject(skill)}");
                    return(ResponseBuilder.Empty());

                // unknown skill received (no response expected)
                default:
                    LogWarn($"unrecognized skill request: {JsonConvert.SerializeObject(skill)}");
                    return(ResponseBuilder.Empty());
                }

                // check if the player reached the end
                var roomCompleteCounter            = 0;
                Dictionary <string, string> result = new Dictionary <string, string>();
                if (adventure.Places[state.CurrentPlaceId].Finished)
                {
                    // TODO: send completion notification with player statistics
                    state.RoomCount++;
                    LogInfo("Current place at room end: " + state.CurrentPlaceId);
                    LogInfo("STATUS at room end: " + state.Status);
                    LogInfo("TIME at room complete: " + state.StartTime);
                    LogInfo("ROOM COUNT at end: " + state.RoomCount);

                    //if(state.CurrentPlaceId == "end-room-good"){
                    result.Add("rooms", roomCompleteCounter.ToString());
                    await _SNSClient.PublishAsync(_adventurePlayerFinishedTopic, "Rooms completed: " + result["rooms"]);

                    //}
                }

                // create/update player record so we can continue in a future session
                await StoreAdventureState(state);

                // respond with serialized player state
                if (reprompt != null)
                {
                    return(ResponseBuilder.Ask(
                               response,
                               new Reprompt {
                        OutputSpeech = reprompt
                    },
                               new Session {
                        Attributes = new Dictionary <string, object> {
                            [SESSION_STATE_KEY] = state
                        }
                    }
                               ));
                }
                return(ResponseBuilder.Tell(response));
            } catch (Exception e) {
                LogError(e, "exception during skill processing");
                return(ResponseBuilder.Tell(new PlainTextOutputSpeech {
                    Text = PROMPT_OOPS
                }));
            }
        }