Compare commits

..

96 Commits

Author SHA1 Message Date
7a35f96061 Merge from github 2020-09-17 19:40:05 +02:00
7bbd94560e Merge pull request #2 from adrienmalin/V2.4
V2.4 Android 10
2020-09-12 15:48:37 +02:00
b651b26ed5 Update .gitignore 2020-09-12 15:46:21 +02:00
dafa3308ea Update StarterNameActivity.kt
suppress unused parameter warning
2020-09-12 15:44:25 +02:00
58b7c35219 Compatibility with Android 10
Refresh GUI
2020-09-12 15:39:42 +02:00
7eeb2fc5f8 change applicationId to new URL 2019-09-22 14:40:10 +02:00
a3a3bcc673 Better english translation of the description 2019-08-31 18:35:36 +02:00
c49026fa79 Update README.md 2019-08-31 18:34:33 +02:00
15c582e7e3 Update MatchActivity.kt 2019-05-13 19:12:41 +02:00
720795cfd6 small changes 2018-12-18 15:29:28 +01:00
a6287e1760 compare with soundex 2018-12-18 15:25:17 +01:00
2564d1b8fa Update SttDialog.kt 2018-12-18 08:30:14 +01:00
3722d27f6a Update SttDialog.kt 2018-12-18 01:00:26 +01:00
6e8afbdd35 Update .gitignore 2018-12-18 00:59:34 +01:00
7b653ec95d ignore case 2018-12-18 00:57:01 +01:00
03f24fbce2 Merge branch 'master' of https://github.com/adrienmalin/PingPoints 2018-12-18 00:53:36 +01:00
d46eccacaa Update .gitignore 2018-12-18 00:47:49 +01:00
8c483824b8 Improve regex 2018-12-17 18:11:18 +01:00
98fec45f4f back to regex 2018-12-17 17:32:39 +01:00
6a51441c0f small changes 2018-12-17 17:23:17 +01:00
c1193f2166 improve lifecycle 2018-12-17 08:01:56 +01:00
0dcef96194 Update build.gradle 2018-12-17 00:04:34 +01:00
dc08b52e0a Move credits to victory activity 2018-12-16 23:55:11 +01:00
4c06a3335e Update SttDialog.kt 2018-12-16 15:09:44 +01:00
1cab126adb Update SttDialog.kt 2018-12-16 14:33:54 +01:00
d3410b14f3 Update SttDialog.kt 2018-12-16 00:01:05 +01:00
a86a57889d parse stt on partial results 2018-12-15 23:51:25 +01:00
f6842a3832 Update dialog_stt.xml 2018-12-15 16:22:02 +01:00
1fa8ea1f0b Change catchphrase to "point %s" 2018-12-15 16:19:46 +01:00
9942cbdcd6 Revert "use string.equals(ignoreCase=true) instead of regex"
This reverts commit 4bb1ff5b42.
2018-12-14 21:22:42 +01:00
4bb1ff5b42 use string.equals(ignoreCase=true) instead of regex 2018-12-14 20:46:27 +01:00
222c414cf2 remove unnecessary frame on stt dialog 2018-12-14 17:42:21 +01:00
8879b6c6d2 Merge branch 'master' of https://github.com/adrienmalin/PingPoints 2018-12-10 21:19:45 +01:00
27f509a835 fix previous matches load 2018-12-10 21:19:41 +01:00
5a1fef3f69 Update dialog_stt.xml 2018-12-10 10:56:25 +01:00
464cda09b9 Merge pull request #1 from adrienmalin/V2
V2 Text to speech and voice recognition
2018-12-10 00:18:10 +01:00
3ed8efb129 add Readme 2018-12-10 00:17:41 +01:00
35f06dc12d Update StarterNameActivity.kt 2018-12-08 15:53:29 +01:00
719b0c252c fix mute on STT and starterRadioButton restoration 2018-12-08 15:07:26 +01:00
fb2f81226f Add next focus to the other textView 2018-12-08 14:38:41 +01:00
6c1ff4f20f Split into functions 2018-12-08 02:37:57 +01:00
73f59c8dcf fix icStt transparancy 2018-12-08 01:21:16 +01:00
7286bef089 mute STT bips 2018-12-07 17:47:00 +01:00
9d9eaef88d Fix STT stopping after 5s of silence 2018-12-07 17:10:50 +01:00
fcb2b90999 on stop stop listening 2018-12-07 16:08:14 +01:00
2edc43fd95 SttDialog 2018-12-07 15:47:20 +01:00
1454713881 Return to victory activity after back button press 2018-12-07 12:35:37 +01:00
ef149251ff Fix warnings 2018-12-07 12:33:10 +01:00
d3d90b176c suppress a comma 2018-12-07 12:19:19 +01:00
1f624dfd51 code cleanup 2018-12-07 12:18:42 +01:00
3ddff42431 Code cleanup 2018-12-07 12:08:48 +01:00
861196e118 Fix undo 2018-12-07 11:59:43 +01:00
c78e159dc6 clean code 2018-12-07 11:51:05 +01:00
13e7710a96 Update README.md 2018-12-07 10:58:37 +01:00
67d94d2cd8 Change titles' size 2018-12-07 10:57:05 +01:00
394af9657d Add french and privacy rules 2018-12-07 10:56:14 +01:00
00199369e8 Update grid_item.xml 2018-12-07 01:35:32 +01:00
bcfa4cb57c previous matches table tweaks 2018-12-07 01:07:30 +01:00
ff57c29ce1 bug fix 2018-12-06 23:57:45 +01:00
0bfb13f678 little changes 2018-12-06 21:29:05 +01:00
c5ee9b6bbf add text margin on match layout 2018-12-06 18:11:55 +01:00
79daaf6968 button hint if no STT 2018-12-06 18:05:53 +01:00
b965302c52 Custom STT dialog 2018-12-06 17:33:23 +01:00
1efae35fea Invisible STT 2018-12-06 15:56:25 +01:00
de4ff89233 some changes 2018-12-05 22:47:14 +01:00
512151d69c Remove unecessary internet permission 2018-12-05 21:11:30 +01:00
8bfb519bb3 improvements 2018-12-05 20:17:41 +01:00
8d0cadaf88 listen to switch swap 2018-12-05 17:27:55 +01:00
bc7472cd95 Change start button text 2018-12-05 17:13:02 +01:00
dccc75d1ea change check TTS and STT 2018-12-05 16:56:55 +01:00
d2df43bf02 Remove menu, action bar, redo 2018-12-05 12:45:12 +01:00
04f388bc1e Link Android back button to undo 2018-12-05 12:23:07 +01:00
b92b0acd89 Add snakbar message when STT is cancelled for the 3rd time 2018-12-05 12:17:09 +01:00
2c64cac3c2 Correct button touch 2018-12-05 11:29:45 +01:00
80e3b61dd4 solved launcher icon problem 2018-12-05 11:24:58 +01:00
5b41d35db3 clean code 2018-12-05 11:09:58 +01:00
d65944be2e Less match finish calculation 2018-12-05 08:55:37 +01:00
bfea110ecc change result display on victory activity 2018-12-05 08:49:21 +01:00
c794555ae4 TTS properly initialized 2018-12-05 01:50:46 +01:00
dcb598cda7 almost good
But why no TTS on game start!?
2018-12-05 01:15:33 +01:00
aab005447d STT 2018-12-05 00:17:15 +01:00
3a34e9a390 Match point + previous matches in table 2018-12-04 20:52:15 +01:00
7b2c35c5a6 Victory! 2018-12-04 18:25:47 +01:00
46333265bd MatchActivity almost finished. Started VictoryActivity 2018-12-04 15:50:07 +01:00
f2a2f8859b fighting with android studio 2018-12-04 00:06:49 +01:00
9f4b35070d dfghj 2018-12-03 23:41:52 +01:00
621c035c74 try to make viewmodel work 2018-12-03 22:25:24 +01:00
ef230d5520 start MatchActivity 2018-12-03 17:43:27 +01:00
83d50e6294 Update AndroidManifest.xml 2018-12-03 08:46:12 +01:00
1243338fa3 Add permission for speech recognition in manifest 2018-12-03 08:45:25 +01:00
76d60dfb2c Finished StarterNameActivity 2018-12-02 23:44:10 +01:00
8b8aecb1c6 StarterNameActivity code 2018-12-01 14:42:04 +01:00
2982096e47 fix layout 2018-11-30 18:30:39 +01:00
3f16dbd49d StarterNameActivity layout 2018-11-30 18:09:34 +01:00
7f153ef64f V2 initialization 2018-11-30 16:49:01 +01:00
96c8f113bb use github release 2018-08-20 21:58:57 +02:00
76 changed files with 2017 additions and 1054 deletions

5
.gitignore vendored
View File

@ -1,10 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea
.DS_Store
/build
/captures
.externalNativeBuild
/app/release/

View File

@ -13,46 +13,6 @@
<PersistentState>
<option name="children">
<map>
<entry key="actionbar">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="clipartAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="url" value="jar:file:/C:/Program%20Files/Android/Android%20Studio/plugins/android/lib/android.jar!/images/material_design_icons/action/ic_info_outline_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="textAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="text" value="" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="assetType" value="TEXT" />
<entry key="imageAsset" value="C:\Users\adima\Downloads\ping-pong (2).png" />
<entry key="outputName" value="not_server" />
<entry key="theme" value="HOLO_DARK" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="launcher">
<value>
<PersistentState>
@ -64,7 +24,6 @@
<option name="values">
<map>
<entry key="scalingPercent" value="90" />
<entry key="trimmed" value="true" />
</map>
</option>
</PersistentState>
@ -75,21 +34,7 @@
<option name="values">
<map>
<entry key="backgroundAssetType" value="COLOR" />
<entry key="backgroundColor" value="3c3a41" />
<entry key="foregroundImage" value="C:\Users\adima\AndroidStudioProjects\PingPoints\app\src\main\res\drawable\ic_ping_pong_table.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="launcherLegacy">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="assetType" value="IMAGE" />
<entry key="iconShape" value="NONE" />
<entry key="imageAsset" value="C:\Users\adima\Downloads\ping-pong (1).png" />
<entry key="foregroundImage" value="C:\Users\adrien.malingrey\Documents\GitHub\PingPoints.V1\app\src\main\res\drawable\ic_launcher_foreground.xml" />
</map>
</option>
</PersistentState>
@ -120,7 +65,7 @@
<PersistentState>
<option name="values">
<map>
<entry key="url" value="jar:file:/C:/Program%20Files/Android/Android%20Studio/plugins/android/lib/android.jar!/images/material_design_icons/content/ic_redo_black_24dp.xml" />
<entry key="url" value="jar:file:/C:/Program%20Files/Android/Android%20Studio/plugins/android/lib/android.jar!/images/material_design_icons/hardware/ic_keyboard_voice_black_24dp.xml" />
</map>
</option>
</PersistentState>
@ -130,10 +75,9 @@
</option>
<option name="values">
<map>
<entry key="autoMirrored" value="true" />
<entry key="color" value="ffffff" />
<entry key="outputName" value="ic_redo" />
<entry key="sourceFile" value="C:\Users\adima\Downloads\ping-pong (3).svg" />
<entry key="outputName" value="ic_stt" />
<entry key="sourceFile" value="C:\Users\adima" />
</map>
</option>
</PersistentState>

