Simple Questions
Now it’s time to plug in dialogue.
Robotify the application (File > New > Robot Application...), register and unregister the application; also, remove the loading of monster data (we’ll put it back later)
class MainActivity : RobotActivity(), RobotLifecycleCallbacks {
val TAG = "MainActivity"
private lateinit var imageHolder : LinearLayout
private val imageLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT, 1.0f)
private var chatFuture: Future<Void>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
imageHolder = findViewById(R.id.imageHolder)
QiSDK.register(this, this)
}
override fun onDestroy() {
chatFuture?.cancel(true)
QiSDK.unregister(this)
super.onDestroy()
}
override fun onRobotFocusGained(qiContext: QiContext?) {
Log.w(TAG, "Robot Focus Gained!")
// TODO: fill in qichat
}
override fun onRobotFocusLost() {
Log.w(TAG, "Robot Focus Lost")
}
override fun onRobotFocusRefused(reason: String?) {
Log.w(TAG, "Robot Focus Refused because $reason")
}
fun showMonsters(monstersToShow: List<Monster>) {
runOnUiThread {
Log.i(TAG, "Showing ${monstersToShow.size} monsters")
imageHolder.removeAllViews()
monstersToShow.forEach { monster ->
val imageView = ImageView(applicationContext).apply {
id = View.generateViewId()
layoutParams = imageLayoutParams
setImageResource(monster.resourceId)
}
imageHolder.addView(imageView)
}
}
}
}
Create a topic (File > New > Chat Topic) called “monsters” with a simple query; we’ll make a more complex one later:
topic: ~monsters()
concept:(color) [red blue yellow green orange purple pink brown black grey white]
u:(Show me _~color monsters)
$color=$1
^execute(clearScreen)
Let me see.
^execute(showMonsters, $color)
Here they are!
To handle this topic, we will create a dedicated class, MonsterDialogue; it will contain: * The code to load the dialogue topic * The executors
Its only interaction with mainActivity will be through a showMonsterList callback, passed at construction.
Create the MonsterDialogue.kt file and add this:
class MonsterDialogue(qiContext: QiContext,
val allMonsters: List<Monster>,
val showMonsterList: (List<Monster>) -> Unit) {
val TAG = "MonsterDialogue"
private val topic = TopicBuilder.with(qiContext).withResource(R.raw.monsters).build()
private val qiChatbot = QiChatbotBuilder.with(qiContext).withTopic(topic).build().apply {
executors = hashMapOf<String, QiChatExecutor>(
"showMonsters" to ShowMonstersExecutor(qiContext),
"clearScreen" to ClearScreenExecutor(qiContext),
)
}
private val chat = ChatBuilder.with(qiContext).withChatbot(qiChatbot).build()
fun run(): Future<Void> {
return chat.async().run()
}
// Executors
inner class ClearScreenExecutor(context: QiContext?) : BaseQiChatExecutor(context) {
override fun runWith(params: MutableList<String>) {
showMonsterList(listOf())
}
override fun stop() {}
}
inner class ShowMonstersExecutor(context: QiContext?) : BaseQiChatExecutor(context) {
override fun runWith(params: MutableList<String>) {
Log.i(TAG, "Showing by color; $params")
val color = params[0]
showMonsterList(allMonsters.filter { it.color == color })
}
override fun stop() {}
}
}
… and then update mainActivity so that: * This class is instantiated on onRobotFocusGained * The list of monster data is created in onRobotFocusGained
override fun onRobotFocusGained(qiContext: QiContext) {
Log.w(TAG, "Robot Focus Gained!")
val monsterData = resources.openRawResource(R.raw.monsters_data)
val allMonsters = readMonstersJSON(monsterData)
allMonsters.forEach {
it.resourceId = resources.getIdentifier(it.filename, "drawable", packageName)
}
val monsterDialogue = MonsterDialogue(qiContext, allMonsters, ::showMonsters)
monsterDialogue.run()
}
Now is a good time to test this integration on Pepper, and check that Pepper can show monsters of the color you asked him.