STT
This commit is contained in:
		| @ -5,18 +5,22 @@ import android.support.v7.app.AppCompatActivity | ||||
| import android.support.v7.app.AppCompatDelegate | ||||
| import android.view.View | ||||
| import android.arch.lifecycle.ViewModelProviders | ||||
| import android.content.ActivityNotFoundException | ||||
| import android.content.Intent | ||||
| import android.speech.RecognizerIntent | ||||
| import android.speech.tts.TextToSpeech | ||||
| import android.support.design.widget.Snackbar | ||||
| import android.text.method.LinkMovementMethod | ||||
| import android.view.Menu | ||||
| import android.view.MenuItem | ||||
| import android.widget.* | ||||
|  | ||||
| const val REQ_CODE_SPEECH_INPUT = 1 | ||||
| import java.util.* | ||||
| import java.util.regex.Pattern | ||||
|  | ||||
|  | ||||
| class MatchActivity : AppCompatActivity() { | ||||
|     val REQ_CODE_SPEECH_INPUT = 1 | ||||
|  | ||||
|     var matchModel: MatchModel? = null | ||||
|     var textScore: android.widget.TextView? = null | ||||
|     var textService: android.widget.TextView? = null | ||||
| @ -63,15 +67,16 @@ class MatchActivity : AppCompatActivity() { | ||||
|                         getBooleanExtra("enableSTT", false) | ||||
|                     ) | ||||
|                 } | ||||
|                 if (it.ttsEnabled) { | ||||
|                     tts = TextToSpeech(this, TextToSpeech.OnInitListener { fun onInit(status: Int) {} }) | ||||
|                 } | ||||
|                 Snackbar.make( | ||||
|                     findViewById(R.id.coordinatorLayout), | ||||
|                     R.string.button_hint, | ||||
|                     Snackbar.LENGTH_SHORT | ||||
|                 ).show() | ||||
|             } | ||||
|             if (it.ttsEnabled) { | ||||
|                 tts = TextToSpeech(this, TextToSpeech.OnInitListener { fun onInit(status: Int) {} }) | ||||
|                 if (it.sttEnabled) tts?.setOnUtteranceProgressListener(WaitForTTS(::launchStt)) | ||||
|             } | ||||
|         } | ||||
|         updateUI() | ||||
|     } | ||||
| @ -100,19 +105,19 @@ class MatchActivity : AppCompatActivity() { | ||||
|     } | ||||
|  | ||||
|     fun updateUI() { | ||||
|         matchModel?.let { | ||||
|         matchModel?.apply { | ||||
|             textScore?.text = getString( | ||||
|                 R.string.score, | ||||
|                 it.players[it.serviceSide].score, | ||||
|                 it.players[it.relaunchSide].score | ||||
|                 players[serviceSide].score, | ||||
|                 players[relaunchSide].score | ||||
|             ) | ||||
|             textService?.text = getString(R.string.service, it.players[it.serviceSide].name) | ||||
|             textService?.text = getString(R.string.service, players[serviceSide].name) | ||||
|  | ||||
|             for ((button, player) in buttons.zip(it.players)) { | ||||
|             for ((button, player) in buttons.zip(players)) { | ||||
|                 button.text = fromHtml(getString(R.string.button_text, player.name, player.score)) | ||||
|             } | ||||
|  | ||||
|             when (it.serviceSide) { | ||||
|             when (serviceSide) { | ||||
|                 0 -> { | ||||
|                     imageViews[0]?.setImageResource(R.drawable.ic_service_0) | ||||
|                     imageViews[1]?.setImageResource(0) | ||||
| @ -123,50 +128,107 @@ class MatchActivity : AppCompatActivity() { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             undo?.isVisible = when (it.playId) { | ||||
|             undo?.isVisible = when (playId) { | ||||
|                 0 -> false | ||||
|                 else -> true | ||||
|             } | ||||
|             redo?.isVisible = when (it.playId) { | ||||
|                 it.history.size - 1 -> false | ||||
|             redo?.isVisible = when (playId) { | ||||
|                 history.size - 1 -> false | ||||
|                 else -> true | ||||
|             } | ||||
|  | ||||
|             if (it.ttsEnabled) { | ||||
|                 if (it.matchFinished()) { | ||||
|                     val (loser, winner) = it.players.sortedBy { player -> player.score } | ||||
|             if (ttsEnabled) ttsSpeak() | ||||
|  | ||||
|             if (matchFinished()) endMatch() | ||||
|             else if (sttEnabled and !ttsEnabled) launchStt() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun ttsSpeak() { | ||||
|         matchModel?.apply { | ||||
|             if (matchFinished()) { | ||||
|                 val (loser, winner) = players.sortedBy { it.score } | ||||
|                 tts?.speak( | ||||
|                     getString( | ||||
|                         R.string.victory_speech, | ||||
|                         winner.name, | ||||
|                         winner.score, | ||||
|                         loser.score | ||||
|                     ), | ||||
|                     TextToSpeech.QUEUE_FLUSH, | ||||
|                     hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "Victory") | ||||
|                 ) | ||||
|             } else { | ||||
|                 tts?.speak( | ||||
|                     getString( | ||||
|                         R.string.update_score_speech, | ||||
|                         players[serviceSide].score, | ||||
|                         players[relaunchSide].score, | ||||
|                         players[serviceSide].name | ||||
|                     ), | ||||
|                     TextToSpeech.QUEUE_FLUSH, | ||||
|                     hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "MessageId") | ||||
|                 ) | ||||
|                 if (matchPoint()) { | ||||
|                     tts?.speak( | ||||
|                         getString( | ||||
|                             R.string.victory_speech, | ||||
|                             winner.name, | ||||
|                             winner.score, | ||||
|                             loser.score | ||||
|                         ), | ||||
|                         TextToSpeech.QUEUE_FLUSH, | ||||
|                         hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "Victory") | ||||
|                     ) | ||||
|                 } else { | ||||
|                     tts?.speak( | ||||
|                         getString( | ||||
|                             R.string.update_score_speech, | ||||
|                             it.players[it.serviceSide].score, | ||||
|                             it.players[it.relaunchSide].score, | ||||
|                             it.players[it.serviceSide].name | ||||
|                         ), | ||||
|                         TextToSpeech.QUEUE_FLUSH, | ||||
|                         getString(R.string.match_point), | ||||
|                         TextToSpeech.QUEUE_ADD, | ||||
|                         hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "MessageId") | ||||
|                     ) | ||||
|                     if (it.matchPoint()) { | ||||
|                         tts?.speak( | ||||
|                             getString(R.string.match_point), | ||||
|                             TextToSpeech.QUEUE_ADD, | ||||
|                             hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "MessageId") | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|             if (it.matchFinished()) endMatch() | ||||
|     fun launchStt() { | ||||
|         matchModel?.apply { | ||||
|             if (sttEnabled) { | ||||
|                 val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) | ||||
|                 intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) | ||||
|                 intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault().getDisplayLanguage()) | ||||
|                 intent.putExtra( | ||||
|                     RecognizerIntent.EXTRA_PROMPT, | ||||
|                     getString( | ||||
|                         R.string.STT_hint, | ||||
|                         players[0].name, | ||||
|                         players[1].name | ||||
|                     ) | ||||
|                 ) | ||||
|                 try { | ||||
|                     startActivityForResult(intent, REQ_CODE_SPEECH_INPUT); | ||||
|                 } catch (e: ActivityNotFoundException) { | ||||
|                     sttEnabled = false | ||||
|                     Snackbar.make( | ||||
|                         findViewById(R.id.coordinatorLayout), | ||||
|                         R.string.STT_unavailable, | ||||
|                         Snackbar.LENGTH_SHORT | ||||
|                     ).show() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | ||||
|         super.onActivityResult(requestCode, resultCode, data) | ||||
|         when (requestCode) { | ||||
|             REQ_CODE_SPEECH_INPUT -> { | ||||
|                 matchModel?.let { | ||||
|                     var understood: Boolean = false | ||||
|                     if (resultCode == RESULT_OK && data != null) { | ||||
|                         val result: String = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)[0] | ||||
|                         for (player in it.players) { | ||||
|                             if (Pattern.compile(getString(R.string.pattern, player.name)).matcher(result).find()) { | ||||
|                                 it.updateScore(player) | ||||
|                                 understood = true | ||||
|                                 break | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     if (!understood) launchStt() | ||||
|                 } | ||||
|             } | ||||
|             else -> { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -175,7 +237,7 @@ class MatchActivity : AppCompatActivity() { | ||||
|             if (!matchFinished()) { | ||||
|                 for (side in 0..1) { | ||||
|                     if (view == buttons[side]) { | ||||
|                         updateScore(side) | ||||
|                         updateScore(players[side]) | ||||
|                     } | ||||
|                 } | ||||
|                 updateUI() | ||||
| @ -189,8 +251,9 @@ class MatchActivity : AppCompatActivity() { | ||||
|                 Intent(this, VictoryActivity::class.java).apply { | ||||
|                     putExtra("winnerName", it.players.maxBy{ player -> player.score }?.name) | ||||
|                     putExtra("player1Name", it.players[0].name) | ||||
|                     putExtra("player1Score", it.players[0].score) | ||||
|                     putExtra("player2Name", it.players[1].name) | ||||
|                     putExtra("score", getString(R.string.score_only, it.players[0].score, it.players[1].score)) | ||||
|                     putExtra("player2Score", it.players[1].score) | ||||
|                 } | ||||
|             ) | ||||
|         } | ||||
|  | ||||
| @ -15,7 +15,7 @@ class MatchModel : ViewModel() { | ||||
|  | ||||
|     fun startMatch(player1Name: String, player2Name:String, starterId: Int, enableTTS: Boolean, enableSTT: Boolean) { | ||||
|         matchStarted = true | ||||
|         players = listOf(Player(player1Name), Player(player2Name)) | ||||
|         players = listOf(Player(player1Name, 0), Player(player2Name, 0)) | ||||
|         serviceSide = starterId | ||||
|         relaunchSide = when(serviceSide) { | ||||
|             0 -> 1 | ||||
| @ -26,9 +26,9 @@ class MatchModel : ViewModel() { | ||||
|         saveState() | ||||
|     } | ||||
|  | ||||
|     fun updateScore(scorerId: Int) { | ||||
|     fun updateScore(scorer: player) { | ||||
|         playId++ | ||||
|         players[scorerId].score++ | ||||
|         scorer.score++ | ||||
|         if ((players.sumBy { it.score } % 2 == 0) or (players.all { it.score >= 10 })) { | ||||
|             serviceSide = relaunchSide.also { relaunchSide = serviceSide } | ||||
|         } | ||||
|  | ||||
| @ -2,5 +2,5 @@ package adrienmalin.pingpoints | ||||
|  | ||||
| data class Player ( | ||||
|     var name: String, | ||||
|     var score: Int = 0 | ||||
|     var score: Int | ||||
| ) | ||||
| @ -14,16 +14,14 @@ import android.support.v4.app.ActivityCompat | ||||
| import android.support.v4.content.ContextCompat | ||||
| import android.support.v7.app.AlertDialog | ||||
| import android.support.v7.app.AppCompatActivity | ||||
| import android.text.method.LinkMovementMethod | ||||
| import android.view.View | ||||
| import android.widget.* | ||||
|  | ||||
|  | ||||
| const val CHECK_TTS = 1 | ||||
| const val ASK_PERMISSIONS_RECORD_AUDIO = 2 | ||||
|  | ||||
|  | ||||
| class StarterNameActivity : AppCompatActivity() { | ||||
|     val CHECK_TTS = 1 | ||||
|     val ASK_PERMISSIONS_RECORD_AUDIO = 2 | ||||
|  | ||||
|     var player1NameInput: AutoCompleteTextView? = null | ||||
|     var player2NameInput: AutoCompleteTextView? = null | ||||
|     var starterRadioGroup: RadioGroup? = null | ||||
|  | ||||
| @ -31,9 +31,16 @@ class VictoryActivity : AppCompatActivity() { | ||||
|             if (!it.matchFinished) { | ||||
|                 it.matchFinished = true | ||||
|                 it.winnerName = intent.getStringExtra("winnerName") | ||||
|                 it.player1Name = intent.getStringExtra("player1Name") | ||||
|                 it.player2Name = intent.getStringExtra("player2Name") | ||||
|                 it.score = intent.getStringExtra("score") | ||||
|                 it.players = listOf( | ||||
|                     Player( | ||||
|                         intent.getStringExtra("player1Name"), | ||||
|                         intent.getIntExtra("player1Score", 0) | ||||
|                     ), | ||||
|                     Player( | ||||
|                         intent.getStringExtra("player2Name"), | ||||
|                         intent.getIntExtra("player2Score", 0) | ||||
|                     ) | ||||
|                 ) | ||||
|  | ||||
|                 it.previousMatches = previousMatch.getString("previousMatches", "") | ||||
|                 previousMatch.edit().apply { | ||||
| @ -41,10 +48,11 @@ class VictoryActivity : AppCompatActivity() { | ||||
|                         "previousMatches", | ||||
|                         getString( | ||||
|                             R.string.result, | ||||
|                             it.player1Name, | ||||
|                             it.score, | ||||
|                             it.player2Name | ||||
|                         ) + '\n' + it.previousMatches | ||||
|                             it.players[0].name, | ||||
|                             it.players[0].score, | ||||
|                             it.players[1].score, | ||||
|                             it.players[1].name | ||||
|                         ) + it.previousMatches | ||||
|                     ) | ||||
|                     commit() | ||||
|                 } | ||||
| @ -54,12 +62,18 @@ class VictoryActivity : AppCompatActivity() { | ||||
|             findViewById<TextView>(R.id.congrats).text = getString(R.string.congrats, it.winnerName) | ||||
|             findViewById<GridView>(R.id.resultGrid).adapter = ArrayAdapter<String>( | ||||
|                 this, | ||||
|                 android.R.layout.simple_list_item_1, | ||||
|                 arrayOf(it.player1Name, it.score, it.player2Name) | ||||
|                 R.layout.grid_item, | ||||
|                 R.id.grid_item_text, | ||||
|                 arrayOf<String>( | ||||
|                     it.players[0].name, | ||||
|                     it.players[0].score.toString() + " - " + it.players[1].score.toString(), | ||||
|                     it.players[1].name | ||||
|                 ) | ||||
|             ) | ||||
|             findViewById<GridView>(R.id.previousMatchesGrid).adapter = ArrayAdapter<String>( | ||||
|                 this, | ||||
|                 android.R.layout.simple_list_item_1, | ||||
|                 R.layout.grid_item, | ||||
|                 R.id.grid_item_text, | ||||
|                 it.previousMatches.split("\t|\n".toRegex()) | ||||
|             ) | ||||
|         } | ||||
| @ -80,18 +94,19 @@ class VictoryActivity : AppCompatActivity() { | ||||
|                         Intent.EXTRA_SUBJECT, | ||||
|                         getString( | ||||
|                             R.string.share_subject, | ||||
|                             it.player1Name, | ||||
|                             it.player2Name | ||||
|                             it.players[0].name, | ||||
|                             it.players[1].name | ||||
|                         ) | ||||
|                     ) | ||||
|                     putExtra( | ||||
|                         Intent.EXTRA_TEXT, | ||||
|                         getString( | ||||
|                             R.string.share_message, | ||||
|                             it.player1Name, | ||||
|                             it.player2Name, | ||||
|                             it.players[0].name, | ||||
|                             it.players[1].name, | ||||
|                             it.winnerName, | ||||
|                             it.score | ||||
|                             it.players[0].score, | ||||
|                             it.players[1].score | ||||
|                         ) | ||||
|                     ) | ||||
|                     type = "text/plain" | ||||
|  | ||||
| @ -5,8 +5,6 @@ import android.arch.lifecycle.ViewModel | ||||
| class VictoryModel : ViewModel() { | ||||
|     var matchFinished: Boolean = false | ||||
|     var winnerName:String = "" | ||||
|     var player1Name = "" | ||||
|     var player2Name = "" | ||||
|     var score = "" | ||||
|     var players: List<Player> = emptyList() | ||||
|     var previousMatches: String = "" | ||||
| } | ||||
							
								
								
									
										11
									
								
								app/src/main/java/adrienmalin/pingpoints/WaitForTts.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/src/main/java/adrienmalin/pingpoints/WaitForTts.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| package adrienmalin.pingpoints | ||||
|  | ||||
| import android.speech.tts.UtteranceProgressListener | ||||
|  | ||||
| class WaitForTTS(val callback: () -> Unit) : UtteranceProgressListener() { | ||||
|     override fun onDone(id: String) { | ||||
|         callback() | ||||
|     } | ||||
|     override fun onStart(id: String) {} | ||||
|     override fun onError(id: String) {} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user