Binary file not shown.

View File

@ -1,5 +1,24 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
@ -25,5 +44,117 @@
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
<codeStyleSettings language="XML">
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

2
.idea/gradle.xml generated
View File

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">

6
.idea/kotlinc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Kotlin2JsCompilerArguments">
<option name="sourceMapEmbedSources" />
</component>
</project>

18
.idea/misc.xml generated
View File

@ -5,22 +5,36 @@
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="5">
<list size="12">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="7" class="java.lang.String" itemvalue="android.annotation.Nullable" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
<item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<list size="11">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="6" class="java.lang.String" itemvalue="android.annotation.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
</list>
</value>
</option>

2
.idea/vcs.xml generated
View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,6 +1,25 @@
# PingPoints
Android App to count points on a Tenis Table match
![Screenshot](https://lh3.googleusercontent.com/BLXMJi7AGF99XptdL0OPLIzFNRFaiAuBCH8VuzXxoUxBUNoQE5bmtxGZqeQIJbq4npVZ=w1111-h649-rw "Screenshot")
![Screenshot](https://lh3.googleusercontent.com/lxAM0pIfDd4HPsbj9xpOWQBgtF89MC81FTAy_fzHImGtJxJU_hfpgZQcCmUZyLUHN0I=w1111-h649-rw "Screenshot")
![Screenshot](https://lh3.googleusercontent.com/wsPhD-GgFhbPvb9-gqsn1Z_FUChltVMitNrW41-wmQsFr_-9VfWYaOWof_yGK_P_7g=w1111-h649-rw "Screenshot")
### English
Android app to score points in a table tennis match
Get it on [Google Play Store](https://play.google.com/store/apps/details?id=adrienmalin.pingpoints)
#### Privacy rules
Audio record permission is only used for Google's speech recognition API.
You can use this app without it.
### Français
Appli Android pour compter les points d'un match de tennis de table
Disponible sur le [Google Play Store](https://play.google.com/store/apps/details?id=adrienmalin.pingpoints)
#### Règles de confidentialité
La permission d'enregistrement audio sert uniquement à utiliser l'API Google de reconnaissance vocale.
Elle n'est pas obligatoire pour utiliser l'application.

View File

@ -5,14 +5,13 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
compileSdkVersion 30
defaultConfig {
applicationId "adrienmalin.pingpoints"
applicationId "fr.malingrey.pingpoints"
minSdkVersion 15
targetSdkVersion 28
versionCode 2
versionName "1.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
targetSdkVersion 30
versionCode 10
versionName "2.4"
vectorDrawables.useSupportLibrary true
}
buildTypes {
@ -24,13 +23,13 @@ android {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0-rc01'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.android.support:support-v4:28.0.0-rc01'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:design:28.0.0-rc01'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0'
implementation 'com.google.android.material:material:1.2.1'
}

Binary file not shown.

View File

@ -1 +1 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":2,"versionName":"1.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":5,"versionName":"2.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]

View File

@ -1,24 +0,0 @@
package adrienmalin.pingpoints
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext()
assertEquals("adrienmalin.pingpoints", appContext.packageName)
}
}

View File

@ -1,30 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="adrienmalin.pingpoints">
package="adrienmalin.pingpoints">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar">
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:fullBackupContent="@xml/backup_descriptor"
android:theme="@style/PingPointsTheme">
<activity
android:name=".MainActivity"
android:screenOrientation="sensorLandscape"
android:theme="@style/Theme.AppCompat.NoActionBar">
android:name=".StarterNameActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".CreditsActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
android:name=".MatchActivity">
</activity>
<activity android:name=".VictoryActivity">
</activity>
</application>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,23 +0,0 @@
package adrienmalin.pingpoints
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.text.method.LinkMovementMethod
import android.view.MenuItem
import android.widget.TextView
class CreditsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_credits)
setSupportActionBar(findViewById(R.id.toolbar))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
findViewById<TextView>(R.id.iconsCredit)?.movementMethod = LinkMovementMethod.getInstance()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
finish()
return true
}
}

View File

@ -1,59 +0,0 @@
package adrienmalin.pingpoints
import android.app.AlertDialog
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.DialogFragment
class EndOfMatchDialog: DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?)=
AlertDialog.Builder(activity).apply{
val players = (activity as MainActivity).players
val names = players.map { it.name }
val winnerName = players.maxBy { it.score }?.name ?: ""
val score = players.map { it.score }.sortedDescending()
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.toTypedArray())
}
)
}
)
setNeutralButton(
R.string.share_button,
DialogInterface.OnClickListener { dialog, id ->
val newMatchIntent: 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(newMatchIntent)
}
)
}.create()
}

View File

@ -1,181 +0,0 @@
package adrienmalin.pingpoints
import android.content.Intent
import android.content.pm.ActivityInfo
import android.os.Build
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.app.AppCompatDelegate
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.Toast
class MainActivity : AppCompatActivity() {
var players: Array<Player> = emptyArray()
var serviceSide: Side = Side.LEFT
var relaunchSide: Side = Side.RIGHT
var textScore: android.widget.TextView? = null
var textService: android.widget.TextView? = null
var buttons: Array<Button> = emptyArray()
var imageViews: Array<ImageView?> = emptyArray()
var history: MutableList<State> = ArrayList()
var step: Int = 0
var undo: MenuItem? = null
var redo: MenuItem? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
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
}
var names: Array<String> = 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.buttonLeftPlayer),
findViewById(R.id.buttonRightPlayer)
)
imageViews = arrayOf(
findViewById(R.id.imgLeftService),
findViewById(R.id.imgRightService)
)
updateUI()
StarterNameDialog().show( supportFragmentManager, "StarterNameDialog")
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main, menu)
undo = menu.findItem(R.id.action_undo)
redo = menu.findItem(R.id.action_redo)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.action_undo -> {
step--
reloadState()
redo?.isVisible = true
true
}
R.id.action_redo -> {
step++
reloadState()
undo?.isVisible = true
true
}
R.id.action_new_match -> {
startActivity(
Intent(this, MainActivity::class.java).apply {
putExtra("names", players.map{ it.name }.toTypedArray())
}
)
true
}
R.id.action_about -> {
startActivity(Intent(this, CreditsActivity::class.java))
true
}
else -> {
super.onOptionsItemSelected(item)
}
}
fun saveState() {
val state = State(players.map { it.score }, serviceSide)
if (step == history.size) {
history.add(state)
} else {
history[step] = state
history = history.subList(0, step+1).toMutableList()
}
if (step > 0) {
undo?.isVisible = true
}
redo?.isVisible = false
}
fun reloadState() {
history[step].let{
players.zip(it.score).forEach{(player, score) -> player.score = score}
serviceSide = it.serviceSide
relaunchSide = when(serviceSide) {
Side.LEFT -> Side.RIGHT
Side.RIGHT -> Side.LEFT
}
}
when(step){
0 -> undo?.isVisible = false
history.size - 1 -> redo?.isVisible = false
}
this.step = step
updateUI()
}
fun setStarterName(serviceSide: Side, names: Collection<String>) {
players.zip(names).forEach { (player, name) -> player.name = name}
this.serviceSide = serviceSide
relaunchSide = when(serviceSide) {
Side.LEFT -> Side.RIGHT
Side.RIGHT -> Side.LEFT
}
saveState()
updateUI()
Toast.makeText(applicationContext, R.string.info, Toast.LENGTH_LONG).show()
}
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))
}
when (serviceSide) {
Side.LEFT -> {
imageViews[Side.LEFT.value]?.setImageResource(R.drawable.ic_left_service)
imageViews[Side.RIGHT.value]?.setImageResource(0)
}
Side.RIGHT -> {
imageViews[Side.LEFT.value]?.setImageResource(0)
imageViews[Side.RIGHT.value]?.setImageResource(R.drawable.ic_right_service)
}
}
}
fun updateScore(view: View) {
for (side in enumValues<Side>()) {
if (view == buttons[side.value]) {
if (!matchIsFinished()) {
step++
players[side.value].score++
if ((players.sumBy { it.score } % 2 == 0) or (players.all { it.score >= 10 })) {
serviceSide = relaunchSide.also { relaunchSide = serviceSide }
}
saveState()
updateUI()
}
if (matchIsFinished()) {
EndOfMatchDialog().show(supportFragmentManager, "EndOfMatchDialog")
}
}
}
}
fun matchIsFinished(): Boolean {
val (minScore, maxScore) = players.map { it.score }.sorted()
return (maxScore >= 11) and (maxScore - minScore >= 2)
}
}

View File

