将阵列数据存储在卡中的简单示例 [英] Simple example to store array data in card

查看:70
本文介绍了将阵列数据存储在卡中的简单示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解如何使用Adaptive卡读取/写入数据.我可以从提交操作中读取数据,然后以文本形式答复,但不能确定输入数据在卡中的显示方式.首先,我想将ShootValue添加到一个可以在卡生命周期内进行传送的数组中.有人可以让我知道怎么做吗?

I would like to understand how to read/write data with Adaptive cards. I can read the data from a submit action, and reply as text, but not sure how present the input data in the card. First place, I would like to add the shootValue to an array that I can carry trough the lifecycle of the card. Can somebody please let me know how to do this?

该问题的目的是了解如何保留卡中的现有响应. 像在《战舰》中一样,我拍摄"A1",在输入框中键入内容,然后提交,我想在卡片中看到"A1".我添加"A2",提交,然后我想在发送给团队的卡片中看到"A1"和"A2".我知道我需要在每次射击时从头开始重建存储卡,这意味着我需要以某种方式进行每次射击.

The goal of this question is to understand how to keep existing responses from the card. Like in Battleship, I shoot "A1", type it in an input box, submit, I would like to see "A1" in the card. I add "A2", submit, then I would like to see "A1" and "A2" in the card that is sent to Teams. I understand that I need to rebuild the card from scratch at every shot, that means, I need to either carry on the shots somehow with each action.

数据卡:

{
  "type": "AdaptiveCard",
  "version": "1.0",
  "body": [
    {
      "type": "TextBlock",
      "text": "Hello {name}"
    },
    {
      "type": "ColumnSet",
      "columns": [
        {
          "type": "Column",
          "width": "stretch",
          "id": "",
          "items": [
            {
              "type": "Container",
              "items": [
                {
                  "type": "Input.Text",
                  "placeholder": "Voorbeeld: A1",
                  "id": "id_shoot",
                  "$data": "shoot"
                }
              ]
            }
          ]
        },
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "Container",
              "items": [
                {
                  "type": "TextBlock",
                  "text": " {shoot}",
                  "horizontalAlignment": "Right",
                  "id": ""
                }
              ],
              "$data": "{shoots}",
              "id": "shotcoords"
            }
          ],
          "$data": "{shots}"
        },
        {
          "type": "Column",
          "width": "stretch",
          "items": [
            {
              "type": "Container",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "{status}",
                  "id": ""
                }
              ],
              "$data": "{shoots}",
              "id": "shotstatuses"
            }
          ],
          "id": ""
        }
      ]
    },
    {
      "type": "ActionSet",
      "id": "",
      "actions": [
        {
          "type": "Action.Submit",
          "title": "Shoot",
          "id": "",
          "style": "positive",
          "data": {}
        }
      ]
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}

数据

{
  "name": "Test shot",
  "shoots": [
    {
      "shoot": "a1",
      "status": "hit"
    },
    {
      "shoot": "a2",
      "status": "hit"
    }
  ]
}

推荐答案

没有简单"的方法可以做到这一点,但是有一种方法.答案将类似于.

There is no "simple" way to do this, but there is a way. The answer will be similar to this one.

首先,您需要一种保存卡状态的方法,以便您可以更新卡的活动.在C#中,您可以像这样声明状态属性访问器:

First, you'll need a way of saving state for your card so you can update the card's activity. In C# you can declare a state property accessor like this:

public IStatePropertyAccessor<Dictionary<string, (string ActivityId, List<string> Shots)>> BattleshipStateAccessor { get; internal set; }

然后您可以像这样实例化

Then you can instantiate it like this

BattleshipStateAccessor = _conversationState.CreateProperty<Dictionary<string, (string, List<string>)>>("battleshipState");

您需要在此处做出一些决定.首先,我选择将state属性设置为字典,这样我就可以跟踪多张卡,并且仅更新所单击的特定卡.如果您不关心它,那么您就不需要字典,也不必担心卡号",但是至少需要保存一个活动ID,这样您才能更新卡.至于保存镜头",您可以在此处进行一些选择.您可以通过在每次拍摄时更新提交动作的数据来在客户端保存该状态,但是我想我也可以将拍摄的照片保存为bot状态,因为无论如何我已经需要将活动ID保存为bot状态.然后是一个问题,您应该保存有关每个镜头的哪些信息.在此示例中,我只保存用户输入的镜头位置,而不是镜头状态,因为我认为随时可以随时重新计算状态.

