diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 773d062..5258d9f 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -16,11 +16,66 @@ + + + + + + + + + @@ -41,11 +96,6 @@ - @@ -56,7 +106,42 @@ - + + + diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index accb349..3d7a5a2 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5f144a9..930fc9c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,15 +9,19 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/PingPoints"> - - - + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png index de50cc6..638e0d3 100644 Binary files a/app/src/main/ic_launcher-web.png and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/adrienmalin/pingpoints/CreditsActivity.kt b/app/src/main/java/adrienmalin/pingpoints/CreditsActivity.kt new file mode 100644 index 0000000..970186d --- /dev/null +++ b/app/src/main/java/adrienmalin/pingpoints/CreditsActivity.kt @@ -0,0 +1,12 @@ +package adrienmalin.pingpoints + +import android.support.v7.app.AppCompatActivity +import android.os.Bundle + +class CreditsActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_credits) + } +} diff --git a/app/src/main/java/adrienmalin/pingpoints/EndOfMatchDialog.kt b/app/src/main/java/adrienmalin/pingpoints/EndOfMatchDialog.kt index 387ae91..96b2261 100644 --- a/app/src/main/java/adrienmalin/pingpoints/EndOfMatchDialog.kt +++ b/app/src/main/java/adrienmalin/pingpoints/EndOfMatchDialog.kt @@ -10,58 +10,64 @@ import android.support.v4.app.DialogFragment class EndOfMatchDialog: DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val builder = AlertDialog.Builder(activity) - val player1Name = arguments?.getString("PLAYER_1_NAME") - val player2Name = arguments?.getString("PLAYER_2_NAME") - val winnerName = arguments?.getString("WINNER_NAME") - val winnerScore = arguments?.getInt("WINNER_SCORE") - val loserScore = arguments?.getInt("LOSER_SCORE") + var names: Array = arrayOf("", "") + var winnerName = "" + var score = IntArray(2) - builder.setTitle(getString(R.string.end_match_dialog_title, winnerName)) - .setMessage(getString(R.string.score, winnerScore, loserScore)) - .setPositiveButton( - R.string.new_match, - DialogInterface.OnClickListener {dialog, id -> - startActivity(Intent(context, MainActivity::class.java)) - activity?.finish() - } - ) - .setNeutralButton( - R.string.share_button, - DialogInterface.OnClickListener { dialog, id -> - val sendIntent: Intent = Intent().apply { - action = Intent.ACTION_SEND - putExtra( - Intent.EXTRA_SUBJECT, - getString( - R.string.share_subject, - player1Name, - player2Name - ) - ) - putExtra( - Intent.EXTRA_TEXT, - getString( - R.string.share_message, - player1Name, - player2Name, - winnerName, - winnerScore, - loserScore - ) - ) - type = "text/plain" - } - startActivity(sendIntent) - } - ) - .setNegativeButton( - R.string.quit_button, - DialogInterface.OnClickListener { dialog, id -> - activity?.finish() - } - ) + arguments?.apply { + names = getStringArray("names") + winnerName = getString("winnerName") + score = getIntArray("score") + } - return builder.create() + return AlertDialog.Builder(activity).apply{ + setTitle(getString(R.string.end_match_dialog_title, winnerName)) + setMessage(getString(R.string.score, score[0], score[1])) + setPositiveButton( + R.string.new_match, + DialogInterface.OnClickListener { dialog, id -> + startActivity( + Intent(context, MainActivity::class.java).apply { + putExtra("names", names) + } + ) + activity?.finish() + } + ) + setNeutralButton( + R.string.share_button, + DialogInterface.OnClickListener { dialog, id -> + val sendIntent: Intent = Intent().apply { + action = Intent.ACTION_SEND + putExtra( + Intent.EXTRA_SUBJECT, + getString( + R.string.share_subject, + names[Side.LEFT.value], + names[Side.RIGHT.value] + ) + ) + putExtra( + Intent.EXTRA_TEXT, + getString(R.string.share_message, + names[Side.LEFT.value], + names[Side.RIGHT.value], + winnerName, + score[0], + score[1] + ) + ) + type = "text/plain" + } + startActivity(sendIntent) + } + ) + setNegativeButton( + R.string.quit_button, + DialogInterface.OnClickListener { dialog, id -> + activity?.finish() + } + ) + }.create() } } \ No newline at end of file diff --git a/app/src/main/java/adrienmalin/pingpoints/MainActivity.kt b/app/src/main/java/adrienmalin/pingpoints/MainActivity.kt index 750e844..e28953f 100644 --- a/app/src/main/java/adrienmalin/pingpoints/MainActivity.kt +++ b/app/src/main/java/adrienmalin/pingpoints/MainActivity.kt @@ -3,37 +3,17 @@ package adrienmalin.pingpoints import android.content.pm.ActivityInfo import android.support.v7.app.AppCompatActivity import android.os.Bundle -import android.text.Html import android.view.View import android.widget.Button import android.os.Build -import android.text.Spanned import android.text.TextUtils.join -import kotlin.math.abs -import android.support.design.widget.Snackbar -import android.support.v4.app.DialogFragment import android.widget.Toast -@SuppressWarnings("deprecation") -fun fromHtml(html: String): Spanned { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY) - } else { - Html.fromHtml(html) - - } -} - - class MainActivity : AppCompatActivity(), StarterNameDialog.StarterNameDialogListener{ - var players: Array = arrayOf( - Player(), - Player() - ) - var server: Int = 0 - var notServer: Int = 1 - + var players: Array = emptyArray() + var serviceSide: Side = Side.LEFT + var relaunchSide: Side = Side.RIGHT var textScore: android.widget.TextView? = null var textService: android.widget.TextView? = null @@ -43,114 +23,112 @@ class MainActivity : AppCompatActivity(), StarterNameDialog.StarterNameDialogLis override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + //setSupportActionBar(findViewById(R.id.toolbar)) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE } - val defaultNames: Array = resources.getStringArray(R.array.players_names) - for ((player, defaultName) in players.zip(defaultNames)) { - player.name = defaultName - } + var names: Array = intent.getStringArrayExtra("names") ?: resources.getStringArray(R.array.default_players_names) + players = arrayOf( + Player(names[Side.LEFT.value]), + Player(names[Side.RIGHT.value]) + ) textScore = findViewById(R.id.textScore) textService = findViewById(R.id.textService) buttons = arrayOf( - findViewById(R.id.buttonPlayer1), - findViewById(R.id.buttonPlayer2) + findViewById(R.id.buttonLeftPlayer), + findViewById(R.id.buttonRightPlayer) ) + updateUI() + openStarterNameDialog() - - update_ui() - - Toast.makeText(applicationContext, R.string.info, Snackbar.LENGTH_LONG) - .show() } fun openStarterNameDialog() { - val (loser, winner) = players.sortedBy { it.score } - var starterNameDialog: EndOfMatchDialog = EndOfMatchDialog() - starterNameDialog.arguments = Bundle() - starterNameDialog.arguments?.putString("PLAYER_1_NAME", players[0].name) - starterNameDialog.arguments?.putString("PLAYER_2_NAME", players[1].name) - starterNameDialog.show( + StarterNameDialog().apply { + val names = players.map{ it.name }.toTypedArray() + arguments = Bundle().apply { + putStringArray("names", names) + } + show( supportFragmentManager, - join(" ", arrayOf(winner.name, winner.score.toString(), "-", loser.name, loser.score.toString())) - ) + "StarterNameDialog:" + join(" vs. ", names) + ) + } } - override fun onStaterNameDialogPositiveClick(dialog: DialogFragment) { - val inputPlayer1Name: android.widget.EditText? = findViewById(R.id.input_player_1_name) - players[0].name = inputPlayer1Name?.text.toString() - val inputPlayer2Name: android.widget.EditText? = findViewById(R.id.input_player_2_name) - players[1].name = inputPlayer2Name?.text.toString() + override fun setStarterName(serviceSide: Side, names: Collection) { + players.zip(names).forEach { (player, name) -> player.name = name} + this.serviceSide = serviceSide + relaunchSide = when(serviceSide) { + Side.LEFT -> Side.RIGHT + Side.RIGHT -> Side.LEFT + } + + updateUI() + Toast.makeText(applicationContext, R.string.info, Toast.LENGTH_LONG).show() } - fun update_ui() { - - textScore?.text = getString(R.string.score, players[server].score, players[notServer].score) - - textService?.text = getString(R.string.service, players[server].name) + fun updateUI() { + textScore?.text = getString(R.string.score, players[serviceSide.value].score, players[relaunchSide.value].score) + textService?.text = getString(R.string.service, players[serviceSide.value].name) for ((button, player) in buttons.zip(players)) { button.text = fromHtml(getString(R.string.button_text, player.name, player.score)) } - if (server == 0) { - buttons[0].setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_button, 0, 0, 0) - buttons[1].setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0) - } else { - buttons[0].setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0) - buttons[1].setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_button, 0) - } - } - - fun onClickPlayer1(view: View) { - updateScore(players[0]) - } - - fun onClickPlayer2(view: View) { - updateScore(players[1]) - } - - fun finishedMatch() = ( - (players.map { it -> it.score } .max() ?: 0 >= 11) or - (abs(players[0].score - players[1].score) >= 2) - ) - - fun updateScore(scoringPlayer: Player) { - if ( !finishedMatch() ) { - scoringPlayer.score++ - if (players.sumBy { it.score } % 2 == 0) { - server = notServer.also { notServer = server } + when (serviceSide) { + Side.LEFT -> { + buttons[Side.LEFT.value].setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_service, 0, 0, 0) + buttons[Side.RIGHT.value].setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_relaunch, 0, 0, 0) + } + Side.RIGHT -> { + buttons[Side.LEFT.value].setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_relaunch, 0) + buttons[Side.RIGHT.value].setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_service, 0) } } - if ( finishedMatch() ) { + } + + fun onClickLeftPlayer(view: View) { + updateScore(players[Side.LEFT.value]) + } + + fun onClickRightPlayer(view: View) { + updateScore(players[Side.RIGHT.value]) + } + + fun updateScore(scoringPlayer: Player) { + if ( !matchIsFinished() ) { + scoringPlayer.score++ + if (players.sumBy { it.score } % 2 == 0) { + serviceSide = relaunchSide.also { relaunchSide = serviceSide } + } + } + if ( matchIsFinished() ) { openEndOfMatchDialog() } - update_ui() + updateUI() + } + + fun matchIsFinished(): Boolean { + val (minScore, maxScore) = players.map { it.score }.sorted() + return (maxScore >= 11) and (maxScore - minScore >= 2) } fun openEndOfMatchDialog() { - var endOfMatchDialog: EndOfMatchDialog = EndOfMatchDialog() - val (loser, winner) = players.sortedBy { it.score } - endOfMatchDialog.arguments = Bundle() - endOfMatchDialog.arguments?.putString("PLAYER_1_NAME", players[0].name) - endOfMatchDialog.arguments?.putString("PLAYER_2_NAME", players[1].name) - endOfMatchDialog.arguments?.putString("WINNER_NAME", winner.name) - endOfMatchDialog.arguments?.putInt("WINNER_SCORE", winner.score) - endOfMatchDialog.arguments?.putInt("LOSER_SCORE", loser.score) - endOfMatchDialog.show( - supportFragmentManager, - join(" ", arrayOf(winner.name, winner.score.toString(), "-", loser.name, loser.score.toString())) - ) + EndOfMatchDialog().apply { + arguments = Bundle().apply { + putStringArray("names", players.map{ it.name }.toTypedArray()) + putString("winnerName", players.maxBy { it.score }?.name) + putIntArray("score", players.map{ it.score }.sortedDescending().toIntArray()) + } + show( + supportFragmentManager, + "EndOfMatchDialog" + ) + } } - -} - -data class Player( - var name: String = "", - var score: Int = 0, - var serviceText: String = "" -) \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/java/adrienmalin/pingpoints/StarterNameDialog.kt b/app/src/main/java/adrienmalin/pingpoints/StarterNameDialog.kt index 4567b6b..205e49e 100644 --- a/app/src/main/java/adrienmalin/pingpoints/StarterNameDialog.kt +++ b/app/src/main/java/adrienmalin/pingpoints/StarterNameDialog.kt @@ -4,53 +4,58 @@ import android.app.AlertDialog import android.app.Dialog import android.os.Bundle import android.support.v4.app.DialogFragment - -import java.util.ArrayList import android.app.Activity - - +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.widget.EditText +import android.widget.RadioGroup +import android.widget.TextView class StarterNameDialog : DialogFragment() { interface StarterNameDialogListener { - fun onStaterNameDialogPositiveClick(dialog: DialogFragment) + fun setStarterName(serviceSide: Side, names: Collection) } - var listener: StarterNameDialogListener? = null + var mainActivity: StarterNameDialogListener? = null override fun onAttach(activity: Activity?) { super.onAttach(activity) try { - listener = activity as StarterNameDialogListener? + mainActivity = activity as StarterNameDialogListener } catch (e: ClassCastException) { throw ClassCastException(activity!!.toString() + " must implement StarterNameDialogListener") } } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val inputPlayer1Name: android.widget.EditText? = findViewById(R.id.input_player_1_name) - val player1Name = arguments?.getString("PLAYER_1_NAME") - inputPlayer1Name?.setText(player1Name, TextView.BufferType.EDITABLE) + val inflater:LayoutInflater = context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + val namesView: View = inflater.inflate(R.layout.starter_name_dialog, null) + val inputsPlayersNames: Array = arrayOf( + namesView.findViewById(R.id.inputLeftPlayerName), + namesView.findViewById(R.id.inputRightPlayerName) + ) + arguments?.getStringArray("names")?.apply{ + zip(inputsPlayersNames).forEach { + (name, inputPlayerName) -> inputPlayerName?.setText(name, TextView.BufferType.EDITABLE) + } + } - val inputPlayer2Name: android.widget.EditText? = findViewById(R.id.input_player_2_name) - val player2Name = arguments?.getString("PLAYER_2_NAME") - inputPlayer2Name?.setText(player2Name, TextView.BufferType.EDITABLE) - - val builder = AlertDialog.Builder(activity) - // Set the dialog title - builder.setTitle(R.string.new_match) - // Specify the list array, the items to be selected by default (null for none), - // and the listener through which to receive callbacks when items are selected - .setMultiChoiceItems(0, null) - .setPositiveButton(R.string.go_button) { dialog, id -> - // User clicked OK, so save the mSelectedItems results somewhere - // or return them to the component that opened the dialog - //... - } - .setNegativeButton(R.string.quit_button) { dialog, id -> - activity?.finish() - } - - return builder.create() + return AlertDialog.Builder(activity).apply { + setTitle(R.string.starter_name_dialog_message) + setView(namesView) + setPositiveButton(R.string.go_button) { dialog, id -> + mainActivity?.setStarterName( + when ((namesView.findViewById(R.id.radioGroup) as RadioGroup)?.checkedRadioButtonId) { + R.id.radioLeftPlayer -> Side.LEFT + else -> Side.RIGHT + }, + inputsPlayersNames.map{ it?.text.toString() } + ) + dismiss() + } + setNegativeButton(R.string.quit_button) { dialog, id -> activity?.finish() } + }.create() } } diff --git a/app/src/main/java/adrienmalin/pingpoints/classes.kt b/app/src/main/java/adrienmalin/pingpoints/classes.kt new file mode 100644 index 0000000..5020ae0 --- /dev/null +++ b/app/src/main/java/adrienmalin/pingpoints/classes.kt @@ -0,0 +1,28 @@ +package adrienmalin.pingpoints + +import android.os.Build +import android.text.Html +import android.text.Spanned + + +data class Player( + var name: String, + var score: Int = 0 +) + + +enum class Side(val value:Int) { + LEFT(0), + RIGHT(1) +} + + +@SuppressWarnings("deprecation") +fun fromHtml(html: String): Spanned { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY) + } else { + Html.fromHtml(html) + + } +} diff --git a/app/src/main/java/adrienmalin/pingpoints/test.java b/app/src/main/java/adrienmalin/pingpoints/test.java deleted file mode 100644 index 6906cc1..0000000 --- a/app/src/main/java/adrienmalin/pingpoints/test.java +++ /dev/null @@ -1,44 +0,0 @@ -package adrienmalin.pingpoints; - -public class test { - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - mSelectedItems = new ArrayList(); // Where we track the selected items - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - // Set the dialog title - builder.setTitle(R.string.pick_toppings) - // Specify the list array, the items to be selected by default (null for none), - // and the listener through which to receive callbacks when items are selected - .setMultiChoiceItems(R.array.toppings, null, - new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, - boolean isChecked) { - if (isChecked) { - // If the user checked the item, add it to the selected items - mSelectedItems.add(which); - } else if (mSelectedItems.contains(which)) { - // Else, if the item is already in the array, remove it - mSelectedItems.remove(Integer.valueOf(which)); - } - } - }) - // Set the action buttons - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // User clicked OK, so save the mSelectedItems results somewhere - // or return them to the component that opened the dialog - ... - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - ... - } - }); - - return builder.create(); - } -} diff --git a/app/src/main/res/drawable-hdpi/ic_button.png b/app/src/main/res/drawable-hdpi/ic_button.png deleted file mode 100644 index a59b878..0000000 Binary files a/app/src/main/res/drawable-hdpi/ic_button.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_button.png b/app/src/main/res/drawable-mdpi/ic_button.png deleted file mode 100644 index a2ddde6..0000000 Binary files a/app/src/main/res/drawable-mdpi/ic_button.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_button.png b/app/src/main/res/drawable-xhdpi/ic_button.png deleted file mode 100644 index 7fc7916..0000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_button.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_button.png b/app/src/main/res/drawable-xxhdpi/ic_button.png deleted file mode 100644 index 3505d76..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_button.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_about.xml b/app/src/main/res/drawable/ic_about.xml new file mode 100644 index 0000000..12e67e7 --- /dev/null +++ b/app/src/main/res/drawable/ic_about.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..86e83ec --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_relaunch.xml b/app/src/main/res/drawable/ic_relaunch.xml new file mode 100644 index 0000000..672fc21 --- /dev/null +++ b/app/src/main/res/drawable/ic_relaunch.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_service.xml b/app/src/main/res/drawable/ic_service.xml new file mode 100644 index 0000000..5fe52b7 --- /dev/null +++ b/app/src/main/res/drawable/ic_service.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_credits.xml b/app/src/main/res/layout/activity_credits.xml new file mode 100644 index 0000000..008ca32 --- /dev/null +++ b/app/src/main/res/layout/activity_credits.xml @@ -0,0 +1,41 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ee9bf0d..d4ed6c0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,6 +7,8 @@ tools:context=".MainActivity" tools:layout_editor_absoluteY="73dp"> + + @@ -70,7 +70,7 @@ app:layout_constraintTop_toBottomOf="@+id/linearLayoutText">