@ -0,0 +1,394 @@
package adrienmalin.pingpoints
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.media.AudioManager
import android.os.Build
import android.os.Bundle
import android.speech.RecognitionListener
import android.speech.RecognizerIntent
import android.speech.SpeechRecognizer
import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.snackbar.Snackbar
import kotlin.math.max
import kotlin.math.min
class MatchActivity : AppCompatActivity() {
var match: MatchModel? = null
var textScore: android.widget.TextView? = null
var textService: android.widget.TextView? = null
var buttons: Array<Button> = emptyArray()
var imageViews: Array<ImageView> = emptyArray()
var icStt: ImageView? = null
var tts: TextToSpeech? = null
var stt: SpeechRecognizer? = null
inner class WaitForTtsInit : TextToSpeech.OnInitListener {
override fun onInit(status: Int) {
updateUI()
}
}
inner class WaitForTtsSpeak : UtteranceProgressListener() {
override fun onDone(id: String) {
runOnUiThread {
startSTT()
}
}
override fun onStart(id: String) {}
override fun onError(id: String) {}
}
inner class SttListener : RecognitionListener {
var minRms: Float = 0f
var maxRms: Float = 0f
override fun onReadyForSpeech(arg0: Bundle?) {
icStt?.alpha = .5f
}
override fun onBeginningOfSpeech() {}
override fun onBufferReceived(buffer: ByteArray?) {}
override fun onRmsChanged(rmsdB: Float) {
minRms = min(rmsdB, minRms)
maxRms = max(rmsdB, maxRms)
if (minRms != maxRms)
icStt?.alpha = 0.5f + (rmsdB - minRms) / (2 * (maxRms - minRms))
}
override fun onPartialResults(data: Bundle) {}
override fun onResults(data: Bundle) {
stt = null
data.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.let { results ->
match?.apply {
for (result in results) {
Log.i("stt results", result)
val soundex = soundex(result)
for (player in players) {
if (soundex == player.soundex) {
icStt?.alpha = 0f
unMuteAudio()
updateScore(player)
updateUI()
return
}
}
}
}
}
showPopUp(getString(R.string.not_understood))
startSTT()
}
override fun onEndOfSpeech() {}
override fun onError(errorCode: Int) {
muteAudio()
Log.e(
"stt", when (errorCode) {
SpeechRecognizer.ERROR_AUDIO -> "Audio recording error"
SpeechRecognizer.ERROR_CLIENT -> "Client side error"
SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "Insufficient permissions"
SpeechRecognizer.ERROR_NETWORK -> "Network error"
SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "Network timeout"
SpeechRecognizer.ERROR_NO_MATCH -> "No match"
SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "RecognitionService busy"
SpeechRecognizer.ERROR_SERVER -> "Error from server"
SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "No speech input"
else -> "Didn't understand, please try again."
}
)
if (match?.matchStarted == true) startSTT()
}
override fun onEvent(arg0: Int, arg1: Bundle?) {}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
setContentView(R.layout.activity_match)
textScore = findViewById(R.id.textScore)
textService = findViewById(R.id.textService)
buttons = arrayOf(
findViewById(R.id.buttonPlayer0),
findViewById(R.id.buttonPlayer1)
)
imageViews = arrayOf(
findViewById(R.id.imgService0),
findViewById(R.id.imgService1)
)
icStt = findViewById(R.id.icStt)
match = ViewModelProvider(this).get(MatchModel::class.java).apply {
if (!matchStarted) {
intent.apply {
matchStarted = true
val player1Name = getStringExtra("player1Name")
val player2Name = getStringExtra("player2Name")
players = listOf(
Player(player1Name ?: getString(R.string.player_1_default_name), 0),
Player(player2Name ?: getString(R.string.player_2_default_name), 0)
)
players.forEach {
it.soundex = soundex(getString(R.string.soundex, it.name))
}
serviceSide = getIntExtra("starterId", 0)
relaunchSide = when (serviceSide) {
0 -> 1
else -> 0
}
ttsEnabled = getBooleanExtra("enableTTS", false)
sttEnabled = getBooleanExtra("enableSTT", false)
saveState()
if (sttEnabled) {
showPopUp(
getString(
R.string.STT_hint,
players[0].name,
players[1].name
),
Snackbar.LENGTH_LONG
)
} else {
showPopUp(getString(R.string.button_hint))
}
if (ttsEnabled) {
tts = TextToSpeech(this@MatchActivity, WaitForTtsInit()).apply {
if (sttEnabled) setOnUtteranceProgressListener(WaitForTtsSpeak())
}
}
}
}
}
}
override fun onDestroy() {
stopSTT()
super.onDestroy()
}
override fun onResume() {
super.onResume()
updateUI()
}
override fun onPause() {
stopSTT()
super.onPause()
}
fun updateUI() {
match?.apply {
textScore?.text = getString(
R.string.score_score,
players[serviceSide].score,
players[relaunchSide].score
)
textService?.text = getString(R.string.service, players[serviceSide].name)
for ((button, player) in buttons.zip(players))
button.text = fromHtml(getString(R.string.button_text, player.name, player.score))
imageViews[0].setImageResource(
when (serviceSide) {
0 -> R.drawable.ic_service_0
else -> 0
}
)
imageViews[1].setImageResource(
when (serviceSide) {
0 -> 0
else -> R.drawable.ic_service_1
}
)
if (matchStarted) {
if (matchFinished)
proclaimVictory()
else {
if (ttsEnabled) {
unMuteAudio()
var scoreSpeech = getString(
R.string.update_score_speech,
players[serviceSide].score,
players[relaunchSide].score,
players[serviceSide].name
)
if (matchPoint) scoreSpeech += getString(R.string.match_point)
say(scoreSpeech)
} else if (sttEnabled) {
startSTT()
}
}
}
}
}
fun proclaimVictory() {
match?.apply {
matchStarted = false
stopSTT()
val (loser, winner) = players.sortedBy { it.score }
if (ttsEnabled) {
say(
getString(
R.string.victory_speech,
winner.name,
winner.score,
loser.score
)
)
}
startActivity(
Intent(this@MatchActivity, VictoryActivity::class.java).apply {
putExtra("winnerName", winner.name)
putExtra("player1Name", players[0].name)
putExtra("player2Name", players[1].name)
putExtra("player1Score", players[0].score)
putExtra("player2Score", players[1].score)
}
)
}
}
fun updateScore(view: View) {
match?.apply {
if (!matchFinished) {
when (view) {
buttons[0] -> updateScore(players[0])
buttons[1] -> updateScore(players[1])
}
}
updateUI()
}
}
override fun onBackPressed() {
if (match?.pointId == 0)
super.onBackPressed()
else {
match?.undo()
updateUI()
}
}
fun showPopUp(text: String, duration: Int = Snackbar.LENGTH_SHORT) {
Snackbar.make(
findViewById(R.id.coordinatorLayout),
text,
duration
).show()
}
fun showPopUp(textId: Int, duration: Int = Snackbar.LENGTH_INDEFINITE) {
Snackbar.make(
findViewById(R.id.coordinatorLayout),
textId,
duration
).show()
}
fun stopSTT() {
icStt?.alpha = 0f
unMuteAudio()
stt?.stopListening()
stt?.destroy()
stt = null
}
fun startSTT() {
stt?.stopListening()
stt?.destroy()
if (match?.matchStarted == true) {
stt = SpeechRecognizer.createSpeechRecognizer(this@MatchActivity).apply {
setRecognitionListener(SttListener())
try {
startListening(
Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH
)
putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 10)
putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
if (!hasExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE)) {
putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
}
}
)
} catch (e: ActivityNotFoundException) {
match?.sttEnabled = false
showPopUp(R.string.STT_unavailable)
}
}
}
}
@Suppress("DEPRECATION")
fun say(text: String, queueMode: Int = TextToSpeech.QUEUE_FLUSH) {
stopSTT()
tts?.speak(
text,
queueMode,
hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "TTS")
)
}
@Suppress("DEPRECATION")
fun muteAudio() {
(getSystemService(Context.AUDIO_SERVICE) as AudioManager).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_MUTE, 0)
adjustStreamVolume(AudioManager.STREAM_ALARM, AudioManager.ADJUST_MUTE, 0)
adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE, 0)
adjustStreamVolume(AudioManager.STREAM_RING, AudioManager.ADJUST_MUTE, 0)
adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_MUTE, 0)
} else {
setStreamMute(AudioManager.STREAM_NOTIFICATION, true)
setStreamMute(AudioManager.STREAM_ALARM, true)
setStreamMute(AudioManager.STREAM_MUSIC, true)
setStreamMute(AudioManager.STREAM_RING, true)
setStreamMute(AudioManager.STREAM_SYSTEM, true)
}
}
}
@Suppress("DEPRECATION")
fun unMuteAudio() {
(getSystemService(Context.AUDIO_SERVICE) as AudioManager).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_UNMUTE, 0)
adjustStreamVolume(AudioManager.STREAM_ALARM, AudioManager.ADJUST_UNMUTE, 0)
adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_UNMUTE, 0)
adjustStreamVolume(AudioManager.STREAM_RING, AudioManager.ADJUST_UNMUTE, 0)
adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_UNMUTE, 0)
} else {
setStreamMute(AudioManager.STREAM_NOTIFICATION, false)
setStreamMute(AudioManager.STREAM_ALARM, false)
setStreamMute(AudioManager.STREAM_MUSIC, false)
setStreamMute(AudioManager.STREAM_RING, false)
setStreamMute(AudioManager.STREAM_SYSTEM, false)
}
}
}
}

View File

@ -0,0 +1,53 @@
package adrienmalin.pingpoints
import androidx.lifecycle.ViewModel
class MatchModel : ViewModel() {
var matchStarted: Boolean = false
var matchFinished: Boolean = false
var matchPoint: Boolean = false
var players: List<Player> = emptyList()
var serviceSide: Int = 0
var relaunchSide: Int = 1
var ttsEnabled: Boolean = false
var sttEnabled: Boolean = false
var pointId: Int = -1
var history: MutableList<Point> = ArrayList()
fun updateScore(scorer: Player) {
scorer.score++
if ((players.sumBy { it.score } % 2 == 0) or (players.all { it.score >= 10 })) {
serviceSide = relaunchSide.also { relaunchSide = serviceSide }
}
saveState()
updateMatch()
}
fun updateMatch() {
val (minScore, maxScore) = players.map { it.score }.sorted()
matchFinished = (maxScore >= 11) and (maxScore - minScore >= 2)
matchPoint = (maxScore >= 10) and (maxScore - minScore >= 1)
}
fun saveState() {
val point = Point(players.map { it.score }, serviceSide)
if (++pointId == history.size) {
history.add(point)
} else {
history[pointId] = point
}
}
fun undo() {
history[--pointId].let {
players.zip(it.score).forEach{(player, score) -> player.score = score}
serviceSide = it.serviceSide
relaunchSide = when(serviceSide) {
0 -> 1
else -> 0
}
}
updateMatch()
}
}

View File

@ -0,0 +1,7 @@
package adrienmalin.pingpoints
data class Player(
val name: String,
var score: Int,
var soundex: String = ""
)

View File

@ -0,0 +1,6 @@
package adrienmalin.pingpoints
data class Point (
val score: List<Int>,
val serviceSide: Int
)

View File