You have a few decisions to make here. First, I'm choosing to make the state property a dictionary so I can keep track of multiple cards and only update the specific card that was clicked. If you don't care about that then you don't need a dictionary and you don't need to worry about "card ID's," but saving at least one activity ID is necessary so that you'll be able to update the card. As for saving the "shots," you have a few choices here. You could save that state on the client side by updating the submit action's data with each shot that's been made, but I figure I might as well save the shots in bot state because I already need to save the activity ID in bot state anyway. Then there's the question of what information about each shot you should save. In this example I'm only saving the location of the shot that the user entered and not the status of the shot, since I figure I can always recalculate the status whenever I need to.

我已经修改了您的提交动作,如下所示:

I've modified your submit action to look like this:

{
  "type": "Action.Submit",
  "title": "Shoot",
  "style": "positive",
  "data": {
    "behavior": "Shoot",
    "cardId": ""
  }
}

我在这里所做的事情是为您的数据对象添加了两个属性,该数据将与文本输入的值一起发送到您的机器人.万一您的漫游器使用可以通过不同方式处理的多种类型的动作,行为"属性将帮助您的漫游器路由至正确的功能. "cardId"属性只是占位符,您的机器人代码将在创建卡片时填写.我已将这些属性的名称存储在常量KEYBEHAVIORKEYCARDID中.

What I've done here is added two properties to your data object, and this data will be sent to your bot along with the text input's value. The "behavior" property will help your bot route to the correct function in case your bot uses multiple types of actions that can be handled different ways. The "cardId" property is just a placeholder that your bot code will fill in when creating the card. I've stored the names of these properties in the constants KEYBEHAVIOR and KEYCARDID.

您需要一种一致的方式来生成您的卡,该方法可在您初次发送卡和更新卡时使用.

You'll want a consistent way to generate your card that you can use when you send the card initially and when you update the card.

internal static IMessageActivity CreateBattleshipCardActivity(
    string cardId,
    object data = null)
{
    data = data ?? new
    {
        name = "Test shot",
        shoots = new string[0],
    };

    JObject card = CreateAdaptiveCard("battleship", data);

    foreach (var token in card.Descendants()
        .Select(token => token as JProperty)
        .Where(token => token?.Name == KEYCARDID))
    {
        token.Value = cardId;
    }

    return MessageFactory.Attachment(new Attachment(
        AdaptiveCard.ContentType,
        content: card));
}

CreateAdaptiveCard函数从具有给定名称的文件中加载JSON模板,并使用给定的数据对其进行转换,然后将其反序列化为JObject.

The CreateAdaptiveCard function loads the JSON template from a file with the given name, transforms it with the given data, and deserializes it into a JObject.

使用此功能,您可以最初在C#中像这样发送卡:

Using this function, you can send the card initially like this in C#:

public async Task TestBattleshipAsync(
    ITurnContext turnContext,
    CancellationToken cancellationToken)
{
    var activity = turnContext.Activity;
    var cardId = Guid.NewGuid().ToString();
    var reply = CreateBattleshipCardActivity(cardId);
    var response = await turnContext.SendActivityAsync(reply, cancellationToken);
    var dict = await BattleshipStateAccessor.GetAsync(
        turnContext,
        () => new Dictionary<string, (string, List<string>)>(),
        cancellationToken);

    dict[cardId] = (response.Id, new List<string>());
}

您可以更新卡,以响应卡的拍摄"提交操作,如下所示:

And you can update the card in response to the card's "Shoot" submit action like this:

private async Task ShootAsync(
    ITurnContext turnContext,
    CancellationToken cancellationToken)
{
    var activity = turnContext.Activity;

    if (activity.ChannelId == Channels.Msteams)
    {
        var value = JObject.FromObject(activity.Value);
        var cardId = Convert.ToString(value[BotUtil.KEYCARDID]);
        var dict = await BattleshipStateAccessor.GetAsync(
            turnContext,
            () => new Dictionary<string, (string, List<string>)>(),
            cancellationToken);

        if (dict.TryGetValue(cardId, out var savedInfo))
        {
            savedInfo.Shots.Add(value["id_shoot"].ToString());

            var data = new
            {
                name = "Test shot",
                shoots = savedInfo.Shots.Select(shot => new
                {
                    shoot = shot,
                    status = DetermineHit(shot),
                }),
            };

            var update = CreateBattleshipCardActivity(cardId, data);

            update.Id = savedInfo.ActivityId;
            update.Conversation = activity.Conversation;

            await turnContext.UpdateActivityAsync(update, cancellationToken);
        }
    }
}

这篇关于将阵列数据存储在卡中的简单示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