@ -0,0 +1,199 @@
package adrienmalin.pingpoints
import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Bundle
import android.speech.SpeechRecognizer
import android.speech.tts.TextToSpeech
import android.view.View
import android.widget.ArrayAdapter
import android.widget.AutoCompleteTextView
import android.widget.RadioGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.switchmaterial.SwitchMaterial
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
var enableTtsSwitch: SwitchMaterial? = null
var enableSttSwitch: SwitchMaterial? = null
var previousMatch: SharedPreferences? = null
var previousPlayers: Set<String> = emptySet()
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_starter_name)
findViews()
checkTtsAvailable()
checkSttAvailable()
restorePreviousSettings()
}
fun findViews() {
player1NameInput = findViewById(R.id.player1Name)
player2NameInput = findViewById(R.id.player2Name)
starterRadioGroup = findViewById(R.id.starterRadioGroup)
enableTtsSwitch = findViewById(R.id.enableTtsSwitch)
enableSttSwitch = findViewById(R.id.enableSttSwitch)
}
fun restorePreviousSettings() {
previousMatch = getPreferences(Context.MODE_PRIVATE).apply {
getStringSet("previousPlayers", emptySet())?.let { previousPlayers = it.toSet() }
val adapter = ArrayAdapter(
this@StarterNameActivity,
android.R.layout.simple_list_item_1,
previousPlayers.toList()
)
player1NameInput?.apply {
setText(
getString("previousPlayer2", getString(R.string.player_1_default_name)),
TextView.BufferType.EDITABLE
)
setAdapter(adapter)
}
player2NameInput?.apply{
setText(
getString("previousPlayer1", getString(R.string.player_2_default_name)),
TextView.BufferType.EDITABLE
)
setAdapter(adapter)
}
starterRadioGroup?.check(
when(getInt("previousStarterId", 0)) {
1 -> R.id.radioPlayer2Starts
else -> R.id.radioPlayer1Starts
}
)
enableTtsSwitch?.isChecked = getBoolean("enableTTS", false)
enableSttSwitch?.isChecked = getBoolean("enableSTT", false)
}
}
fun checkTtsAvailable() {
enableTtsSwitch?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
Intent().apply {
action = TextToSpeech.Engine.ACTION_CHECK_TTS_DATA
startActivityForResult(this, CHECK_TTS)
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
CHECK_TTS -> {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
enableTtsSwitch?.isChecked = true
} else {
enableTtsSwitch?.isChecked = false
showText(R.string.TTS_unavailable)
Intent().apply {
action = TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
startActivity(this)
}
}
} else -> {}
}
}
fun checkSttAvailable() {
enableSttSwitch?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
if (SpeechRecognizer.isRecognitionAvailable(this@StarterNameActivity)) {
// Ask for record audio permission
if (ContextCompat.checkSelfPermission(
this@StarterNameActivity,
Manifest.permission.RECORD_AUDIO
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this@StarterNameActivity,
arrayOf(Manifest.permission.RECORD_AUDIO),
ASK_PERMISSIONS_RECORD_AUDIO
)
}
} else {
enableSttSwitch?.isChecked = false
showText(R.string.STT_unavailable)
}
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
ASK_PERMISSIONS_RECORD_AUDIO -> {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
enableSttSwitch?.isChecked = true
} else {
enableSttSwitch?.isChecked = false
showText(R.string.audio_record_permission_denied)
}
} else -> {}
}
}
fun swapNames(@Suppress("UNUSED_PARAMETER") view: View) {
player1NameInput?.text = player2NameInput?.text.also {
player2NameInput?.text = player1NameInput?.text
}
}
fun startMatch(@Suppress("UNUSED_PARAMETER") view: View) {
val player1Name = player1NameInput?.text.toString()
val player2Name = player2NameInput?.text.toString()
val starterId = when (starterRadioGroup?.checkedRadioButtonId) {
R.id.radioPlayer2Starts -> 1
else -> 0
}
val enableTTS = enableTtsSwitch?.isChecked
val enableSTT = enableSttSwitch?.isChecked
// Save settings
previousMatch?.edit()?.apply {
putString("previousPlayer1", player1Name)
putString("previousPlayer2", player2Name)
putInt("previousStarterId", starterId)
putStringSet("previousPlayers", previousPlayers.plus(player1Name).plus(player2Name))
enableTTS?.let { putBoolean("enableTTS", it) }
enableSTT?.let { putBoolean("enableSTT", it) }
apply()
}
startActivity(
Intent(this, MatchActivity::class.java).apply {
putExtra("player1Name", player1Name)
putExtra("player2Name", player2Name)
putExtra("starterId", starterId)
putExtra("enableTTS", enableTTS)
putExtra("enableSTT", enableSTT)
}
)
}
fun showText(textId: Int, duration: Int = Snackbar.LENGTH_SHORT) {
Snackbar.make(
findViewById(R.id.coordinatorLayout),
textId,
duration
).show()
}
}

View File

@ -1,42 +0,0 @@
package adrienmalin.pingpoints
import android.app.AlertDialog
import android.content.Context
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.view.LayoutInflater
import android.view.View
import android.widget.EditText
import android.widget.RadioGroup
import android.widget.TextView
class StarterNameDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?) =
AlertDialog.Builder(activity).apply {
val mainActivity = activity as MainActivity
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<EditText?> = arrayOf(
namesView.findViewById(R.id.inputLeftPlayerName),
namesView.findViewById(R.id.inputRightPlayerName)
)
inputsPlayersNames.zip(mainActivity.players.map{ it.name }).forEach { (inputPlayerName, name) ->
inputPlayerName?.setText(name, TextView.BufferType.EDITABLE)
}
setTitle(R.string.starter_name_dialog_message)
setView(namesView)
setPositiveButton(R.string.go_button) { dialog, id ->
dismiss()
mainActivity.setStarterName(
when (namesView.findViewById<RadioGroup>(R.id.radioGroup)?.checkedRadioButtonId) {
R.id.radioLeftPlayer -> Side.LEFT
else -> Side.RIGHT
},
inputsPlayersNames.map{ it?.text.toString() }
)
}
}.create()
}

View File

@ -0,0 +1,134 @@
package adrienmalin.pingpoints
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.view.View
import android.widget.ArrayAdapter
import android.widget.GridView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.ViewModelProvider
import kotlin.math.max
import kotlin.math.min
class VictoryActivity : AppCompatActivity() {
var victoryModel: VictoryModel? = null
var previousMatch: SharedPreferences? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
setContentView(R.layout.activity_victory)
previousMatch = getPreferences(Context.MODE_PRIVATE)
initVictoryModel()
updateUI()
}
fun initVictoryModel() {
victoryModel = ViewModelProvider(this).get(VictoryModel::class.java).apply {
if (!matchFinished) {
matchFinished = true
winnerName = intent.getStringExtra("winnerName") ?: ""
players = listOf(
Player(
intent.getStringExtra("player1Name")
?: getString(R.string.player_1_default_name),
intent.getIntExtra("player1Score", 0)
),
Player(
intent.getStringExtra("player2Name")
?: getString(R.string.player_2_default_name),
intent.getIntExtra("player2Score", 0)
)
)
previousMatch?.apply{ previousMatches = getString("previousMatches", "") ?: "" }
}
}
}
fun updateUI() {
victoryModel?.apply {
findViewById<TextView>(R.id.congrats).text = getString(R.string.congrats, winnerName)
findViewById<TextView>(R.id.player1NameTextView).text = players[0].name
findViewById<TextView>(R.id.scoreTextView).text = getString(
R.string.score,
players[0].score,
players[1].score
)
findViewById<TextView>(R.id.player2NameTextView).text = players[1].name
findViewById<GridView>(R.id.previousMatchesGrid).adapter = ArrayAdapter(
this@VictoryActivity,
R.layout.grid_item,
R.id.grid_item_text,
previousMatches.split("[\t\n]".toRegex()).toMutableList()
)
}
// Set HTML text for icons credits
findViewById<TextView>(R.id.iconsCredit).apply {
text = fromHtml(getString(R.string.iconCredits))
movementMethod = LinkMovementMethod.getInstance()
}
}
override fun onStop() {
victoryModel?.apply {
previousMatch?.edit()?.apply {
putString(
"previousMatches",
getString(
R.string.results,
players[0].name,
"%2d - %2d".format(players[0].score, players[1].score),
players[1].name,
previousMatches
)
)
apply()
}
}
super.onStop()
}
fun newMatch(@Suppress("UNUSED_PARAMETER") view: View) {
startActivity(
Intent(this, StarterNameActivity::class.java)
)
}
fun share(@Suppress("UNUSED_PARAMETER") view: View) {
victoryModel?.apply {
startActivity(
Intent().apply {
action = Intent.ACTION_SEND
putExtra(
Intent.EXTRA_SUBJECT,
getString(
R.string.share_subject,
players[0].name,
players[1].name
)
)
putExtra(
Intent.EXTRA_TEXT,
getString(
R.string.share_message,
players[0].name,
players[1].name,
winnerName,
max(players[0].score, players[1].score),
min(players[0].score, players[1].score)
)
)
type = "text/plain"
}
)
}
}
}

View File

@ -0,0 +1,10 @@
package adrienmalin.pingpoints
import androidx.lifecycle.ViewModel
class VictoryModel : ViewModel() {
var matchFinished: Boolean = false
var winnerName:String = ""
var players: List<Player> = emptyList()
var previousMatches: String = ""
}

View File

@ -1,33 +0,0 @@
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)
}
data class State(
val score: List<Int>,
val serviceSide: Side
)
@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)
}
}

View File

@ -0,0 +1,12 @@
package adrienmalin.pingpoints
import android.os.Build
import android.text.Html
import android.text.Spanned
@Suppress("DEPRECATION")
fun fromHtml(source: String): Spanned = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> Html.fromHtml(source, Html.FROM_HTML_MODE_COMPACT)
else -> Html.fromHtml(source)
}

View File

@ -0,0 +1,66 @@
package adrienmalin.pingpoints
import java.util.*
import java.util.regex.Pattern
val yNotPrecededByA:Pattern = Pattern.compile("(?<!A)Y")
val hNotPrecededByCS: Pattern = Pattern.compile("(?<![CS])H")
val aInWord: Pattern = Pattern.compile("(?<!\\b)A")
val silentEndLetter = Pattern.compile("[ADST](?=\\b)")
val notALetter = Pattern.compile("\\W")
val doubleLetter = Pattern.compile("(\\w)\\1+(?!\\1)")
fun soundex(string: String): String {
var s = string
.trim()
.toUpperCase(Locale.ROOT)
.replace('Â', 'A')
.replace('Ä', 'A')
.replace('À', 'A')
.replace('E', 'A')
.replace('È', 'A')
.replace('É', 'A')
.replace('Ê', 'A')
.replace('Ë', 'A')
.replace('Œ', 'A')
.replace('I', 'A')
.replace('Î', 'A')
.replace('Ï', 'A')
.replace('O', 'A')
.replace('Ô', 'A')
.replace('Ö', 'A')
.replace('U', 'A')
.replace('Ù', 'A')
.replace('Û', 'A')
.replace('Ü', 'A')
.replace('Ç', 'S')
.replace("GUI", "KI")
.replace("GUE", "KE")
.replace("GA", "KA")
.replace("GO", "KO")
.replace("GU", "K")
.replace("CA", "KA")
.replace("CO", "KO")
.replace("CU", "KU")
.replace("Q", "K")
.replace("CC", "K")
.replace("CK", "K")
.replace("MAC", "MCC")
.replace("ASA", "AZA")
.replace("KN", "NN")
.replace("PF", "FF")
.replace("SCH", "SSS")
.replace("PH", "FF")
.replace("H", "")
s = yNotPrecededByA.matcher(s).replaceAll("")
s = hNotPrecededByCS.matcher(s).replaceAll("")
s = silentEndLetter.matcher(s).replaceAll("")
s = silentEndLetter.matcher(s).replaceAll("")
s = notALetter.matcher(s).replaceAll("")
s = aInWord.matcher(s).replaceAll("")
s = doubleLetter.matcher(s).replaceAll("$1")
return s
}

View File

@ -1,34 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFFFF" android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
</vector>

View File

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

View File

@ -1,15 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="930.9091"
android:viewportHeight="930.9091"
android:viewportWidth="1034.3434"
android:viewportHeight="1034.3434"
android:autoMirrored="true">
<group android:translateX="209.45454"
android:translateY="205.14478">
<path android:fillColor="#A1D8F6" android:pathData="M8.348,89.733h495.304v331.386h-495.304z"/>
<path android:fillColor="#0088FF" android:pathData="M43.542,117.136h424.504v276.58h-424.504z"/>
<path android:fillColor="#016DF5" android:pathData="M255.8,117.136h212.257v276.58h-212.257z"/>
<path android:fillColor="#FFFFFF" android:pathData="M235.976,69.398h41.06v373.203h-41.06z"/>
<path android:fillColor="#3C3A41" android:pathData="M503.652,81.386H285.38V69.399c0,-4.611 -3.736,-8.348 -8.348,-8.348h-41.06c-4.61,0 -8.348,3.736 -8.348,8.348v11.989H99.981c-4.61,0 -8.348,3.736 -8.348,8.348s3.738,8.348 8.348,8.348h127.644v10.704h-77.956H43.542c-4.61,0 -8.348,3.736 -8.348,8.348v138.864v137.719c0,4.611 3.738,8.348 8.348,8.348h106.126h77.956v10.704H16.696V98.082h26.852c4.61,0 8.348,-3.736 8.348,-8.348s-3.738,-8.348 -8.348,-8.348h-35.2C3.738,81.386 0,85.123 0,89.734v331.385c0,4.611 3.738,8.348 8.348,8.348h219.276v13.134c0,4.611 3.738,8.348 8.348,8.348h41.06c4.611,0 8.348,-3.736 8.348,-8.348v-13.134h130.937c4.611,0 8.348,-3.736 8.348,-8.348c0,-4.611 -3.736,-8.348 -8.348,-8.348H285.38v-10.704h76.542h106.126c4.611,0 8.348,-3.736 8.348,-8.348v-137.72V117.134c0,-4.611 -3.736,-8.348 -8.348,-8.348H361.922H285.38V98.082h209.924v314.69h-27.248c-4.611,0 -8.348,3.736 -8.348,8.348c0,4.611 3.736,8.348 8.348,8.348h35.596c4.611,0 8.348,-3.736 8.348,-8.348V89.734C512,85.124 508.263,81.386 503.652,81.386zM51.89,125.482h89.431v122.17H51.89V125.482zM51.89,385.371V264.347h89.431v121.023H51.89zM158.015,385.371V255.999V125.482h69.609v259.889H158.015zM268.684,434.252H244.32v-13.134v-27.4V117.134v-27.4V77.747h24.365v11.989v27.4V393.72v27.4V434.252zM370.269,385.371V264.347H459.7v121.023H370.269zM459.7,125.482v122.17h-89.431v-122.17H459.7zM353.574,125.482v130.518v129.371H285.38V125.482H353.574z"/>
<group android:translateX="51.71717"
android:translateY="51.71717">
<group android:translateX="209.45454"
android:translateY="205.14478">
<path android:fillColor="#A1D8F6" android:pathData="M8.348,89.733h495.304v331.386h-495.304z"/>
<path android:fillColor="#0088FF" android:pathData="M43.542,117.136h424.504v276.58h-424.504z"/>
<path android:fillColor="#016DF5" android:pathData="M255.8,117.136h212.257v276.58h-212.257z"/>
<path android:fillColor="#FFFFFF" android:pathData="M235.976,69.398h41.06v373.203h-41.06z"/>
<path android:fillColor="#3C3A41" android:pathData="M503.652,81.386H285.38V69.399c0,-4.611 -3.736,-8.348 -8.348,-8.348h-41.06c-4.61,0 -8.348,3.736 -8.348,8.348v11.989H99.981c-4.61,0 -8.348,3.736 -8.348,8.348s3.738,8.348 8.348,8.348h127.644v10.704h-77.956H43.542c-4.61,0 -8.348,3.736 -8.348,8.348v138.864v137.719c0,4.611 3.738,8.348 8.348,8.348h106.126h77.956v10.704H16.696V98.082h26.852c4.61,0 8.348,-3.736 8.348,-8.348s-3.738,-8.348 -8.348,-8.348h-35.2C3.738,81.386 0,85.123 0,89.734v331.385c0,4.611 3.738,8.348 8.348,8.348h219.276v13.134c0,4.611 3.738,8.348 8.348,8.348h41.06c4.611,0 8.348,-3.736 8.348,-8.348v-13.134h130.937c4.611,0 8.348,-3.736 8.348,-8.348c0,-4.611 -3.736,-8.348 -8.348,-8.348H285.38v-10.704h76.542h106.126c4.611,0 8.348,-3.736 8.348,-8.348v-137.72V117.134c0,-4.611 -3.736,-8.348 -8.348,-8.348H361.922H285.38V98.082h209.924v314.69h-27.248c-4.611,0 -8.348,3.736 -8.348,8.348c0,4.611 3.736,8.348 8.348,8.348h35.596c4.611,0 8.348,-3.736 8.348,-8.348V89.734C512,85.124 508.263,81.386 503.652,81.386zM51.89,125.482h89.431v122.17H51.89V125.482zM51.89,385.371V264.347h89.431v121.023H51.89zM158.015,385.371V255.999V125.482h69.609v259.889H158.015zM268.684,434.252H244.32v-13.134v-27.4V117.134v-27.4V77.747h24.365v11.989v27.4V393.72v27.4V434.252zM370.269,385.371V264.347H459.7v121.023H370.269zM459.7,125.482v122.17h-89.431v-122.17H459.7zM353.574,125.482v130.518v129.371H285.38V125.482H353.574z"/>
</group>
</group>
</vector>

View File

@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="430.556" android:viewportWidth="430.556"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
android:viewportHeight="430.556" android:viewportWidth="430.556"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M139.689,93.625c0.552,-4.94 5.006,-8.496 9.944,-7.945c4.94,0.552 8.497,5.004 7.945,9.943c-0.398,3.566 3.715,14.81 21.66,34.326c16.172,17.59 39.202,37.165 64.845,55.121c17.287,12.104 35.165,23.035 51.702,31.609c4.413,2.288 6.135,7.721 3.847,12.133c-1.602,3.089 -4.743,4.859 -7.997,4.859c-1.396,0 -2.811,-0.325 -4.135,-1.012c-17.231,-8.935 -35.814,-20.293 -53.741,-32.846C184.855,165.572 136.803,119.458 139.689,93.625zM52.83,91.751c-4.802,-1.301 -9.739,1.543 -11.036,6.341c-5.789,21.428 -4.187,44.349 4.51,64.541c2.622,6.087 5.887,11.938 9.705,17.391l25.55,36.492c11.818,16.878 28.379,29.397 47.893,36.205c0.981,0.342 1.981,0.505 2.964,0.505c3.721,0 7.203,-2.326 8.498,-6.038c1.637,-4.693 -0.84,-9.825 -5.533,-11.463c-15.926,-5.556 -29.438,-15.768 -39.076,-29.533l-25.551,-36.493c-3.116,-4.45 -5.78,-9.223 -7.917,-14.186c-7.098,-16.478 -8.399,-35.203 -3.666,-52.727C60.468,97.988 57.629,93.047 52.83,91.751zM306.703,198.433c3.112,0 6.139,-1.616 7.805,-4.507c2.483,-4.306 1.005,-9.81 -3.301,-12.292c-11.505,-6.634 -23.224,-14.118 -34.83,-22.244c-21.658,-15.165 -41.119,-31.282 -56.278,-46.611c-3.495,-3.532 -9.192,-3.565 -12.728,-0.07c-3.534,3.495 -3.566,9.193 -0.07,12.728c15.907,16.085 36.223,32.925 58.752,48.698c12.036,8.428 24.203,16.197 36.163,23.094C303.632,198.044 305.177,198.433 306.703,198.433zM179.468,105.23c4.071,2.851 9.683,1.86 12.535,-2.21l27.736,-39.611c16.175,-23.102 40.497,-38.542 68.484,-43.477c27.986,-4.938 56.124,1.255 79.227,17.431c42.257,29.588 57.098,86.902 34.521,133.317c-2.174,4.47 -0.313,9.855 4.157,12.03c1.268,0.616 2.609,0.908 3.93,0.908c3.336,0 6.542,-1.863 8.1,-5.065c12.747,-26.206 15.785,-56.35 8.555,-84.876c-7.311,-28.845 -24.69,-54.08 -48.939,-71.059C350.733,3.685 317.821,-3.568 285.097,2.205c-32.722,5.77 -61.17,23.839 -80.103,50.879l-27.736,39.611C174.406,96.767 175.396,102.379 179.468,105.23zM349.668,380.735c2.235,3.19 3.094,7.069 2.416,10.92c-0.679,3.851 -2.812,7.203 -6.006,9.439l-37.92,26.552c-2.546,1.781 -5.469,2.636 -8.363,2.637c-4.613,0 -9.154,-2.171 -11.994,-6.224l-23.765,-33.94c-0.015,-0.021 -0.03,-0.042 -0.045,-0.063c-0.015,-0.021 -0.029,-0.042 -0.044,-0.063l-26.687,-38.114c-0.039,-0.053 -0.077,-0.105 -0.114,-0.159c-0.037,-0.054 -0.074,-0.107 -0.11,-0.161l-10.572,-15.099c-2.851,-4.071 -1.861,-9.684 2.21,-12.534c4.072,-2.853 9.684,-1.862 12.535,2.21l5.521,7.886l39.754,-27.834c4.072,-2.852 9.684,-1.862 12.535,2.21l26.714,38.153c0.044,0.061 0.088,0.121 0.131,0.183s0.085,0.123 0.126,0.186L349.668,380.735zM273.574,372.358l32.381,-22.673l-16.519,-23.593l-32.381,22.673L273.574,372.358zM332.984,388.288l-16.705,-23.858l-32.381,22.673l16.706,23.859L332.984,388.288zM424.708,240.113c0,29.289 -23.828,53.117 -53.117,53.117c-15.028,0 -29.419,-6.41 -39.483,-17.587c-8.792,-9.765 -13.634,-22.383 -13.634,-35.53c0,-29.289 23.828,-53.117 53.117,-53.117S424.708,210.823 424.708,240.113zM406.708,240.113c0,-19.363 -15.753,-35.117 -35.117,-35.117s-35.117,15.754 -35.117,35.117c0,8.691 3.2,17.032 9.011,23.485c6.655,7.393 16.171,11.632 26.106,11.632C390.955,275.23 406.708,259.476 406.708,240.113zM118.872,288.815c3.721,0 7.203,-2.326 8.498,-6.038c1.637,-4.693 -0.841,-9.825 -5.534,-11.462c-21.089,-7.355 -38.982,-20.88 -51.746,-39.112L37.09,185.075c-16.176,-23.103 -22.366,-51.238 -17.431,-79.226c4.935,-27.988 20.377,-52.31 43.48,-68.486c36.03,-25.229 84.706,-25.36 121.124,-0.324c4.097,2.815 9.7,1.778 12.515,-2.318c2.816,-4.097 1.778,-9.699 -2.318,-12.516C151.887,-7.061 94.963,-6.895 52.815,22.619C25.774,41.552 7.703,70.001 1.933,102.724s1.479,65.635 20.413,92.676l32.998,47.126c14.943,21.346 35.886,37.178 60.564,45.785C116.889,288.653 117.888,288.815 118.872,288.815zM236.791,289.807l-16.505,23.571c-0.001,0.001 -0.001,0.002 -0.002,0.003c-0.001,0.002 -0.002,0.004 -0.003,0.005l-77.493,110.67c-2.839,4.056 -7.382,6.229 -11.995,6.229c-2.894,0 -5.815,-0.855 -8.361,-2.636l-37.924,-26.557c-3.194,-2.235 -5.327,-5.587 -6.006,-9.437c-0.679,-3.85 0.18,-7.729 2.417,-10.923l23.721,-33.877c0.028,-0.041 0.057,-0.083 0.085,-0.124c0.029,-0.042 0.059,-0.083 0.088,-0.123l26.655,-38.067c0.033,-0.049 0.066,-0.097 0.1,-0.146c0.034,-0.049 0.068,-0.097 0.103,-0.145l26.631,-38.032c0.036,-0.054 0.073,-0.107 0.111,-0.161c0.037,-0.054 0.076,-0.107 0.114,-0.16l16.389,-23.406c-17.779,-23.404 -26.645,-52.261 -25.064,-82.017c0.263,-4.964 4.5,-8.781 9.465,-8.51c4.963,0.264 8.773,4.501 8.51,9.465c-1.461,27.494 7.484,54.077 25.188,74.851c2.659,3.12 2.874,7.643 0.522,11l-15.216,21.73l32.381,22.674l15.216,-21.73c2.351,-3.357 6.672,-4.702 10.515,-3.271c20.884,7.781 44.326,8.711 66.005,2.615c4.785,-1.345 9.755,1.443 11.1,6.229s-1.443,9.754 -6.228,11.1C284.255,297.106 259.48,296.782 236.791,289.807zM146.689,387.102l-32.38,-22.673l-16.707,23.859l32.38,22.673L146.689,387.102zM173.533,348.767l-32.381,-22.674l-16.519,23.591l32.381,22.674L173.533,348.767zM200.377,310.429l-32.38,-22.673l-16.52,23.593l32.38,22.673L200.377,310.429z"/>
</vector>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#FFFFFF" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M18.4,10.6C16.55,8.99 14.15,8 11.5,8c-4.65,0 -8.58,3.03 -9.96,7.22L3.9,16c1.05,-3.19 4.05,-5.5 7.6,-5.5 1.95,0 3.73,0.72 5.12,1.88L13,16h9V7l-3.6,3.6z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,15c1.66,0 2.99,-1.34 2.99,-3L15,6c0,-1.66 -1.34,-3 -3,-3S9,4.34 9,6v6c0,1.66 1.34,3 3,3zM17.3,12c0,3 -2.54,5.1 -5.3,5.1S6.7,15 6.7,12L5,12c0,3.42 2.72,6.23 6,6.72L11,22h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6.99,11L3,15l3.99,4v-3H14v-2H6.99v-3zM21,9l-3.99,-4v3H10v2h7.01v3L21,9z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M16,17.01V10h-2v7.01h-3L15,21l4,-3.99h-3zM9,3L5,6.99h3V14h2V6.99h3L9,3z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#FFFFFF" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12.5,8c-2.65,0 -5.05,0.99 -6.9,2.6L2,7v9h9l-3.62,-3.62c1.39,-1.16 3.16,-1.88 5.12,-1.88 3.54,0 6.55,2.31 7.6,5.5l2.37,-0.78C21.08,11.03 17.15,8 12.5,8z"/>
</vector>

View File

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinatorLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textScore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="32dp"
android:layout_weight="1"
android:text="@string/score_score"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_weight="1"
android:text="@string/service"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/icStt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginTop="24dp"
android:alpha="0"
android:contentDescription="@string/STT"
app:layout_constraintEnd_toEndOf="@+id/textService"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_stt" />
<ImageView
android:id="@+id/imgService0"
android:layout_width="48dp"
android:layout_height="0dp"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"
android:contentDescription="@string/service_img_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textScore"
app:srcCompat="@drawable/ic_service_1" />
<Button
android:id="@+id/buttonPlayer0"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="32dp"
android:layout_weight="1"
android:bufferType="spannable"
android:onClick="updateScore"
android:textAllCaps="false"
android:textSize="24sp"
android:textStyle="bold"
android:theme="@style/ColoredButtonStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/buttonPlayer1"
app:layout_constraintStart_toEndOf="@+id/imgService0"
app:layout_constraintTop_toBottomOf="@+id/textScore"
tools:text="@string/button_text" />
<Button
android:id="@+id/buttonPlayer1"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:layout_marginBottom="32dp"
android:layout_weight="1"
android:bufferType="spannable"
android:onClick="updateScore"
android:textAllCaps="false"
android:textSize="24sp"
android:textStyle="bold"
android:theme="@style/ColoredButtonStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/imgService1"
app:layout_constraintStart_toEndOf="@+id/buttonPlayer0"
app:layout_constraintTop_toBottomOf="@+id/textService"
tools:text="@string/button_text" />
<ImageView
android:id="@+id/imgService1"
android:layout_width="48dp"
android:layout_height="0dp"
android:layout_margin="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="32dp"
android:contentDescription="@string/service_img_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textService" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".StarterNameActivity">
<Button
android:id="@+id/startButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:drawableStart="@drawable/ic_new_match"
android:drawableLeft="@drawable/ic_new_match"
android:onClick="startMatch"
android:text="@string/start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/enableSttSwitch" />
<TextView
android:id="@+id/WhoStarts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="32dp"
android:text="@string/who_starts"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RadioGroup
android:id="@+id/starterRadioGroup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/WhoStarts">
<RadioButton
android:id="@+id/radioPlayer1Starts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:checked="true"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="93dp" />
<AutoCompleteTextView
android:id="@+id/player1Name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:completionThreshold="1"
android:hint="@string/player_1_default_name"
android:imeOptions="actionNext"
android:singleLine="true"
android:text="@string/player_1_default_name"
tools:layout_editor_absoluteX="143dp"
tools:layout_editor_absoluteY="48dp" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:contentDescription="@string/swap_names"
android:onClick="swapNames"
app:srcCompat="@drawable/ic_swap_horiz" />
<RadioButton
android:id="@+id/radioPlayer2Starts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:checked="true"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="93dp" />
<AutoCompleteTextView
android:id="@+id/player2Name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:completionThreshold="1"
android:hint="@string/player_2_default_name"
android:imeOptions="actionNext"
android:singleLine="true"
android:text="@string/player_2_default_name"
tools:layout_editor_absoluteX="136dp" />
</RadioGroup>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/enableTtsSwitch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/TTS"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/starterRadioGroup" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/enableSttSwitch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/STT"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/enableTtsSwitch" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CreditsActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginBottom="8dp"
android:background="@color/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/PingPointsCredit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/PingPointsCredits"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
tools:layout_editor_absoluteX="136dp"
tools:layout_editor_absoluteY="111dp" />
<TextView
android:id="@+id/iconsCredit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/iconCredits"
app:layout_constraintTop_toBottomOf="@+id/PingPointsCredit"
tools:layout_editor_absoluteX="106dp" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>

View File

@ -1,143 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:layout_editor_absoluteY="73dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginBottom="8dp"
android:background="@color/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<LinearLayout
android:id="@+id/linearLayoutText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="8dp">
<TextView
android:id="@+id/textService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:gravity="left"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toTopOf="@+id/linearLayoutButtons"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@+id/textScore"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/service" />
<TextView
android:id="@+id/textScore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:gravity="right|center"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/score" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/imgLeftService"
android:layout_width="48dp"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="0"
android:contentDescription="@string/service_img_description"
app:srcCompat="@drawable/ic_left_service"
tools:layout_editor_absoluteY="120dp" />
<Button
android:id="@+id/buttonLeftPlayer"
style="@style/Base.Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_weight="1"
android:background="@color/colorAccent"
android:bufferType="spannable"
android:onClick="updateScore"
android:textAllCaps="false"
android:textAppearance="@style/TextAppearance.AppCompat.Button"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/imgLeftService"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/button_text" />
<Button
android:id="@+id/buttonRightPlayer"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_weight="1"
android:background="@color/colorAccent"
android:bufferType="spannable"
android:onClick="updateScore"
android:textAllCaps="false"
android:textAppearance="@style/TextAppearance.AppCompat.Button"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/imgRightService"
app:layout_constraintStart_toEndOf="@+id/buttonLeftPlayer"
tools:text="@string/button_text" />
<ImageView
android:id="@+id/imgRightService"
android:layout_width="48dp"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="0"
android:contentDescription="@string/service_img_description"
tools:layout_editor_absoluteY="120dp" />
</LinearLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinatorLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textService"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="32dp"
android:layout_weight="1"
android:gravity="start"
android:text="@string/service"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/icStt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:alpha="0"
android:contentDescription="@string/STT"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_stt" />
<TextView
android:id="@+id/textScore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:gravity="start"
android:text="@string/score_score"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toTopOf="@+id/imgService0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textService" />
<ImageView
android:id="@+id/imgService0"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/service_img_description"
app:layout_constraintBottom_toTopOf="@+id/buttonPlayer0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textScore"
app:srcCompat="@drawable/ic_service_1" />
<Button
android:id="@+id/buttonPlayer0"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:bufferType="spannable"
android:onClick="updateScore"
android:textAllCaps="false"
android:textSize="24sp"
android:textStyle="bold"
android:theme="@style/ColoredButtonStyle"
app:layout_constraintBottom_toTopOf="@+id/buttonPlayer1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgService0"
tools:text="@string/button_text" />
<Button
android:id="@+id/buttonPlayer1"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:bufferType="spannable"
android:onClick="updateScore"
android:textAllCaps="false"
android:textSize="24sp"
android:textStyle="bold"
android:theme="@style/ColoredButtonStyle"
app:layout_constraintBottom_toTopOf="@+id/imgService1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/buttonPlayer0"
tools:text="@string/button_text" />
<ImageView
android:id="@+id/imgService1"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="8dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="32dp"
android:contentDescription="@string/service_img_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/buttonPlayer1" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinatorLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".StarterNameActivity">
<TextView
android:id="@+id/WhoStarts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="32dp"
android:text="@string/who_starts"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RadioGroup
android:id="@+id/starterRadioGroup"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="@+id/player2Name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/player1Name">
<RadioButton
android:id="@+id/radioPlayer1Starts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:gravity="top"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="93dp" />
<RadioButton
android:id="@+id/radioPlayer2Starts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:gravity="bottom"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="93dp" />
</RadioGroup>
<AutoCompleteTextView
android:id="@+id/player1Name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:completionThreshold="1"
android:hint="@string/player_1_default_name"
android:imeOptions="actionNext"
android:selectAllOnFocus="true"
android:singleLine="true"
android:text="@string/player_1_default_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/starterRadioGroup"
app:layout_constraintTop_toBottomOf="@+id/WhoStarts" />
<ImageButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:contentDescription="@string/swap_names"
android:onClick="swapNames"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/player1Name"
app:srcCompat="@drawable/ic_swap_vert" />
<AutoCompleteTextView
android:id="@+id/player2Name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:completionThreshold="1"
android:hint="@string/player_2_default_name"
android:imeOptions="actionNext"
android:selectAllOnFocus="true"
android:singleLine="true"
android:text="@string/player_2_default_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/starterRadioGroup"
app:layout_constraintTop_toBottomOf="@+id/imageButton" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/enableTtsSwitch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/TTS"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/player2Name" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/enableSttSwitch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/STT"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/enableTtsSwitch" />
<Button
android:id="@+id/startButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:drawableStart="@drawable/ic_new_match"
android:drawableLeft="@drawable/ic_new_match"
android:onClick="startMatch"
android:text="@string/start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/enableSttSwitch" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".VictoryActivity">
<TextView
android:id="@+id/congrats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/congrats"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/player1NameTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:text="@string/player_1_default_name"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintBottom_toTopOf="@+id/previousMatchesTextView"
app:layout_constraintEnd_toStartOf="@+id/scoreTextView"
app:layout_constraintTop_toBottomOf="@+id/congrats" />
<TextView
android:id="@+id/scoreTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:layout_weight="0"
android:text="@string/score"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintBottom_toTopOf="@+id/previousMatchesTextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/congrats" />
<TextView
android:id="@+id/player2NameTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:text="@string/player_2_default_name"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintBottom_toTopOf="@+id/previousMatchesTextView"
app:layout_constraintStart_toEndOf="@+id/scoreTextView"
app:layout_constraintTop_toBottomOf="@+id/congrats" />
<TextView
android:id="@+id/previousMatchesTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/previous_matches"
android:textAllCaps="true"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/player1NameTextView" />
<GridView
android:id="@+id/previousMatchesGrid"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="8dp"
android:clickable="false"
android:gravity="center"
android:numColumns="3"
app:layout_constraintBottom_toTopOf="@+id/pingPointsCredit"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/previousMatchesTextView">
</GridView>
<TextView
android:id="@+id/pingPointsCredit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_weight="0"
android:text="@string/PingPointsCredits"
app:layout_constraintBottom_toTopOf="@+id/iconsCredit"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/previousMatchesGrid" />
<TextView
android:id="@+id/iconsCredit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="24dp"
android:layout_weight="0"
android:maxLines="1"
android:text="@string/iconCredits"
app:layout_constraintBottom_toTopOf="@+id/buttonShare"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/buttonNewMatch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="32dp"
android:drawableStart="@drawable/ic_new_match"
android:drawableLeft="@drawable/ic_new_match"
android:onClick="newMatch"
android:text="@string/new_match"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<Button
android:id="@+id/buttonShare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginBottom="32dp"
android:drawableStart="@drawable/ic_share"
android:drawableLeft="@drawable/ic_share"
android:onClick="share"
android:text="@string/share"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/grid_item_text"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true"
tools:context=".NomsJoueursEtPremierServeurDialog">
<!-- TODO: Update blank fragment layout -->
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioLeftPlayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:checked="true"
android:inputType="text" />
<android.support.design.widget.TextInputEditText
android:id="@+id/inputLeftPlayerName"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/name"
android:selectAllOnFocus="true"
android:singleLine="true" />
<RadioButton
android:id="@+id/radioRightPlayer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:inputType="none" />
<android.support.design.widget.TextInputEditText
android:id="@+id/inputRightPlayerName"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/name"
android:selectAllOnFocus="true"
android:singleLine="true" />
</RadioGroup>
</FrameLayout>

View File

@ -1,16 +0,0 @@
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_new_match"
android:icon="@drawable/ic_new_match"
android:title="@string/new_match"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_about"
android:icon="@drawable/ic_about"
android:title="@string/about"
app:showAsAction="ifRoom" />
</menu>

View File

@ -1,30 +0,0 @@
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_undo"
android:icon="@drawable/ic_undo"
android:title="@string/undo"
app:showAsAction="ifRoom"
android:visible="false" />
<item
android:id="@+id/action_redo"
android:icon="@drawable/ic_redo"
android:title="@string/redo"
app:showAsAction="ifRoom"
android:visible="false" />
<item
android:id="@+id/action_new_match"
android:icon="@drawable/ic_new_match"
android:title="@string/new_match"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_about"
android:icon="@drawable/ic_about"
android:title="@string/about"
app:showAsAction="ifRoom" />
</menu>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -1,26 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Ping Points</string>
<string name="info">Cliquez sur le joueur qui a marqué</string>
<string name="service">Service : %s</string>
<string name="score">Score : %d - %d</string>
<string-array name="default_players_names">
<item>Joueur 1</item>
<item>Joueur 2</item>
</string-array>
<string name="end_match_dialog_title">Bravo %s !</string>
<string name="new_match">Nouveau match</string>
<string name="quit_button">Quitter</string>
<string name="name">Nom</string>
<string name="go_button">Allons-y !</string>
<string name="starter_name_dialog_message">Qui commence ?</string>
<string name="share_button">Partager</string>
<string name="share_subject">Match Ping Points : %s contre %s</string>
<string name="share_message">%s contre %s:\n%s a gagné par %d à %d\nPing Points est disponible sur Google Play</string>
<string name="who_starts">Qui commence ?</string>
<string name="player_1_default_name">Joueur 1</string>
<string name="player_2_default_name">Joueur 2</string>
<string name="TTS">Synthèse vocale</string>
<string name="STT">Reconnaissance vocale</string>
<string name="start">Allons-y !</string>
<string name="swap_names">Échanger les noms</string>
<string name="PingPointsCredits">Ping Points par Adrien Malin</string>
<string name="iconCredits"><div>Icônes par <a href="http://www.freepik.com" title="Freepik">Freepik</a> chez <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> Licence <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div></string>
<string name="about">À propos</string>
<string name="iconCredits">Icônes par &lt;a href=&quot;http://www.freepik.com&quot; title=&quot;Freepik&quot;&gt;Freepik&lt;/a&gt; chez &lt;a href=&quot;https://www.flaticon.com/&quot; title=&quot;Flaticon&quot;&gt;flaticon.com&lt;/a&gt; Licence &lt;a href=&quot;http://creativecommons.org/licenses/by/3.0/&quot; title=&quot;Creative Commons BY 3.0&quot; target=&quot;_blank&quot;&gt;CC 3.0 BY&lt;/a&gt;</string>
<string name="TTS_unavailable">Désolé, votre appareil ne permet pas la synthèse vocale.</string>
<string name="STT_unavailable">Désolé, votre appareil ne permet pas la reconnaissance vocale.</string>
<string name="audio_record_permission_denied">La reconnaissance vocale a besoin de la permission d\'enregistrer des
fichiers audio pour fonctionner.
</string>
<string name="service">Service : %s</string>
<string name="score_score">Score : %d - %d</string>
<string name="service_img_description">Service</string>
<string name="undo">Annuler</string>
<string name="redo">Rétablir</string>
<string name="update_score_speech">"%d - %d. Service : %s. "</string>
<string name="button_hint">Cliquez sur le joueur qui a marqué</string>
<string name="congrats">Bravo %s !</string>
<string name="previous_matches">Matchs précédents</string>
<string name="new_match">Nouveau match</string>
<string name="share">Partager</string>
<string name="victory_speech">%s gagne par %d à %d.</string>
<string name="share_subject">Match Ping Points : %s contre %s</string>
<string name="share_message">"%s contre %s:\n%s a gagné par %d à %d\nPing Points est disponible sur Google Play"</string>
<string name="match_point">Balle de match</string>
<string name="STT_hint">Dîtes : \"Point pour %s\"\nou \"Point pour %s\"</string>
<string name="not_understood">Pouvez-vous répéter ?</string>
<string name="soundex">point pour %s</string>
</resources>

View File

@ -2,5 +2,6 @@
<resources>
<color name="colorPrimary">#016df5</color>
<color name="colorPrimaryDark">#004aa7</color>
<color name="colorAccent">#0088FF</color>
<color name="colorAccent">#0088ff</color>
<color name="white">#ffffff</color>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#3C3A41</color>
<color name="ic_launcher_background">#26A69A</color>
</resources>

View File

@ -1,27 +1,40 @@
<resources>
<string name="app_name">Ping Points</string>
<string name="go_button">Play</string>
<string name="starter_name_dialog_message">Who starts?</string>
<string name="info">Click on the scoring player</string>
<string name="service">Service: %s</string>
<string name="score">Score: %d - %d</string>
<string name="button_text" translatable="false">%s &lt;br /&gt; &lt;br /&gt; &lt;big&gt; &lt;big&gt; %d &lt;/big&gt; &lt;/big&gt;</string>
<string name="end_match_dialog_title">Congratulations, %s!</string>
<string-array name="default_players_names">
<item>Player 1</item>
<item>Player 2</item>
</string-array>
<string name="new_match">New match</string>
<string name="quit_button">Quit</string>
<string name="name">Name</string>
<string name="share_button">Share</string>
<string name="share_subject">Ping Points Match: %s vs. %s</string>
<string name="share_message">%s vs. %s:\n%s won by %d to %d\n\nGet Ping Points on Google Play</string>
<string name="radioText" translatable="false"></string>
<string name="who_starts">Who starts?</string>
<string name="player_1_default_name">Player 1</string>
<string name="player_2_default_name">Player 2</string>
<string name="TTS">Text to speech</string>
<string name="STT">Voice recognizer</string>
<string name="start">Play</string>
<string name="swap_names">Swap names</string>
<string name="PingPointsCredits">Ping Points by Adrien Malin</string>
<string name="iconCredits">Icons made by &lt;a href=&quot;http://www.freepik.com&quot; title=&quot;Freepik&quot;&gt;Freepik&lt;/a&gt; from &lt;a href=&quot;https://www.flaticon.com/&quot; title=&quot;Flaticon&quot;&gt;www.flaticon.com&lt;/a&gt; is licensed by &lt;a href=&quot;http://creativecommons.org/licenses/by/3.0/&quot; title=&quot;Creative Commons BY 3.0&quot; target=&quot;_blank&quot;&gt;CC 3.0 BY&lt;/a&gt;</string>
<string name="about">About</string>
<string name="iconCredits">Icons made by &lt;a href=&quot;http://www.freepik.com&quot; title=&quot;Freepik&quot;&gt;Freepik&lt;/a&gt;
from &lt;a href=&quot;https://www.flaticon.com/&quot; title=&quot;Flaticon&quot;&gt;flaticon.com&lt;/a&gt; is
licensed by &lt;a href=&quot;http://creativecommons.org/licenses/by/3.0/&quot; title=&quot;Creative Commons BY
3.0&quot; target=&quot;_blank&quot;&gt;CC 3.0 BY&lt;/a&gt;
</string>
<string name="TTS_unavailable">Sorry, your device doesn\'t support text to speech.</string>
<string name="STT_unavailable">Sorry, your device doesn\'t support voice recognition.</string>
<string name="audio_record_permission_denied">Audio recording permission required to use voice recognition.</string>
<string name="service">Service: %s</string>
<string name="score_score">Score: %d - %d</string>
<string name="service_img_description">Service</string>
<string name="undo">Undo</string>
<string name="redo">Redo</string>
<string name="button_text" translatable="false">%s &lt;br /&gt; &lt;br /&gt; &lt;big&gt; &lt;big&gt; %d &lt;/big&gt;
&lt;/big&gt;
</string>
<string name="update_score_speech">"%d - %d. Service: %s. "</string>
<string name="button_hint">Click on the scoring player</string>
<string name="congrats">Congratulations, %s!</string>
<string name="previous_matches">Previous matches</string>
<string name="new_match">New match</string>
<string name="share">Share</string>
<string name="results" translatable="false">%s\t%s\t%s\n%s</string>
<string name="victory_speech">%s wins by %d to %d.</string>
<string name="share_subject">Ping Points Match: %s vs. %s</string>
<string name="share_message">%s vs. %s:\n%s won by %d to %d\nGet Ping Points on Google Play</string>
<string name="match_point">Match point</string>
<string name="STT_hint">Say: \"Point for %s\"\nor \"Point for %s\"</string>
<string name="soundex">point for %s</string>
<string name="not_understood">Can you repeat, please?</string>
<string name="score" translatable="false">%d - %d</string>
</resources>

View File

@ -0,0 +1,23 @@
<resources>
<!-- the theme applied to the application or activity -->
<style name="PingPointsTheme" parent="@style/Platform.MaterialComponents">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="colorControlNormal">#FFFFFF</item>
<item name="android:actionBarStyle">@style/ColoredActionBarBackground</item>
<!-- Support library compatibility -->
<item name="actionBarStyle">@style/ColoredActionBarBackground</item>
</style>
<style name="ColoredActionBarBackground" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">@color/colorPrimary</item>
<!-- Support library compatibility -->
<item name="background">@color/colorPrimary</item>
</style>
<style name="ColoredButtonStyle" parent="Widget.AppCompat.Button.Colored">
<item name="colorButtonNormal">@color/colorAccent</item>
<item name="android:textColor">@color/white</item>
</style>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<!-- Exclude specific shared preferences that contain GCM registration Id -->
</full-backup-content>

View File

@ -0,0 +1,6 @@
<!--suppress XmlHighlighting -->
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="430.556" android:viewportWidth="430.556"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M139.689,93.625c0.552,-4.94 5.006,-8.496 9.944,-7.945c4.94,0.552 8.497,5.004 7.945,9.943c-0.398,3.566 3.715,14.81 21.66,34.326c16.172,17.59 39.202,37.165 64.845,55.121c17.287,12.104 35.165,23.035 51.702,31.609c4.413,2.288 6.135,7.721 3.847,12.133c-1.602,3.089 -4.743,4.859 -7.997,4.859c-1.396,0 -2.811,-0.325 -4.135,-1.012c-17.231,-8.935 -35.814,-20.293 -53.741,-32.846C184.855,165.572 136.803,119.458 139.689,93.625zM52.83,91.751c-4.802,-1.301 -9.739,1.543 -11.036,6.341c-5.789,21.428 -4.187,44.349 4.51,64.541c2.622,6.087 5.887,11.938 9.705,17.391l25.55,36.492c11.818,16.878 28.379,29.397 47.893,36.205c0.981,0.342 1.981,0.505 2.964,0.505c3.721,0 7.203,-2.326 8.498,-6.038c1.637,-4.693 -0.84,-9.825 -5.533,-11.463c-15.926,-5.556 -29.438,-15.768 -39.076,-29.533l-25.551,-36.493c-3.116,-4.45 -5.78,-9.223 -7.917,-14.186c-7.098,-16.478 -8.399,-35.203 -3.666,-52.727C60.468,97.988 57.629,93.047 52.83,91.751zM306.703,198.433c3.112,0 6.139,-1.616 7.805,-4.507c2.483,-4.306 1.005,-9.81 -3.301,-12.292c-11.505,-6.634 -23.224,-14.118 -34.83,-22.244c-21.658,-15.165 -41.119,-31.282 -56.278,-46.611c-3.495,-3.532 -9.192,-3.565 -12.728,-0.07c-3.534,3.495 -3.566,9.193 -0.07,12.728c15.907,16.085 36.223,32.925 58.752,48.698c12.036,8.428 24.203,16.197 36.163,23.094C303.632,198.044 305.177,198.433 306.703,198.433zM179.468,105.23c4.071,2.851 9.683,1.86 12.535,-2.21l27.736,-39.611c16.175,-23.102 40.497,-38.542 68.484,-43.477c27.986,-4.938 56.124,1.255 79.227,17.431c42.257,29.588 57.098,86.902 34.521,133.317c-2.174,4.47 -0.313,9.855 4.157,12.03c1.268,0.616 2.609,0.908 3.93,0.908c3.336,0 6.542,-1.863 8.1,-5.065c12.747,-26.206 15.785,-56.35 8.555,-84.876c-7.311,-28.845 -24.69,-54.08 -48.939,-71.059C350.733,3.685 317.821,-3.568 285.097,2.205c-32.722,5.77 -61.17,23.839 -80.103,50.879l-27.736,39.611C174.406,96.767 175.396,102.379 179.468,105.23zM349.668,380.735c2.235,3.19 3.094,7.069 2.416,10.92c-0.679,3.851 -2.812,7.203 -6.006,9.439l-37.92,26.552c-2.546,1.781 -5.469,2.636 -8.363,2.637c-4.613,0 -9.154,-2.171 -11.994,-6.224l-23.765,-33.94c-0.015,-0.021 -0.03,-0.042 -0.045,-0.063c-0.015,-0.021 -0.029,-0.042 -0.044,-0.063l-26.687,-38.114c-0.039,-0.053 -0.077,-0.105 -0.114,-0.159c-0.037,-0.054 -0.074,-0.107 -0.11,-0.161l-10.572,-15.099c-2.851,-4.071 -1.861,-9.684 2.21,-12.534c4.072,-2.853 9.684,-1.862 12.535,2.21l5.521,7.886l39.754,-27.834c4.072,-2.852 9.684,-1.862 12.535,2.21l26.714,38.153c0.044,0.061 0.088,0.121 0.131,0.183s0.085,0.123 0.126,0.186L349.668,380.735zM273.574,372.358l32.381,-22.673l-16.519,-23.593l-32.381,22.673L273.574,372.358zM332.984,388.288l-16.705,-23.858l-32.381,22.673l16.706,23.859L332.984,388.288zM424.708,240.113c0,29.289 -23.828,53.117 -53.117,53.117c-15.028,0 -29.419,-6.41 -39.483,-17.587c-8.792,-9.765 -13.634,-22.383 -13.634,-35.53c0,-29.289 23.828,-53.117 53.117,-53.117S424.708,210.823 424.708,240.113zM406.708,240.113c0,-19.363 -15.753,-35.117 -35.117,-35.117s-35.117,15.754 -35.117,35.117c0,8.691 3.2,17.032 9.011,23.485c6.655,7.393 16.171,11.632 26.106,11.632C390.955,275.23 406.708,259.476 406.708,240.113zM118.872,288.815c3.721,0 7.203,-2.326 8.498,-6.038c1.637,-4.693 -0.841,-9.825 -5.534,-11.462c-21.089,-7.355 -38.982,-20.88 -51.746,-39.112L37.09,185.075c-16.176,-23.103 -22.366,-51.238 -17.431,-79.226c4.935,-27.988 20.377,-52.31 43.48,-68.486c36.03,-25.229 84.706,-25.36 121.124,-0.324c4.097,2.815 9.7,1.778 12.515,-2.318c2.816,-4.097 1.778,-9.699 -2.318,-12.516C151.887,-7.061 94.963,-6.895 52.815,22.619C25.774,41.552 7.703,70.001 1.933,102.724s1.479,65.635 20.413,92.676l32.998,47.126c14.943,21.346 35.886,37.178 60.564,45.785C116.889,288.653 117.888,288.815 118.872,288.815zM236.791,289.807l-16.505,23.571c-0.001,0.001 -0.001,0.002 -0.002,0.003c-0.001,0.002 -0.002,0.004 -0.003,0.005l-77.493,110.67c-2.839,4.056 -7.382,6.229 -11.995,6.229c-2.894,0 -5.815,-0.855 -8.361,-2.636l-37.924,-26.557c-3.194,-2.235 -5.327,-5.587 -6.006,-9.437c-0.679,-3.85 0.18,-7.729 2.417,-10.923l23.721,-33.877c0.028,-0.041 0.057,-0.083 0.085,-0.124c0.029,-0.042 0.059,-0.083 0.088,-0.123l26.655,-38.067c0.033,-0.049 0.066,-0.097 0.1,-0.146c0.034,-0.049 0.068,-0.097 0.103,-0.145l26.631,-38.032c0.036,-0.054 0.073,-0.107 0.111,-0.161c0.037,-0.054 0.076,-0.107 0.114,-0.16l16.389,-23.406c-17.779,-23.404 -26.645,-52.261 -25.064,-82.017c0.263,-4.964 4.5,-8.781 9.465,-8.51c4.963,0.264 8.773,4.501 8.51,9.465c-1.461,27.494 7.484,54.077 25.188,74.851c2.659,3.12 2.874,7.643 0.522,11l-15.216,21.73l32.381,22.674l15.216,-21.73c2.351,-3.357 6.672,-4.702 10.515,-3.271c20.884,7.781 44.326,8.711 66.005,2.615c4.785,-1.345 9.755,1.443 11.1,6.229s-1.443,9.754 -6.228,11.1C284.255,297.106 259.48,296.782 236.791,289.807zM146.689,387.102l-32.38,-22.673l-16.707,23.859l32.38,22.673L146.689,387.102zM173.533,348.767l-32.381,-22.674l-16.519,23.591l32.381,22.674L173.533,348.767zM200.377,310.429l-32.38,-22.673l-16.52,23.593l32.38,22.673L200.377,310.429z"/>
</vector>

View File

@ -1,17 +0,0 @@
package adrienmalin.pingpoints
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@ -1,13 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.2.50'
ext.kotlin_version = '1.4.0'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong

View File

@ -1,9 +1,12 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
@ -11,3 +14,7 @@ org.gradle.jvmargs=-Xmx1536m
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.useAndroidX=true
android.enableJetifier=true

Binary file not shown.

View File

@ -1,6 +1,6 @@
#Sat Aug 11 18:40:19 CEST 2018
#Tue Sep 08 21:52:23 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip