11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_choose_remove_favorite.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | workflow_dispatch:
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - name: Checkout repository
16 | uses: actions/checkout@v2
17 |
18 | - name: Create and push tag
19 | run: |
20 | git config --local user.email "6969594+namlit@users.noreply.github.com"
21 | git config --local user.name "GitHub Action"
22 | ./create_tag.sh
23 | git push origin --tags
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_generation_parameters_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_save_generation_parameters.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_confirm_remove_favorite.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_confirm_remove_generation_parameter.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/NamedSiteswap.java:
--------------------------------------------------------------------------------
1 | package siteswaplib;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | public class NamedSiteswap extends Siteswap {
6 |
7 | public NamedSiteswap(String siteswap, int numJugglers, String name) {
8 | super(siteswap, numJugglers, name);
9 | }
10 |
11 | public NamedSiteswap(Siteswap siteswap) {
12 | super(siteswap);
13 | }
14 |
15 | @NonNull
16 | @Override
17 | public String toString() {
18 |
19 | String name = getSiteswapName() == "" ? "" : getSiteswapName() + ": ";
20 | return name + super.toString();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - develop
8 | pull_request:
9 | workflow_dispatch:
10 |
11 | jobs:
12 | build:
13 |
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - name: Checkout repository
18 | uses: actions/checkout@v2
19 |
20 | - name: Set up JDK
21 | uses: actions/setup-java@v2
22 | with:
23 | distribution: 'adopt'
24 | java-version: '17'
25 |
26 | - name: Build with Gradle
27 | run: ./gradlew build
28 |
29 | - name: Run tests
30 | run: ./gradlew test
31 |
32 | - name: Archive artifacts
33 | uses: actions/upload-artifact@v2
34 | with:
35 | name: app-artifacts
36 | path: app/build/outputs/
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/GenerationParameterDao.java:
--------------------------------------------------------------------------------
1 | package namlit.siteswapgenerator;
2 |
3 | import androidx.room.Dao;
4 | import androidx.room.Delete;
5 | import androidx.room.Insert;
6 | import androidx.room.Query;
7 |
8 | import java.util.List;
9 |
10 | @Dao
11 | public interface GenerationParameterDao {
12 |
13 | @Query("SELECT * FROM generation_parameters ORDER BY name")
14 | List getAllGenerationParameters();
15 |
16 | @Query("SELECT * FROM generation_parameters WHERE name IS :name")
17 | GenerationParameterEntity getGenerationParamenters(String name);
18 |
19 | @Insert
20 | void insertGenerationParameters(GenerationParameterEntity... generationParameters);
21 |
22 | @Delete
23 | void deleteGenerationParameters(GenerationParameterEntity generationParameters);
24 | }
25 |
--------------------------------------------------------------------------------
/images/exportAllPNG.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | inkscape appicon.svg --export-png ../app/src/main/res/mipmap-mdpi/appicon.png -w 48 -h 48
4 | inkscape appicon.svg --export-png ../app/src/main/res/mipmap-hdpi/appicon.png -w 72 -h 72
5 | inkscape appicon.svg --export-png ../app/src/main/res/mipmap-xhdpi/appicon.png -w 96 -h 96
6 | inkscape appicon.svg --export-png ../app/src/main/res/mipmap-xxhdpi/appicon.png -w 144 -h 144
7 | inkscape appicon.svg --export-png ../app/src/main/res/mipmap-xxxhdpi/appicon.png -w 192 -h 192
8 |
9 | inkscape favorite_star_icon.svg --export-png ../app/src/main/res/drawable/favorite_star_icon.png -w 96 -h 96
10 | inkscape rotate_default_icon.svg --export-png ../app/src/main/res/drawable/rotate_default_icon.png -w 96 -h 96
11 | inkscape named_siteswaps_icon.svg --export-png ../app/src/main/res/drawable/named_siteswaps_icon.png -w 96 -h 96
12 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_show_favorites.xml:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | android.defaults.buildfeatures.buildconfig=true
13 | android.enableJetifier=true
14 | android.nonFinalResIds=false
15 | android.nonTransitiveRClass=false
16 | android.useAndroidX=true
17 | org.gradle.jvmargs=-Xmx1536m
18 | org.gradle.warning.mode=all
19 |
20 | # When configured, Gradle will run in incubating parallel mode.
21 | # This option should only be used with decoupled projects. More details, visit
22 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
23 | # org.gradle.parallel=true
24 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/tilman/Daten/AndroidSdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_show_siteswaps.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
21 |
22 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/test/java/namlit/siteswapgenerator/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 | import org.junit.Test;
22 |
23 | import static org.junit.Assert.*;
24 |
25 | /**
26 | * Example local unit test, which will execute on the development machine (host).
27 | *
28 | * @see Testing documentation
29 | */
30 | public class ExampleUnitTest {
31 | @Test
32 | public void addition_isCorrect() throws Exception {
33 | assertEquals(4, 2 + 2);
34 | }
35 | }
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_detailed_siteswap.xml:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdk 34
5 | defaultConfig {
6 | applicationId "namlit.siteswapgenerator"
7 | minSdkVersion 15
8 | targetSdkVersion 34
9 | versionCode 37
10 | versionName "1.5.0"
11 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
12 | javaCompileOptions {
13 | annotationProcessorOptions {
14 | arguments = ["room.schemaLocation":
15 | "$projectDir/schemas".toString()]
16 | }
17 | }
18 | }
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | namespace 'namlit.siteswapgenerator'
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: 'libs', include: ['*.jar'])
30 | androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
31 | exclude group: 'com.android.support', module: 'support-annotations'
32 | })
33 | def room_version = "1.1.1"
34 | implementation 'androidx.appcompat:appcompat:1.0.0'
35 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
36 | implementation 'com.google.android.material:material:1.0.0'
37 | implementation 'androidx.room:room-runtime:2.0.0'
38 | implementation 'com.google.zxing:core:3.2.0'
39 | annotationProcessor 'androidx.room:room-compiler:2.0.0'
40 | testImplementation 'junit:junit:4.12'
41 | testImplementation 'androidx.room:room-testing:2.0.0'
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/namlit/siteswapgenerator/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 | import android.content.Context;
22 | import androidx.test.platform.app.InstrumentationRegistry;
23 | import androidx.test.ext.junit.runners.AndroidJUnit4;
24 |
25 | import org.junit.Test;
26 | import org.junit.runner.RunWith;
27 |
28 | import static org.junit.Assert.*;
29 |
30 | /**
31 | * Instrumentation test, which will execute on an Android device.
32 | *
33 | * @see Testing documentation
34 | */
35 | @RunWith(AndroidJUnit4.class)
36 | public class ExampleInstrumentedTest {
37 | @Test
38 | public void useAppContext() throws Exception {
39 | // Context of the app under test.
40 | Context appContext = InstrumentationRegistry.getTargetContext();
41 |
42 | assertEquals("namlit.siteswapgenerator", appContext.getPackageName());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/InterfaceFilterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Test;
22 |
23 | import static org.junit.Assert.assertEquals;
24 |
25 | public class InterfaceFilterTest {
26 |
27 | @Test
28 | public void testParsableStringConversion() {
29 | InterfaceFilter filter1 = new InterfaceFilter(new Siteswap("ppsps"), InterfaceFilter.Type.EXCLUDE);
30 | InterfaceFilter filter2 = new InterfaceFilter(new Siteswap("972"), InterfaceFilter.Type.INCLUDE);
31 |
32 | String filter1str = filter1.toParsableString();
33 | String filter2str = filter2.toParsableString();
34 |
35 | InterfaceFilter filter1conv = new InterfaceFilter().fromParsableString(filter1str);
36 | InterfaceFilter filter2conv = new InterfaceFilter().fromParsableString(filter2str);
37 |
38 | assertEquals(filter1, filter1conv);
39 | assertEquals(filter2, filter2conv);
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/FavoriteDao.java:
--------------------------------------------------------------------------------
1 | package namlit.siteswapgenerator;
2 |
3 | import androidx.sqlite.db.SupportSQLiteQuery;
4 | import androidx.room.Dao;
5 | import androidx.room.Delete;
6 | import androidx.room.Insert;
7 | import androidx.room.Query;
8 | import androidx.room.RawQuery;
9 |
10 | import java.util.List;
11 |
12 | @Dao
13 | public interface FavoriteDao {
14 |
15 | @Query("SELECT * FROM favorites ORDER BY name")
16 | List getAllFavorites();
17 |
18 | @Query("SELECT * FROM favorites WHERE siteswap IS :siteswap")
19 | List getSiteswaps(String siteswap);
20 |
21 | @Query("SELECT * FROM favorites WHERE siteswap IS :siteswap")
22 | SiteswapEntity getSiteswap(String siteswap);
23 |
24 | @Query("SELECT DISTINCT juggler_names FROM favorites ORDER BY juggler_names")
25 | List getJugglers();
26 |
27 | @Query("SELECT DISTINCT location FROM favorites ORDER BY location")
28 | List getLocations();
29 |
30 | @Query("SELECT DISTINCT date FROM favorites ORDER BY date")
31 | List getDates();
32 |
33 | @Query("SELECT * FROM favorites WHERE juggler_names IS :juggler")
34 | List getSiteswapsOfJuggler(String juggler);
35 |
36 | @Query("SELECT * FROM favorites WHERE location IS :location")
37 | List getSiteswapsOfLocation(String location);
38 |
39 | @Query("SELECT * FROM favorites WHERE date IS :date")
40 | List getSiteswapsOfDate(String date);
41 |
42 | @RawQuery
43 | int checkpoint(SupportSQLiteQuery supportSQLiteQuery);
44 |
45 | @Insert
46 | void insertFavorites(SiteswapEntity... siteswap);
47 |
48 | @Delete
49 | void deleteFavorite(SiteswapEntity siteswap);
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/LocalPatternFilterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Test;
22 |
23 | import static org.junit.Assert.assertEquals;
24 |
25 | public class LocalPatternFilterTest {
26 |
27 | @Test
28 | public void testParsableStringConversion() {
29 | LocalPatternFilter filter1 = new LocalPatternFilter(new Siteswap("ppsps"), LocalPatternFilter.Type.EXCLUDE, 3);
30 | LocalPatternFilter filter2 = new LocalPatternFilter(new Siteswap("972"), LocalPatternFilter.Type.INCLUDE, 5);
31 |
32 | String filter1str = filter1.toParsableString();
33 | String filter2str = filter2.toParsableString();
34 |
35 | LocalPatternFilter filter1conv = new LocalPatternFilter().fromParsableString(filter1str);
36 | LocalPatternFilter filter2conv = new LocalPatternFilter().fromParsableString(filter2str);
37 |
38 | assertEquals(filter1, filter1conv);
39 | assertEquals(filter2, filter2conv);
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/PatternFilterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Test;
22 |
23 | import static org.junit.Assert.assertArrayEquals;
24 | import static org.junit.Assert.assertEquals;
25 | import static org.junit.Assert.assertNotEquals;
26 |
27 | public class PatternFilterTest {
28 |
29 | @Test
30 | public void testParsableStringConversion() {
31 | PatternFilter filter1 = new PatternFilter(new Siteswap("ppsps"), PatternFilter.Type.EXCLUDE);
32 | PatternFilter filter2 = new PatternFilter(new Siteswap("972"), PatternFilter.Type.INCLUDE);
33 |
34 | String filter1str = filter1.toParsableString();
35 | String filter2str = filter2.toParsableString();
36 |
37 | PatternFilter filter1conv = new PatternFilter(filter1str);
38 | PatternFilter filter2conv = new PatternFilter(filter2str);
39 |
40 | assertEquals(filter1, filter1conv);
41 | assertEquals(filter2, filter2conv);
42 |
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/SiteswapArrayAdapter.java:
--------------------------------------------------------------------------------
1 | package namlit.siteswapgenerator;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.ArrayAdapter;
9 | import android.widget.TextView;
10 |
11 | import java.util.List;
12 |
13 | import siteswaplib.NamedSiteswap;
14 | import siteswaplib.Siteswap;
15 |
16 | public class SiteswapArrayAdapter extends ArrayAdapter {
17 |
18 | private final LayoutInflater mInflater;
19 | private final int mResource;
20 |
21 | public SiteswapArrayAdapter (Context context, int resource, List siteswaps) {
22 |
23 | super(context, resource, siteswaps);
24 | mInflater = LayoutInflater.from(context);
25 | mResource = resource;
26 | }
27 |
28 | @Override
29 | public View getView(int position, View convertView, ViewGroup parent) {
30 |
31 | final View view;
32 | final TextView text;
33 | LayoutInflater inflater = mInflater;
34 | int resource = mResource;
35 | if (convertView == null) {
36 | view = inflater.inflate(resource, parent, false);
37 | } else {
38 | view = convertView;
39 | }
40 | try {
41 | text = (TextView) view;
42 |
43 | } catch (ClassCastException e) {
44 | Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
45 | throw new IllegalStateException(
46 | "ArrayAdapter requires the resource ID to be a TextView", e);
47 | }
48 | final NamedSiteswap siteswap = getItem(position);
49 | text.setText(siteswap.toString());
50 | return view;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/LocalInterfaceFilterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Test;
22 |
23 | import static org.junit.Assert.assertEquals;
24 |
25 | public class LocalInterfaceFilterTest {
26 |
27 | @Test
28 | public void testParsableStringConversion() {
29 | LocalInterfaceFilter filter1 = new LocalInterfaceFilter(new Siteswap("ppsps"), LocalInterfaceFilter.Type.EXCLUDE, 3);
30 | LocalInterfaceFilter filter2 = new LocalInterfaceFilter(new Siteswap("972"), LocalInterfaceFilter.Type.INCLUDE, 5);
31 |
32 | String filter1str = filter1.toParsableString();
33 | String filter2str = filter2.toParsableString();
34 |
35 | LocalInterfaceFilter filter1conv = new LocalInterfaceFilter().fromParsableString(filter1str);
36 | LocalInterfaceFilter filter2conv = new LocalInterfaceFilter().fromParsableString(filter2str);
37 |
38 | assertEquals(filter1, filter1conv);
39 | assertEquals(filter2, filter2conv);
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_about_page.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
17 |
18 |
26 |
27 |
36 |
37 |
40 |
41 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/Filter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import java.io.Serializable;
22 | import java.util.LinkedList;
23 |
24 | import siteswaplib.NumberFilter.Type;
25 |
26 | public abstract class Filter implements Serializable {
27 |
28 | public enum FilterType {NUMBER_FILTER, PATTERN_FILTER, INTERFACE_FILTER,
29 | LOCAL_PATTERN_FILTER, LOCAL_INTERFACE_FILTER};
30 |
31 | public abstract boolean isFulfilled(Siteswap siteswap);
32 |
33 | /**
34 | * The filter is only tested at/up to index position. This function can be
35 | * used during siteswap generation to test, if a partly generated siteswap
36 | * would fulfill the filter condition. Returns true, if the filter is currently
37 | * fulfilled or might be fulfilled later, when the complete siteswap is
38 | * generated. Returns False, if it is not possible anymore, to fulfill the filter
39 | * condition.
40 | * */
41 | public abstract boolean isPartlyFulfilled(Siteswap siteswap, int index);
42 |
43 | public abstract String toParsableString();
44 | public abstract Filter fromParsableString(String str);
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/FilterListTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Test;
22 |
23 | import static org.junit.Assert.assertEquals;
24 |
25 | public class FilterListTest {
26 |
27 | @Test
28 | public void testParsableStringConversion() {
29 | FilterList list1 = new FilterList();
30 | list1.addDefaultFilters(5, 1);
31 | FilterList list2 = new FilterList();
32 | list2.addDefaultFilters(3, 3);
33 |
34 | list1.add(new NumberFilter("9p", NumberFilter.Type.EQUAL, 1, 3));
35 | list1.add(new NumberFilter("9", NumberFilter.Type.EQUAL, 1, 3));
36 | list1.add(new LocalInterfaceFilter(new Siteswap("ppsps"), LocalInterfaceFilter.Type.EXCLUDE, 3));
37 |
38 | String list1str = list1.toParsableString();
39 | String list2str = list2.toParsableString();
40 |
41 | FilterList list1conv = new FilterList().fromParsableString(list1str);
42 | FilterList list2conv = new FilterList().fromParsableString(list2str);
43 |
44 | assertEquals(list1, list1conv);
45 | assertEquals(list2, list2conv);
46 |
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/NonScrollListView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 | import android.util.AttributeSet;
22 | import android.widget.ListView;
23 | import android.content.Context;
24 | import android.view.ViewGroup;
25 |
26 | /**
27 | * Created by tilman on 07.10.17.
28 | */
29 |
30 | public class NonScrollListView extends ListView {
31 |
32 | public NonScrollListView(Context context) {
33 | super(context);
34 | }
35 | public NonScrollListView(Context context, AttributeSet attrs) {
36 | super(context, attrs);
37 | }
38 | public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
39 | super(context, attrs, defStyle);
40 | }
41 | @Override
42 | public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
43 | int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
44 | Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
45 | super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
46 | ViewGroup.LayoutParams params = getLayoutParams();
47 | params.height = getMeasuredHeight();
48 | }
49 | }
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/AddFilterDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 | import android.content.Context;
22 | import androidx.fragment.app.DialogFragment;
23 |
24 | import siteswaplib.Filter;
25 |
26 | /**
27 | * Created by tilman on 29.10.17.
28 | */
29 |
30 | public class AddFilterDialog extends DialogFragment {
31 |
32 | public interface FilterDialogListener {
33 | public void onAddSiteswapFilter(Filter filter);
34 | public void onRemoveSiteswapFilter(Filter filter);
35 | public void onChangeSiteswapFilter(Filter oldFilter, Filter newFilter);
36 | }
37 |
38 | // Use this instance of the interface to deliver action events
39 | FilterDialogListener mListener;
40 |
41 | // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
42 | @Override
43 | public void onAttach(Context context) {
44 | super.onAttach(context);
45 |
46 | try {
47 |
48 | mListener = (FilterDialogListener) context;
49 | } catch (ClassCastException e) {
50 |
51 | throw new ClassCastException(context.toString()
52 | + " must implement NoticeDialogListener");
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_enter_siteswap.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
15 |
16 |
23 |
24 |
25 |
28 |
29 |
34 |
35 |
42 |
43 |
44 |
47 |
48 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/privacy-policy.md:
--------------------------------------------------------------------------------
1 | # Privacy Policy for Siteswap Generator App
2 |
3 | Last updated: 2023-12-27
4 |
5 | Thank you for using the Siteswap Generator app! Your privacy is important to us, and we are committed to protecting your personal information. This Privacy Policy is designed to help you understand how we collect, use, and safeguard your data when you use our mobile application.
6 |
7 | ## 1. No Collection of Personal Information
8 |
9 | The Siteswap Generator app does not collect, store, or transmit any personally identifiable information. We do not access, use, or share your location, contacts, photos, or any other personal data. The app is designed to respect your privacy by operating without the need for user account creation or data tracking.
10 |
11 | ## 2. Anonymous Usage Statistics
12 |
13 | To improve the app's performance and user experience, the Siteswap Generator app may collect anonymous usage statistics. These statistics are limited to non-personal data such as app crashes, device information, and general usage patterns. This information is used solely for analytical purposes and does not identify individual users.
14 |
15 | ## 3. External Links
16 |
17 | The app may contain links to external websites or services. We are not responsible for the privacy practices or content of these external sites. Please review the privacy policies of those third-party services for information on how they collect, use, and safeguard your data.
18 |
19 | ## 4. Security
20 |
21 | We take reasonable measures to protect your information from unauthorized access, disclosure, alteration, and destruction. However, please be aware that no method of transmission over the internet or electronic storage is 100% secure. Therefore, we cannot guarantee absolute security.
22 |
23 | ## 5. Changes to this Privacy Policy
24 |
25 | We may update this Privacy Policy from time to time to reflect changes in our practices or for other operational, legal, or regulatory reasons. It is recommended that you review this Privacy Policy periodically for any changes. The date of the last update will be provided at the top of this document.
26 | Contact Us
27 |
28 | If you have any questions or concerns about this Privacy Policy or the Siteswap Generator app, please contact us at namlitdev@mailbox.org.
29 |
30 | By using the Siteswap Generator app, you agree to the terms outlined in this Privacy Policy.
31 |
32 | Thank you for your trust in our commitment to privacy.
33 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/AppDatabase.java:
--------------------------------------------------------------------------------
1 | package namlit.siteswapgenerator;
2 |
3 | import androidx.sqlite.db.SupportSQLiteDatabase;
4 | import androidx.room.Database;
5 | import androidx.room.Room;
6 | import androidx.room.RoomDatabase;
7 | import androidx.room.migration.Migration;
8 | import android.content.Context;
9 |
10 | @Database(entities = {SiteswapEntity.class, GenerationParameterEntity.class}, version = 2)
11 | public abstract class AppDatabase extends RoomDatabase {
12 |
13 | public final static String database_name = "siteswap_generator_app_database";
14 | private static AppDatabase INSTANCE;
15 |
16 | public abstract FavoriteDao siteswapDao();
17 | public abstract GenerationParameterDao generationParameterDao();
18 |
19 | public static AppDatabase getAppDatabase(Context context) {
20 | if (INSTANCE == null) {
21 | INSTANCE =
22 | Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class,
23 | database_name)
24 | .addMigrations(MIGRATION_1_2)
25 | .build();
26 | }
27 | return INSTANCE;
28 | }
29 |
30 | public static void destroyInstance() {
31 | INSTANCE = null;
32 | }
33 |
34 | static final Migration MIGRATION_1_2 = new Migration(1, 2) {
35 | @Override
36 | public void migrate(SupportSQLiteDatabase database) {
37 | database.execSQL("CREATE TABLE `generation_parameters` (" +
38 | "`uid` INTEGER NOT NULL, " +
39 | "`name` TEXT, " +
40 | "`numberOfObjects` INTEGER NOT NULL, " +
41 | "`periodLength` INTEGER NOT NULL, " +
42 | "`maxThrow` INTEGER NOT NULL, " +
43 | "`minThrow` INTEGER NOT NULL, " +
44 | "`numberOfJugglers` INTEGER NOT NULL, " +
45 | "`maxResults` INTEGER NOT NULL, " +
46 | "`timeout` INTEGER NOT NULL, " +
47 | "`isSynchronous` INTEGER NOT NULL, " +
48 | "`isRandomMode` INTEGER NOT NULL, " +
49 | "`isZips` INTEGER NOT NULL, " +
50 | "`isZaps` INTEGER NOT NULL, " +
51 | "`isHolds` INTEGER NOT NULL, " +
52 | "`filterListString` TEXT, " +
53 | "PRIMARY KEY(`uid`))");
54 | }
55 | };
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/number_filter_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
22 |
23 |
29 |
30 |
36 |
37 |
38 |
39 |
44 |
45 |
50 |
51 |
58 |
59 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/CyclicByteArray.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import java.util.*;
22 | import java.io.Serializable;
23 |
24 | public class CyclicByteArray implements Iterable, Iterator, Serializable{
25 | private int first_element_index = 0;
26 | private int iterator_count = 0;
27 | private byte[] data;
28 |
29 | public CyclicByteArray(byte[] data) {
30 | this.data = new byte[data.length];
31 | for(int i = 0; i < data.length; ++i)
32 | this.data[i] = data[i];
33 | }
34 |
35 | public CyclicByteArray(CyclicByteArray array) {
36 | this(array.data);
37 | this.first_element_index = array.first_element_index;
38 | }
39 |
40 | public byte at(int index) {
41 | if (length() == 0)
42 | return 0;
43 | return data[((first_element_index + index) % length() + length()) % length()];
44 | }
45 |
46 | public void modify(int index, byte value) {
47 | if (length() == 0)
48 | return;
49 | data[((first_element_index + index) % length() + length()) % length()] = value;
50 | }
51 |
52 | public int length() {
53 | return data.length;
54 | }
55 |
56 | public void rotateRight(int positions) {
57 | if (length() == 0)
58 | return;
59 | first_element_index = (first_element_index - positions) % length();
60 | if (first_element_index < 0)
61 | first_element_index += length();
62 | }
63 |
64 | public void rotateLeft(int positions) {
65 | if (length() == 0)
66 | return;
67 | first_element_index = (first_element_index + positions) % length();
68 | if (first_element_index < 0)
69 | first_element_index += length();
70 | }
71 |
72 | @Override
73 | public Iterator iterator() {
74 | iterator_count = 0;
75 | return this;
76 | }
77 |
78 | @Override
79 | public boolean hasNext() {
80 | return iterator_count != length();
81 | }
82 |
83 | @Override
84 | public Byte next() {
85 | if (iterator_count >= length())
86 | throw new NoSuchElementException();
87 |
88 | return at(iterator_count++);
89 | }
90 |
91 | @Override
92 | public void remove() {
93 | // not implemented
94 | }
95 |
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/SiteswapGeneratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Test;
22 |
23 | import java.util.LinkedList;
24 |
25 | import static org.junit.Assert.assertEquals;
26 | import static siteswaplib.SiteswapGenerator.Status.ALL_SITESWAPS_FOUND;
27 |
28 | public class SiteswapGeneratorTest {
29 |
30 | @Test
31 | public void testGeneration() {
32 | int numberOfJugglers = 2;
33 | int period = 7;
34 | int minThrow = 2;
35 | int maxThrow = 10;
36 | int numberOfObjects = 6;
37 | int numberOfSynchronousHands = 1;
38 | FilterList filters = new FilterList();
39 | filters.addDefaultFilters(numberOfJugglers, minThrow, numberOfSynchronousHands);
40 | filters.add(new LocalInterfaceFilter(
41 | new Siteswap("ppspsps"), PatternFilter.Type.INCLUDE, numberOfJugglers));
42 | filters.add(new LocalPatternFilter(
43 | new Siteswap("22"), PatternFilter.Type.EXCLUDE, numberOfJugglers));
44 | filters.add(new LocalPatternFilter(
45 | new Siteswap("44"), PatternFilter.Type.EXCLUDE, numberOfJugglers));
46 |
47 | SiteswapGenerator gen = new SiteswapGenerator(period, maxThrow, minThrow, numberOfObjects, numberOfJugglers, filters);
48 | gen.setSyncPattern(false);
49 |
50 | SiteswapGenerator.Status status = gen.generateSiteswaps();
51 | assertEquals(ALL_SITESWAPS_FOUND, status);
52 | String expected = new String("[7567566, 7746675, 7746756, 7747746, 8456757, 8457567, 8457747, 8556756, 8557566, 8557746, 8557845, 8558556, 8627577, 8852757, 9245778, 9457467, 9458457, 9525678, 9527478, 9527892, 9529458, 9557466, 9557862, 9558456, 9558852, 9625677, 9627477, 9629457, 9645675, 9645774, 9685275, 9695274, 9724677, 9729627, 9744675, 9744774, 9749625, 9749724, 9784275, 9789225, 9794274, 9922497, 9924477, 9924972, 9929427, 9929922, 9952467, 9952962, a524579, a525578, a529529, a625577, a645575, a675275, a724577, a729527, a744575, a749525, a756275, a759245, a774275, a779225, a855275]");
53 | assertEquals(expected, gen.getSiteswaps().toString());
54 | return;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/SiteswapEntity.java:
--------------------------------------------------------------------------------
1 | package namlit.siteswapgenerator;
2 |
3 | import androidx.room.ColumnInfo;
4 | import androidx.room.Entity;
5 | import androidx.room.PrimaryKey;
6 | import androidx.annotation.NonNull;
7 |
8 | import java.io.Serializable;
9 |
10 | import siteswaplib.Siteswap;
11 |
12 | @Entity(tableName = "favorites")
13 | public class SiteswapEntity implements Serializable {
14 |
15 | @PrimaryKey(autoGenerate = true)
16 | @ColumnInfo(name = "uid")
17 | private int uid;
18 |
19 | @ColumnInfo(name = "siteswap")
20 | private String siteswap;
21 |
22 | @ColumnInfo(name = "name")
23 | private String name;
24 |
25 | @ColumnInfo(name = "juggler_names")
26 | private String juggerNames;
27 |
28 | @ColumnInfo(name = "location")
29 | private String location;
30 |
31 | @ColumnInfo(name = "date")
32 | private String date;
33 |
34 | public SiteswapEntity() {
35 |
36 | }
37 |
38 | public SiteswapEntity(Siteswap siteswap, String name, String juggerNames,
39 | String location, String date) {
40 | fromSiteswap(siteswap);
41 | setName(name);
42 | setJuggerNames(juggerNames);
43 | setLocation(location);
44 | setDate(date);
45 | }
46 |
47 | public int getUid() {
48 | return uid;
49 | }
50 |
51 | public void setUid(int uid) {
52 | this.uid = uid;
53 | }
54 |
55 | public String getSiteswap() {
56 | return siteswap;
57 | }
58 |
59 | public void setSiteswap(String siteswap) {
60 | this.siteswap = siteswap;
61 | }
62 |
63 | public String getName() {
64 | return name;
65 | }
66 |
67 | public void setName(String favoriteName) {
68 | this.name = favoriteName;
69 | }
70 |
71 | public String getJuggerNames() {
72 | return juggerNames;
73 | }
74 |
75 | public void setJuggerNames(String juggerNames) {
76 | this.juggerNames = juggerNames;
77 | }
78 |
79 | public String getLocation() {
80 | return location;
81 | }
82 |
83 | public void setLocation(String location) {
84 | this.location = location;
85 | }
86 |
87 | public String getDate() {
88 | return date;
89 | }
90 |
91 | public void setDate(String date) {
92 | this.date = date;
93 | }
94 |
95 | public Siteswap toSiteswap() {
96 | Siteswap siteswap = new Siteswap(getSiteswap());
97 | return siteswap;
98 | }
99 |
100 | public void fromSiteswap(Siteswap siteswap) {
101 | setSiteswap(siteswap.toParsableString());
102 | setName(siteswap.getSiteswapName());
103 | }
104 |
105 | @Override
106 | public String toString() {
107 | return getName() + ", " +
108 | getJuggerNames() + ", " +
109 | getLocation() + ", " +
110 | getDate();
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/InterfaceFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | /**
22 | * Created by tilman on 29.10.17.
23 | */
24 |
25 | public class InterfaceFilter extends PatternFilter {
26 |
27 | static final private String VERSION = "1";
28 |
29 | public InterfaceFilter() {
30 | }
31 |
32 | public InterfaceFilter(String str) {
33 | fromParsableString(str);
34 | }
35 |
36 | public InterfaceFilter(Siteswap pattern, Type type) {
37 | super(pattern, type);
38 | }
39 |
40 | @Override
41 | public String toString() {
42 | String str;
43 |
44 | if (mType == Type.INCLUDE)
45 | str = new String("Include Interface: ");
46 | else
47 | str = new String("Exclude Interface: ");
48 | str += mPattern.toString();
49 | return str;
50 | }
51 |
52 | @Override
53 | public String toParsableString() {
54 | String str = new String();
55 | str += String.valueOf(VERSION) + ",";
56 | str += super.toParsableString();
57 | return str;
58 | }
59 |
60 | @Override
61 | public InterfaceFilter fromParsableString(String str) {
62 | String[] splits = str.split(",");
63 | int begin_index = 0;
64 | if (splits.length < 3) {
65 | return this;
66 | }
67 | if (!splits[0].equals(VERSION))
68 | return this;
69 | begin_index += splits[0].length() + 1;
70 | super.fromParsableString(str.substring(begin_index));
71 | return this;
72 | }
73 |
74 | @Override
75 | public boolean isFulfilled(Siteswap siteswap) {
76 |
77 | Siteswap siteswapInterface = siteswap.toInterface(Siteswap.FREE);
78 |
79 | if (mType == Type.INCLUDE)
80 | return siteswapInterface.isPattern(mPattern);
81 | return !siteswapInterface.isPattern(mPattern);
82 | }
83 |
84 |
85 | @Override
86 | public boolean isPartlyFulfilled(Siteswap siteswap, int index) {
87 |
88 | if (mType == Type.EXCLUDE) {
89 | return isFulfilled(siteswap);
90 | }
91 |
92 | // Intefaces that need to be included are not checked for partly generated siteswaps
93 | // at the moment
94 | return true;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/images/favorite_star_icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
78 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/PatternFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | public class PatternFilter extends Filter {
22 |
23 | public enum Type {EXCLUDE, INCLUDE}
24 | static final private String VERSION = "1";
25 |
26 | protected Siteswap mPattern;
27 | protected Type mType;
28 |
29 | public PatternFilter() {
30 | }
31 |
32 | public PatternFilter(String str) {
33 | fromParsableString(str);
34 | }
35 |
36 | public PatternFilter(Siteswap pattern, Type type) {
37 | this.mPattern = pattern;
38 | this.mType = type;
39 | }
40 |
41 | @Override
42 | public boolean isFulfilled(Siteswap siteswap) {
43 | if (mType == Type.INCLUDE)
44 | return siteswap.isPattern(mPattern);
45 | return !siteswap.isPattern(mPattern);
46 | }
47 |
48 |
49 | @Override
50 | public boolean isPartlyFulfilled(Siteswap siteswap, int index) {
51 | if (mType == Type.INCLUDE)
52 | return true; // TODO return false, if it is impossible to fulfill pattern
53 | switch (mType)
54 | {
55 | case INCLUDE:
56 | break;
57 | case EXCLUDE:
58 | if (index < mPattern.period_length() - 1)
59 | return true;
60 | return !siteswap.isPattern(mPattern, index + 1 - mPattern.period_length());
61 | }
62 | return true;
63 | }
64 |
65 | @Override
66 | public String toParsableString() {
67 | String str = new String();
68 | str += String.valueOf(VERSION) + ",";
69 | str += mPattern.toParsableString() + ",";
70 | str += mType.toString() + ",";
71 | return str;
72 | }
73 |
74 | @Override
75 | public PatternFilter fromParsableString(String str) {
76 | String[] splits = str.split(",");
77 | if (splits.length < 3) {
78 | return this;
79 | }
80 | if (!splits[0].equals(VERSION))
81 | return this;
82 | mPattern = new Siteswap(splits[1]);
83 | mType = Type.valueOf(splits[2]);
84 | return this;
85 | }
86 |
87 | @Override
88 | public String toString() {
89 | String str;
90 | if (mType == Type.INCLUDE)
91 | str = new String("Include: ");
92 | else
93 | str = new String("Exclude: ");
94 | str += mPattern.toString();
95 | return str;
96 | }
97 |
98 | @Override
99 | public boolean equals(Object obj) {
100 | if (! (obj instanceof PatternFilter))
101 | return false;
102 | PatternFilter rhs = (PatternFilter) obj;
103 | return mType.equals(rhs.mType) && mPattern.equals(rhs.mPattern);
104 | }
105 |
106 | public Type getType() {
107 | return mType;
108 | }
109 |
110 | public Siteswap getPattern() {
111 | return mPattern;
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/LocalInterfaceFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | /**
22 | * Created by tilman on 29.10.17.
23 | */
24 |
25 | public class LocalInterfaceFilter extends InterfaceFilter {
26 |
27 | static final private String VERSION = "1";
28 |
29 | private Siteswap mLocalPattern;
30 |
31 | public LocalInterfaceFilter() {
32 | }
33 |
34 | public LocalInterfaceFilter(String str) {
35 | fromParsableString(str);
36 | }
37 |
38 | public LocalInterfaceFilter(Siteswap pattern, Type type, int numberOfJugglers) {
39 | super(pattern, type);
40 |
41 | mLocalPattern = pattern;
42 |
43 | byte[] globalPattern = new byte[numberOfJugglers * pattern.period_length() - (numberOfJugglers-1)];
44 |
45 | for (int i = 0; i < globalPattern.length; ++i) {
46 | if (i % numberOfJugglers == 0)
47 | globalPattern[i] = pattern.at(i / numberOfJugglers);
48 | else
49 | globalPattern[i] = Siteswap.DONT_CARE;
50 | }
51 | mPattern = new Siteswap(globalPattern);
52 |
53 | }
54 |
55 | @Override
56 | public String toParsableString() {
57 | String str = new String();
58 | str += String.valueOf(VERSION) + ",";
59 | str += mLocalPattern.toParsableString() + ",";
60 | str += super.toParsableString();
61 | return str;
62 | }
63 |
64 | @Override
65 | public LocalInterfaceFilter fromParsableString(String str) {
66 | String[] splits = str.split(",");
67 | int begin_index = 0;
68 | if (splits.length < 3) {
69 | return this;
70 | }
71 | if (!splits[0].equals(VERSION))
72 | return this;
73 | begin_index += splits[0].length() + 1;
74 | mLocalPattern = new Siteswap(splits[1]);
75 | begin_index += splits[1].length() + 1;
76 | super.fromParsableString(str.substring(begin_index));
77 | return this;
78 | }
79 |
80 | @Override
81 | public String toString() {
82 | String str;
83 |
84 | if (mType == Type.INCLUDE)
85 | str = new String("Include Local Interface: ");
86 | else
87 | str = new String("Exclude Local Interface: ");
88 | str += mLocalPattern.toString();
89 | return str;
90 | }
91 |
92 | public Siteswap getGlobalPattern() {
93 | return mPattern;
94 | }
95 |
96 | @Override
97 | public Siteswap getPattern() {
98 | return mLocalPattern;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/images/named_siteswaps_icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
89 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/NamedSiteswapActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 | import android.content.Intent;
22 | import android.os.Bundle;
23 | import androidx.appcompat.app.AppCompatActivity;
24 |
25 | import android.text.TextUtils;
26 | import android.view.View;
27 | import android.widget.AdapterView;
28 | import android.widget.ListView;
29 | import android.widget.SearchView;
30 |
31 | import java.util.List;
32 |
33 | import siteswaplib.NamedSiteswap;
34 | import siteswaplib.NamedSiteswaps;
35 | import siteswaplib.Siteswap;
36 |
37 | public class NamedSiteswapActivity extends AppCompatActivity {
38 |
39 | static final private List mSiteswapList = NamedSiteswaps.getListOfNamedSiteswaps();
40 |
41 | SearchView mSearchView;
42 | ListView mSiteswapListView;
43 |
44 |
45 | @Override
46 | protected void onCreate(Bundle savedInstanceState) {
47 | super.onCreate(savedInstanceState);
48 | setContentView(R.layout.activity_show_siteswaps);
49 |
50 | setTitle(String.format(getString(R.string.named_siteswaps__title)));
51 |
52 | mSiteswapListView = (ListView) findViewById(R.id.siteswap_list);
53 | mSearchView = (SearchView) findViewById(R.id.search_view);
54 |
55 | SiteswapArrayAdapter adapter = new SiteswapArrayAdapter(
56 | NamedSiteswapActivity.this, android.R.layout.simple_list_item_1, mSiteswapList);
57 | mSiteswapListView.setAdapter(adapter);
58 | mSiteswapListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
59 | @Override
60 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
61 |
62 | Siteswap siteswap = ((Siteswap) parent.getItemAtPosition(position));
63 | Intent intent = new Intent(getApplicationContext(), DetailedSiteswapActivity.class);
64 | intent.putExtra(getString(R.string.intent_detailed_siteswap_view__siteswap), siteswap);
65 | startActivity(intent);
66 | }
67 | });
68 |
69 | mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
70 | @Override
71 | public boolean onQueryTextSubmit(String query) {
72 | return false;
73 | }
74 |
75 | @Override
76 | public boolean onQueryTextChange(String newText) {
77 | if (TextUtils.isEmpty(newText)) {
78 | adapter.getFilter().filter(null);
79 | } else {
80 | adapter.getFilter().filter(newText);
81 | }
82 | return true;
83 | }
84 | });
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/LocalPatternFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | /**
22 | * Created by tilman on 29.10.17.
23 | */
24 |
25 | public class LocalPatternFilter extends PatternFilter {
26 |
27 | static final private String VERSION = "1";
28 | private Siteswap mLocalPattern;
29 |
30 | public LocalPatternFilter() {
31 | }
32 |
33 | public LocalPatternFilter(String str) {
34 | fromParsableString(str);
35 | }
36 |
37 | public LocalPatternFilter(Siteswap pattern, Type type, int numberOfJugglers) {
38 | super(pattern, type);
39 |
40 | mLocalPattern = pattern;
41 |
42 | byte[] globalPattern = new byte[numberOfJugglers * pattern.period_length() - (numberOfJugglers-1)];
43 |
44 | for (int i = 0; i < globalPattern.length; ++i) {
45 | if (i % numberOfJugglers == 0)
46 | globalPattern[i] = pattern.at(i / numberOfJugglers);
47 | else
48 | globalPattern[i] = Siteswap.DONT_CARE;
49 | }
50 | mPattern = new Siteswap(globalPattern);
51 |
52 | }
53 |
54 | @Override
55 | public String toParsableString() {
56 | String str = new String();
57 | str += String.valueOf(VERSION) + ",";
58 | str += mLocalPattern.toParsableString() + ",";
59 | str += super.toParsableString();
60 | return str;
61 | }
62 |
63 | @Override
64 | public LocalPatternFilter fromParsableString(String str) {
65 | String[] splits = str.split(",");
66 | int begin_index = 0;
67 | if (splits.length < 3) {
68 | return this;
69 | }
70 | if (!splits[0].equals(VERSION))
71 | return this;
72 | begin_index += splits[0].length() + 1;
73 | mLocalPattern = new Siteswap(splits[1]);
74 | begin_index += splits[1].length() + 1;
75 | super.fromParsableString(str.substring(begin_index));
76 | return this;
77 | }
78 |
79 | @Override
80 | public String toString() {
81 | String str;
82 |
83 | if (mType == Type.INCLUDE)
84 | str = new String("Include Local: ");
85 | else
86 | str = new String("Exclude Local: ");
87 | str += mLocalPattern.toString();
88 | return str;
89 | }
90 |
91 | @Override
92 | public boolean equals(Object obj) {
93 | if (! (obj instanceof LocalPatternFilter))
94 | return false;
95 | LocalPatternFilter rhs = (LocalPatternFilter) obj;
96 | return mLocalPattern.equals(rhs.mLocalPattern) && super.equals(rhs);
97 | }
98 |
99 |
100 | public Siteswap getGlobalPattern() {
101 | return mPattern;
102 | }
103 |
104 | @Override
105 | public Siteswap getPattern() {
106 | return mLocalPattern;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/QRCodeDialog.java:
--------------------------------------------------------------------------------
1 | package namlit.siteswapgenerator;
2 |
3 | import android.app.Dialog;
4 | import android.graphics.Point;
5 | import androidx.fragment.app.DialogFragment;
6 | import androidx.fragment.app.FragmentManager;
7 | import androidx.appcompat.app.AlertDialog;
8 | import android.graphics.Bitmap;
9 | import android.graphics.Color;
10 | import android.os.Bundle;
11 | import android.view.Display;
12 | import android.view.WindowManager;
13 | import android.widget.ImageView;
14 |
15 | import com.google.zxing.BarcodeFormat;
16 | import com.google.zxing.WriterException;
17 | import com.google.zxing.common.BitMatrix;
18 | import com.google.zxing.qrcode.QRCodeWriter;
19 |
20 | import static android.content.Context.WINDOW_SERVICE;
21 |
22 | public class QRCodeDialog extends DialogFragment {
23 |
24 | private static final String STATE_QR_CONTENT = "STATE_QR_CONTENT";
25 | String mQRContent;
26 | Bitmap mQRImage;
27 |
28 | @Override
29 | public Dialog onCreateDialog(Bundle savedInstanceState) {
30 |
31 | if(savedInstanceState != null) {
32 | mQRContent = savedInstanceState.getString(STATE_QR_CONTENT);
33 | }
34 |
35 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
36 |
37 | builder.setView(createQRCodeView());
38 | final AlertDialog dialog = builder.create();
39 | return dialog;
40 | }
41 |
42 | @Override
43 | public void onStart() {
44 | super.onStart();
45 | }
46 |
47 | @Override
48 | public void onSaveInstanceState(Bundle outState) {
49 | super.onSaveInstanceState(outState);
50 |
51 | outState.putString(STATE_QR_CONTENT, mQRContent);
52 | }
53 |
54 | @Override
55 | public void onStop() {
56 | super.onStop();
57 | }
58 |
59 | private ImageView createQRCodeView() {
60 |
61 | QRCodeWriter qrCodeWriter = new QRCodeWriter();
62 | try {
63 | WindowManager manager = (WindowManager) getActivity().getSystemService(WINDOW_SERVICE);
64 | Display display = manager.getDefaultDisplay();
65 | Point point = new Point();
66 | display.getSize(point);
67 | int width = point.x;
68 | int height = point.y;
69 | int smallerDimension = width < height ? width : height;
70 | smallerDimension = smallerDimension * 3/4;
71 |
72 | BitMatrix bitMatrix = qrCodeWriter.encode(mQRContent, BarcodeFormat.QR_CODE, smallerDimension, smallerDimension);
73 |
74 | final int w = bitMatrix.getWidth();
75 | final int h = bitMatrix.getHeight();
76 | final int[] pixels = new int[w * h];
77 |
78 | for (int y = 0; y < h; y++) {
79 | final int offset = y * w;
80 | for (int x = 0; x < w; x++) {
81 | pixels[offset + x] = bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE;
82 | }
83 | }
84 |
85 | mQRImage = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
86 | mQRImage.setPixels(pixels, 0, smallerDimension, 0, 0, w, h);
87 |
88 | ImageView imageView = new ImageView(getActivity());
89 | imageView.setImageBitmap(mQRImage);
90 | return imageView;
91 | }
92 | catch (WriterException e) {
93 | dismiss();
94 | return null;
95 | }
96 |
97 | }
98 |
99 | public void show(FragmentManager manager, String tag, String qrContent) {
100 | mQRContent = qrContent;
101 | show(manager, tag);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_generate_compatible_siteswap_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
13 |
14 |
19 |
20 |
27 |
28 |
31 |
32 |
37 |
38 |
45 |
46 |
49 |
50 |
55 |
56 |
63 |
64 |
65 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/ChooseRemoveFavoriteDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import androidx.fragment.app.DialogFragment;
26 | import androidx.fragment.app.FragmentManager;
27 | import androidx.appcompat.app.AlertDialog;
28 | import android.view.View;
29 | import android.widget.AdapterView;
30 | import android.widget.ArrayAdapter;
31 | import android.widget.ListView;
32 |
33 | import java.io.Serializable;
34 | import java.util.List;
35 |
36 | /**
37 | * Created by tilman on 29.10.17.
38 | */
39 |
40 | public class ChooseRemoveFavoriteDialog extends DialogFragment {
41 |
42 | private static final String STATE_SITESWAP_ENTITY_LIST = "STATE_SITESWAP_ENTITY_LIST";
43 | private ListView mListView;
44 | private List mSiteswapEntityList;
45 |
46 | @Override
47 | public Dialog onCreateDialog(Bundle savedInstanceState) {
48 |
49 | if(savedInstanceState != null) {
50 | mSiteswapEntityList = (List) savedInstanceState.getSerializable(STATE_SITESWAP_ENTITY_LIST);
51 | }
52 |
53 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
54 |
55 | builder.setView(R.layout.layout_choose_remove_favorite)
56 | .setTitle(getString(R.string.choose_remove_favorite__title))
57 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
58 | @Override
59 | public void onClick(DialogInterface dialog, int which) {
60 |
61 | }
62 | });
63 | final AlertDialog dialog = builder.create();
64 | return dialog;
65 | }
66 |
67 | @Override
68 | public void onStart() {
69 | super.onStart();
70 |
71 | mListView = (ListView) getDialog().findViewById(R.id.favorite_choose_remove_list);
72 | ArrayAdapter adapter = new ArrayAdapter(
73 | getContext(), android.R.layout.simple_list_item_1, mSiteswapEntityList);
74 | mListView.setAdapter(adapter);
75 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
76 | @Override
77 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
78 | SiteswapEntity siteswapEntity = ((SiteswapEntity) parent.getItemAtPosition(position));
79 |
80 | new ConfirmRemoveFavoriteDialog().show(getFragmentManager(),
81 | getString(R.string.confirm_remove_favorite__dialog_tag),
82 | siteswapEntity);
83 | dismiss();
84 | }
85 | });
86 |
87 |
88 | }
89 |
90 |
91 | @Override
92 | public void onSaveInstanceState(Bundle outState) {
93 | super.onSaveInstanceState(outState);
94 |
95 | outState.putSerializable(STATE_SITESWAP_ENTITY_LIST, (Serializable) mSiteswapEntityList);
96 | }
97 |
98 | @Override
99 | public void onStop() {
100 | super.onStop();
101 | }
102 |
103 | public void show(FragmentManager manager, String tag, List siteswapEntityList) {
104 | mSiteswapEntityList = siteswapEntityList;
105 | show(manager, tag);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_add_to_favorites.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
13 |
14 |
19 |
20 |
27 |
28 |
29 |
32 |
33 |
38 |
39 |
46 |
47 |
48 |
51 |
52 |
57 |
58 |
65 |
66 |
67 |
70 |
71 |
76 |
77 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/SiteswapTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Test;
22 |
23 | import static org.junit.Assert.assertArrayEquals;
24 | import static org.junit.Assert.assertEquals;
25 | import static org.junit.Assert.assertNotEquals;
26 |
27 | public class SiteswapTest {
28 |
29 | @Test
30 | public void testCreateSynchronousFromString() {
31 | String expected = new String("6p");
32 | NumberFilter filter = new NumberFilter(expected, NumberFilter.Type.EQUAL, 1, 2);
33 | }
34 |
35 | @Test
36 | public void testParseString() {
37 | String siteswap_str_1 = "v1.0.0/86277.2.1.0";
38 | String siteswap_str_1_substring = "86277.2.1.0";
39 | Siteswap siteswap_1 = new Siteswap(siteswap_str_1);
40 | assertEquals("86277", siteswap_1.toAsyncString());
41 | assertEquals(2, siteswap_1.getNumberOfJugglers());
42 | assertEquals(1, siteswap_1.getNumberOfSynchronousHands());
43 | assertEquals(0, siteswap_1.getSynchronousStartPosition());
44 | assertEquals(siteswap_str_1_substring, siteswap_1.toParsableString());
45 |
46 | String siteswap_str_2 = "c9ec99bc39ac99a.3.3.1";
47 | Siteswap siteswap_2 = new Siteswap(siteswap_str_2);
48 | assertEquals("c9ec99bc39ac99a", siteswap_2.toAsyncString());
49 | assertEquals(3, siteswap_2.getNumberOfJugglers());
50 | assertEquals(3, siteswap_2.getNumberOfSynchronousHands());
51 | assertEquals(1, siteswap_2.getSynchronousStartPosition());
52 | assertEquals(siteswap_str_2, siteswap_2.toParsableString());
53 |
54 | String siteswap_str_3 = "86277.2.1";
55 | Siteswap siteswap_3 = new Siteswap(siteswap_str_3);
56 | assertEquals("86277", siteswap_3.toAsyncString());
57 | assertEquals(2, siteswap_3.getNumberOfJugglers());
58 | assertEquals(1, siteswap_3.getNumberOfSynchronousHands());
59 | assertEquals(0, siteswap_3.getSynchronousStartPosition());
60 | assertEquals(siteswap_str_1_substring, siteswap_3.toParsableString());
61 |
62 | String siteswap_str_4 = "86277.2";
63 | Siteswap siteswap_4 = new Siteswap(siteswap_str_4);
64 | assertEquals("86277", siteswap_4.toAsyncString());
65 | assertEquals(2, siteswap_4.getNumberOfJugglers());
66 | assertEquals(1, siteswap_4.getNumberOfSynchronousHands());
67 | assertEquals(0, siteswap_4.getSynchronousStartPosition());
68 | assertEquals(siteswap_str_1_substring, siteswap_4.toParsableString());
69 |
70 | String siteswap_str_5 = "86277";
71 | Siteswap siteswap_5 = new Siteswap(siteswap_str_5);
72 | assertEquals("86277", siteswap_5.toAsyncString());
73 | assertEquals(2, siteswap_5.getNumberOfJugglers());
74 | assertEquals(1, siteswap_5.getNumberOfSynchronousHands());
75 | assertEquals(0, siteswap_5.getSynchronousStartPosition());
76 | assertEquals(siteswap_str_1_substring, siteswap_5.toParsableString());
77 |
78 | }
79 |
80 | @Test
81 | public void testMergeSyncSiteswapsFailOnInvalidSiteswap() {
82 | Siteswap s1 = new Siteswap("86277");
83 | Siteswap s2 = new Siteswap("6787a");
84 | Siteswap merged = Siteswap.mergeCompatible(s1, s2);
85 | assertEquals(merged, null);
86 | }
87 |
88 | @Test
89 | public void testMergeSyncSiteswapsFailOnIncompatibility() {
90 | Siteswap s1 = new Siteswap("86277");
91 | Siteswap s2 = new Siteswap("86727");
92 | Siteswap merged = Siteswap.mergeCompatible(s1, s2);
93 | assertEquals(merged, null);
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/DeleteGenerationParametersDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import androidx.fragment.app.DialogFragment;
26 | import androidx.fragment.app.FragmentManager;
27 | import androidx.appcompat.app.AlertDialog;
28 | import android.view.View;
29 | import android.widget.AdapterView;
30 | import android.widget.ArrayAdapter;
31 | import android.widget.ListView;
32 |
33 | import java.io.Serializable;
34 | import java.util.List;
35 |
36 | /**
37 | * Created by tilman on 29.10.17.
38 | */
39 |
40 | public class DeleteGenerationParametersDialog extends DialogFragment {
41 |
42 | private static final String STATE_GENERATION_PARAMETER_ENTITY = "STATE_GENERATION_PARAMETER_ENTITY";
43 | private ListView mListView;
44 | private List mGenerationParameterEntityList;
45 |
46 | @Override
47 | public Dialog onCreateDialog(Bundle savedInstanceState) {
48 |
49 | if(savedInstanceState != null) {
50 | mGenerationParameterEntityList = (List) savedInstanceState.getSerializable(STATE_GENERATION_PARAMETER_ENTITY);
51 | }
52 |
53 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
54 |
55 | builder.setView(R.layout.layout_generation_parameters_list)
56 | .setTitle(getString(R.string.delete_generation_parameters__title))
57 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
58 | @Override
59 | public void onClick(DialogInterface dialog, int which) {
60 |
61 | }
62 | });
63 | final AlertDialog dialog = builder.create();
64 | return dialog;
65 | }
66 |
67 | @Override
68 | public void onStart() {
69 | super.onStart();
70 |
71 | mListView = (ListView) getDialog().findViewById(R.id.generation_parameters_list);
72 | ArrayAdapter adapter = new ArrayAdapter(
73 | getContext(), android.R.layout.simple_list_item_1, mGenerationParameterEntityList);
74 | mListView.setAdapter(adapter);
75 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
76 | @Override
77 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
78 | GenerationParameterEntity generationParameterEntity = ((GenerationParameterEntity) parent.getItemAtPosition(position));
79 | new ConfirmDeleteGenerationParametersDialog().show(getFragmentManager(),
80 | getString(R.string.confirm_delete_generation_parameters__dialog_tag),
81 | generationParameterEntity);
82 | dismiss();
83 | }
84 | });
85 | }
86 |
87 | @Override
88 | public void onSaveInstanceState(Bundle outState) {
89 | super.onSaveInstanceState(outState);
90 |
91 | outState.putSerializable(STATE_GENERATION_PARAMETER_ENTITY, (Serializable) mGenerationParameterEntityList);
92 | }
93 |
94 | @Override
95 | public void onStop() {
96 | super.onStop();
97 | }
98 |
99 | public void show(FragmentManager manager, String tag, List siteswapEntityList) {
100 | mGenerationParameterEntityList = siteswapEntityList;
101 | show(manager, tag);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pattern_filter_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
19 |
20 |
27 |
28 |
34 |
35 |
36 |
41 |
42 |
49 |
50 |
56 |
57 |
58 |
59 |
60 |
65 |
66 |
73 |
74 |
81 |
82 |
83 |
84 |
89 |
90 |
97 |
98 |
104 |
105 |
106 |
107 |
113 |
114 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/LoadGenerationParametersDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import androidx.fragment.app.DialogFragment;
26 | import androidx.fragment.app.FragmentManager;
27 | import androidx.appcompat.app.AlertDialog;
28 | import android.view.View;
29 | import android.widget.AdapterView;
30 | import android.widget.ArrayAdapter;
31 | import android.widget.ListView;
32 |
33 | import java.io.Serializable;
34 | import java.util.List;
35 |
36 | /**
37 | * Created by tilman on 29.10.17.
38 | */
39 |
40 | public class LoadGenerationParametersDialog extends DialogFragment {
41 |
42 | private static final String STATE_GENERATION_PARAMETER_ENTITY = "STATE_GENERATION_PARAMETER_ENTITY";
43 | private ListView mListView;
44 | private List mGenerationParameterEntityList;
45 | private UpdateGenerationParameters updateGenerationParameters;
46 |
47 | public interface UpdateGenerationParameters {
48 | public void updateGenerationParameters(GenerationParameterEntity entity);
49 | }
50 |
51 | @Override
52 | public Dialog onCreateDialog(Bundle savedInstanceState) {
53 |
54 | if(savedInstanceState != null) {
55 | mGenerationParameterEntityList = (List) savedInstanceState.getSerializable(STATE_GENERATION_PARAMETER_ENTITY);
56 | }
57 |
58 | updateGenerationParameters = (UpdateGenerationParameters) getActivity();
59 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
60 |
61 | builder.setView(R.layout.layout_generation_parameters_list)
62 | .setTitle(getString(R.string.load_generation_parameters__title))
63 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
64 | @Override
65 | public void onClick(DialogInterface dialog, int which) {
66 |
67 | }
68 | });
69 | final AlertDialog dialog = builder.create();
70 | return dialog;
71 | }
72 |
73 | @Override
74 | public void onStart() {
75 | super.onStart();
76 |
77 | mListView = (ListView) getDialog().findViewById(R.id.generation_parameters_list);
78 | ArrayAdapter adapter = new ArrayAdapter(
79 | getContext(), android.R.layout.simple_list_item_1, mGenerationParameterEntityList);
80 | mListView.setAdapter(adapter);
81 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
82 | @Override
83 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
84 | GenerationParameterEntity generationParameterEntity = ((GenerationParameterEntity) parent.getItemAtPosition(position));
85 | updateGenerationParameters.updateGenerationParameters(generationParameterEntity);
86 | dismiss();
87 | }
88 | });
89 |
90 |
91 | }
92 |
93 |
94 | @Override
95 | public void onSaveInstanceState(Bundle outState) {
96 | super.onSaveInstanceState(outState);
97 |
98 | outState.putSerializable(STATE_GENERATION_PARAMETER_ENTITY, (Serializable) mGenerationParameterEntityList);
99 | }
100 |
101 | @Override
102 | public void onStop() {
103 | super.onStop();
104 | }
105 |
106 | public void show(FragmentManager manager, String tag, List siteswapEntityList) {
107 | mGenerationParameterEntityList = siteswapEntityList;
108 | show(manager, tag);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/SaveGenerationParametersDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import androidx.fragment.app.DialogFragment;
26 | import androidx.fragment.app.FragmentManager;
27 | import androidx.appcompat.app.AlertDialog;
28 | import android.view.View;
29 | import android.widget.Button;
30 | import android.widget.EditText;
31 |
32 | /**
33 | * Created by tilman on 29.10.17.
34 | */
35 |
36 | public class SaveGenerationParametersDialog extends DialogFragment {
37 |
38 | private static final String STATE_GENERATION_PARAMETER_ENTITY = "STATE_GENERATION_PARAMETER_ENTITY";
39 | private EditText mGenerationParameterNameTextEdit;
40 | private GenerationParameterEntity mGenerationParameterEntity;
41 |
42 | @Override
43 | public Dialog onCreateDialog(Bundle savedInstanceState) {
44 |
45 | if(savedInstanceState != null) {
46 | mGenerationParameterEntity = (GenerationParameterEntity) savedInstanceState.getSerializable(STATE_GENERATION_PARAMETER_ENTITY);
47 | }
48 |
49 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
50 |
51 | builder.setView(R.layout.layout_save_generation_parameters)
52 | .setTitle(getString(R.string.save_generation_parameters__title))
53 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
54 | @Override
55 | public void onClick(DialogInterface dialog, int which) {
56 |
57 | }
58 | }).setPositiveButton(getString(R.string.ok), null);
59 | final AlertDialog dialog = builder.create();
60 | dialog.setOnShowListener(new DialogInterface.OnShowListener() {
61 | @Override
62 | public void onShow(final DialogInterface dialog) {
63 | Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
64 | button.setOnClickListener(new View.OnClickListener() {
65 | @Override
66 | public void onClick(View v) {
67 | mGenerationParameterEntity.setName(mGenerationParameterNameTextEdit.getText().toString());
68 | insertEntityInDatabase();
69 | dialog.dismiss();
70 | }
71 | });
72 | }
73 | });
74 | return dialog;
75 | }
76 |
77 | public void insertEntityInDatabase() {
78 | new Thread(new Runnable() {
79 | @Override
80 | public void run() {
81 | try {
82 | AppDatabase db = AppDatabase.getAppDatabase(getContext());
83 | db.generationParameterDao().insertGenerationParameters(mGenerationParameterEntity);
84 | } catch (android.database.sqlite.SQLiteConstraintException e) {
85 | }
86 | }
87 | }).start();
88 | }
89 |
90 |
91 | @Override
92 | public void onStart() {
93 | super.onStart();
94 | mGenerationParameterNameTextEdit = (EditText) getDialog().findViewById(R.id.generation_parameter_name_text_edit_text_edit);
95 | }
96 |
97 |
98 | @Override
99 | public void onSaveInstanceState(Bundle outState) {
100 | super.onSaveInstanceState(outState);
101 |
102 | outState.putSerializable(STATE_GENERATION_PARAMETER_ENTITY, mGenerationParameterEntity);
103 | }
104 |
105 | @Override
106 | public void onStop() {
107 | super.onStop();
108 | }
109 |
110 | public void show(FragmentManager manager, String tag, GenerationParameterEntity entity) {
111 | mGenerationParameterEntity = entity;
112 | show(manager, tag);
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/ConfirmDeleteGenerationParametersDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import androidx.fragment.app.DialogFragment;
26 | import androidx.fragment.app.FragmentManager;
27 | import androidx.appcompat.app.AlertDialog;
28 | import android.view.View;
29 | import android.widget.Button;
30 | import android.widget.TextView;
31 |
32 | /**
33 | * Created by tilman on 29.10.17.
34 | */
35 |
36 | public class ConfirmDeleteGenerationParametersDialog extends DialogFragment {
37 |
38 | private static final String STATE_GENERATION_PARAMETER_ENTITY = "STATE_GENERATION_PARAMETER_ENTITY";
39 | private TextView mGenerationParametersTextView;
40 | private GenerationParameterEntity mGenerationParameterEntity;
41 |
42 | @Override
43 | public Dialog onCreateDialog(Bundle savedInstanceState) {
44 |
45 | if(savedInstanceState != null) {
46 | mGenerationParameterEntity = (GenerationParameterEntity) savedInstanceState.getSerializable(STATE_GENERATION_PARAMETER_ENTITY);
47 | }
48 |
49 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
50 |
51 | builder.setView(R.layout.layout_confirm_remove_generation_parameter)
52 | .setTitle(getString(R.string.confirm_delete_generation_parameters__title))
53 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
54 | @Override
55 | public void onClick(DialogInterface dialog, int which) {
56 |
57 | }
58 | }).setPositiveButton(getString(R.string.remove), null);
59 | final AlertDialog dialog = builder.create();
60 | dialog.setOnShowListener(new DialogInterface.OnShowListener() {
61 | @Override
62 | public void onShow(final DialogInterface dialog) {
63 | Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
64 | button.setOnClickListener(new View.OnClickListener() {
65 | @Override
66 | public void onClick(View v) {
67 | deleteGenerationParameters();
68 | dialog.dismiss();
69 | }
70 | });
71 | }
72 | });
73 | return dialog;
74 | }
75 |
76 | @Override
77 | public void onStart() {
78 | super.onStart();
79 |
80 | mGenerationParametersTextView = (TextView) getDialog().findViewById(R.id.generation_parameter_text_view);
81 | mGenerationParametersTextView.setText(mGenerationParameterEntity.toString());
82 | }
83 |
84 | public void deleteGenerationParameters() {
85 | new Thread(new Runnable() {
86 | @Override
87 | public void run() {
88 | try {
89 | AppDatabase db = AppDatabase.getAppDatabase(getContext());
90 | db.generationParameterDao().deleteGenerationParameters(mGenerationParameterEntity);
91 | } catch (android.database.sqlite.SQLiteConstraintException e) {
92 | }
93 | }
94 | }).start();
95 | }
96 |
97 | @Override
98 | public void onSaveInstanceState(Bundle outState) {
99 | super.onSaveInstanceState(outState);
100 |
101 | outState.putSerializable(STATE_GENERATION_PARAMETER_ENTITY, mGenerationParameterEntity);
102 | }
103 |
104 | @Override
105 | public void onStop() {
106 | super.onStop();
107 | }
108 |
109 | public void show(FragmentManager manager, String tag, GenerationParameterEntity generationParameterEntity) {
110 | mGenerationParameterEntity = generationParameterEntity;
111 | show(manager, tag);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/app/src/test/java/siteswaplib/NumberFilterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import org.junit.Before;
22 | import org.junit.Test;
23 |
24 | import java.util.Arrays;
25 | import java.util.LinkedList;
26 | import java.util.List;
27 |
28 | import static org.junit.Assert.*;
29 |
30 | public class NumberFilterTest {
31 |
32 | @Test
33 | public void testCreateSynchronousFromString() {
34 | String expected = new String("6p");
35 | NumberFilter filter = new NumberFilter(expected, NumberFilter.Type.EQUAL, 1, 2);
36 | assertEquals(expected, filter.getFilterValue().toString());
37 | }
38 |
39 | @Test
40 | public void testEquals() {
41 | NumberFilter filter1 = new NumberFilter("6p", NumberFilter.Type.EQUAL, 1, 2);
42 | NumberFilter filter2 = new NumberFilter("6p", NumberFilter.Type.EQUAL, 1, 2);
43 | NumberFilter filter3 = new NumberFilter("6", NumberFilter.Type.EQUAL, 1, 2);
44 | NumberFilter filter4 = new NumberFilter("8p", NumberFilter.Type.EQUAL, 1, 2);
45 | assertEquals(filter1, filter2);
46 | assertNotEquals(filter1, filter3);
47 | assertNotEquals(filter1, filter4);
48 | }
49 |
50 | @Test
51 | public void testSynchronousPassConversion() {
52 | NumberFilter filter = new NumberFilter("9p", NumberFilter.Type.EQUAL, 1, 3);
53 | assertArrayEquals(new int[]{10, 11}, filter.getFilterValue().getValues(0));
54 | assertArrayEquals(new int[]{8, 10}, filter.getFilterValue().getValues(1));
55 | assertArrayEquals(new int[]{7, 8}, filter.getFilterValue().getValues(2));
56 | }
57 |
58 | @Test
59 | public void testCountValue() {
60 | NumberFilter filter1 = new NumberFilter("9p", NumberFilter.Type.EQUAL, 1, 3);
61 | NumberFilter filter2 = new NumberFilter("9", NumberFilter.Type.EQUAL, 1, 3);
62 | Siteswap siteswap1 = new Siteswap("89a4945", 3);
63 | Siteswap siteswap2 = new Siteswap("8859a57889a059a49a5919a3783", 3);
64 | siteswap1.setNumberOfSynchronousHands(3);
65 | siteswap2.setNumberOfSynchronousHands(3);
66 | siteswap2.setSynchronousStartPosition(2);
67 | int expected1 = 4;
68 | int expected2 = 9;
69 | int expected3 = 6; // Attention: counted over global period length
70 | int expected4 = 6;
71 | assertEquals(expected1, siteswap1.countFilterValue(filter1.getFilterValue()));
72 | assertEquals(expected2, siteswap2.countFilterValue(filter1.getFilterValue()));
73 | assertEquals(expected3, siteswap1.countFilterValue(filter2.getFilterValue()));
74 | assertEquals(expected4, siteswap2.countFilterValue(filter2.getFilterValue()));
75 | }
76 |
77 | @Test
78 | public void testParsableStringConversion() {
79 | NumberFilter filter1 = new NumberFilter("9p", NumberFilter.Type.EQUAL, 1, 3);
80 | NumberFilter filter2 = new NumberFilter("9", NumberFilter.Type.EQUAL, 1, 3);
81 | NumberFilter filter3 = new NumberFilter("5", NumberFilter.Type.GREATER_EQUAL, 3, 1);
82 | NumberFilter filter4 = new NumberFilter("a", NumberFilter.Type.SMALLER_EQUAL, 15, 1);
83 |
84 | String filter1str = filter1.toParsableString();
85 | String filter2str = filter2.toParsableString();
86 | String filter3str = filter3.toParsableString();
87 | String filter4str = filter4.toParsableString();
88 |
89 | NumberFilter filter1conv = new NumberFilter().fromParsableString(filter1str);
90 | NumberFilter filter2conv = new NumberFilter().fromParsableString(filter2str);
91 | NumberFilter filter3conv = new NumberFilter().fromParsableString(filter3str);
92 | NumberFilter filter4conv = new NumberFilter().fromParsableString(filter4str);
93 |
94 | assertEquals(filter1, filter1conv);
95 | assertEquals(filter2, filter2conv);
96 | assertEquals(filter3, filter3conv);
97 | assertEquals(filter4, filter4conv);
98 |
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/SiteswapGenerationFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 | import android.app.Activity;
22 | import android.content.Context;
23 | import android.os.AsyncTask;
24 | import android.os.Bundle;
25 | import android.app.Fragment;
26 |
27 | import siteswaplib.SiteswapGenerator;
28 |
29 | /**
30 | * Created by tilman on 22.11.17.
31 | */
32 |
33 | public class SiteswapGenerationFragment extends Fragment {
34 |
35 | interface SiteswapGenerationCallbacks {
36 | SiteswapGenerator getSiteswapGenerator();
37 | void onGenerationComplete(SiteswapGenerator generator, SiteswapGenerator.Status status);
38 | }
39 |
40 | private SiteswapGenerationCallbacks mCallbacks;
41 | private SiteswapGenerationTask mTask;
42 |
43 | @Override
44 | public void onAttach(Context context) {
45 | super.onAttach(context);
46 | mCallbacks = (SiteswapGenerationCallbacks) context;
47 | }
48 |
49 | @Override
50 | public void onAttach(Activity context) {
51 | super.onAttach(context);
52 | mCallbacks = (SiteswapGenerationCallbacks) context;
53 | }
54 |
55 | @Override
56 | public void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 |
59 | setRetainInstance(true);
60 |
61 | // Create and execute the background task.
62 | mTask = new SiteswapGenerationTask();
63 | mTask.execute();
64 | }
65 |
66 | /**
67 | * Set the callback to null so we don't accidentally leak the
68 | * Activity instance.
69 | */
70 | @Override
71 | public void onDetach() {
72 | super.onDetach();
73 | mCallbacks = null;
74 | }
75 |
76 | @Override
77 | public void onDestroy() {
78 | super.onDestroy();
79 | mTask.mGenerator.cancelGeneration();
80 | mTask.cancel(true);
81 | mTask.mGenerator = null;
82 | mTask = null;
83 | }
84 |
85 | public void getSiteswapGenerator() {
86 | if (isError()) {
87 | mTask = new SiteswapGenerationTask();
88 | mTask.execute();
89 | return;
90 | }
91 | if (mTask.getStatus() == AsyncTask.Status.FINISHED) {
92 | mTask.generationComplete();
93 | }
94 | }
95 |
96 | public boolean isError() {
97 | if(mTask.mGenerator == null)
98 | return true;
99 | return mTask.mIsError;
100 | }
101 |
102 | private class SiteswapGenerationTask extends AsyncTask {
103 |
104 | private SiteswapGenerator mGenerator;
105 | private SiteswapGenerator.Status mGenerationStatus;
106 | private boolean mIsError = false;
107 |
108 | @Override
109 | protected void onPreExecute() {
110 | if (mCallbacks != null) {
111 | mGenerator = mCallbacks.getSiteswapGenerator();
112 | }
113 | }
114 |
115 | @Override
116 | protected Void doInBackground(Void... ignore) {
117 | try {
118 | mGenerationStatus = mGenerator.generateSiteswaps();
119 | }
120 | catch (java.lang.RuntimeException e) {
121 | mIsError = true;
122 | // This exceptions occurs, if the Andoid system recycles the memory of the
123 | // activity, but doInBackgound is still executed in background.
124 | }
125 | return null;
126 | }
127 |
128 | @Override
129 | protected void onPostExecute(Void ignore) {
130 |
131 | generationComplete();
132 | }
133 |
134 | private void generationComplete() {
135 | if (mIsError) {
136 | return;
137 | }
138 | if (mCallbacks != null) {
139 | mCallbacks.onGenerationComplete(mGenerator, mGenerationStatus);
140 | }
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/NamedSiteswaps.java:
--------------------------------------------------------------------------------
1 | package siteswaplib;
2 |
3 |
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | public class NamedSiteswaps {
8 |
9 |
10 | static final private List namedSiteswapsList = Arrays.asList(
11 | new NamedSiteswap("86722", 2, "5 club not why"),
12 | new NamedSiteswap("86227", 2, "5 club why not"),
13 | new NamedSiteswap("86867", 2, "5 count popcorn (44)"),
14 | new NamedSiteswap("a6667", 2, "5 count popcorn"),
15 | new NamedSiteswap("9964966", 2, "7 club Jim's 2 count"),
16 | new NamedSiteswap("9964786", 2, "7 club Jim's 2 count (variation)"),
17 | new NamedSiteswap("9784966", 2, "7 club Jim's 2 count (variation)"),
18 | new NamedSiteswap("9784786", 2, "7 club Jim's 2 count (variation)"),
19 | new NamedSiteswap("9969268", 2, "7 club maybe (1)"),
20 | new NamedSiteswap("9968296", 2, "7 club maybe (2)"),
21 | new NamedSiteswap("9968278", 2, "7 club maybe (variation)"),
22 | new NamedSiteswap("7", 2, "7 club one count"),
23 | new NamedSiteswap("9962968", 2, "7 club not why"),
24 | new NamedSiteswap("9962788", 2, "7 club not why (variation)"),
25 | new NamedSiteswap("9782968", 2, "7 club not why (variation)"),
26 | new NamedSiteswap("9782788", 2, "7 club not why (variation)"),
27 | new NamedSiteswap("966", 2, "7 club three count"),
28 | new NamedSiteswap("7786867", 2, "7 club Vitoria"),
29 | new NamedSiteswap("9968926", 2, "7 club why not"),
30 | new NamedSiteswap("9788926", 2, "7 club why not (variation)"),
31 | new NamedSiteswap("8686867", 2, "7 count popcorn"),
32 | new NamedSiteswap("9668686", 2, "7 count popcorn (variation)"),
33 | new NamedSiteswap("a666786", 2, "7 count popcorn (variation)"),
34 | new NamedSiteswap("a666867", 2, "7 count popcorn (variation)"),
35 | new NamedSiteswap("a666966", 2, "7 count popcorn (variation)"),
36 | new NamedSiteswap("996", 2, "8 club pps"),
37 | new NamedSiteswap("9797888", 2, "8 club Vitoria"),
38 | new NamedSiteswap("9", 2, "9 club one count"),
39 | new NamedSiteswap("a2747", 2, "aa7 Warmup Pattern"),
40 | new NamedSiteswap("9667867", 2, "Aspirin"),
41 | new NamedSiteswap("756", 2, "baby dragon; zap opus 1; holy hand-grenade"),
42 | new NamedSiteswap("9968978", 2, "Clean Finish"),
43 | new NamedSiteswap("726", 2, "coconut laden swallow"),
44 | new NamedSiteswap("9789268", 2, "Das Schirche"),
45 | new NamedSiteswap("7796686", 2, "Das Schöne"),
46 | new NamedSiteswap("945", 2, "dragon; black beast of aaaarg..."),
47 | new NamedSiteswap("7742744", 2, "Flipalot"),
48 | new NamedSiteswap("867", 2, "French 3 count"),
49 | new NamedSiteswap("86777", 2, "Funky Bookends"),
50 | new NamedSiteswap("942", 2, "glass elevator"),
51 | new NamedSiteswap("9792688", 2, "Good Morning"),
52 | new NamedSiteswap("996882777", 2, "Great Chaos"),
53 | new NamedSiteswap("8882225", 2, "Heffalot"),
54 | new NamedSiteswap("975", 2, "Holy Grail; zap opus two"),
55 | new NamedSiteswap("77222", 2, "inverted parsnip"),
56 | new NamedSiteswap("75724", 2, "Kaatzi"),
57 | new NamedSiteswap("645", 2, "killer bunny"),
58 | new NamedSiteswap("774", 2, "Jim's 1 count (async)"),
59 | new NamedSiteswap("77466", 2, "Jim's 2 count (async)"),
60 | new NamedSiteswap("77772", 2, "Martin's one count (async)"),
61 | new NamedSiteswap("86727", 2, "maybe"),
62 | new NamedSiteswap("96627", 2, "maybe not"),
63 | new NamedSiteswap("7777266", 2, "Mild Madness (async)"),
64 | new NamedSiteswap("9789788", 2, "Milk Duds"),
65 | new NamedSiteswap("9647772", 2, "Odnom"),
66 | new NamedSiteswap("9969968", 2, "Ollerup"),
67 | new NamedSiteswap("96672", 2, "not likely"),
68 | new NamedSiteswap("86772", 2, "not why"),
69 | new NamedSiteswap("77722", 2, "parsnip"),
70 | new NamedSiteswap("99494", 2, "Peanut Flips"),
71 | new NamedSiteswap("9669667", 2, "Placebo"),
72 | new NamedSiteswap("9969788", 2, "Poem"),
73 | new NamedSiteswap("9968897", 2, "Real Fake Clean Finish"),
74 | new NamedSiteswap("7284554", 2, "The forgotten Flip"),
75 | new NamedSiteswap("7788289247772", 2, "The missing elevator button"),
76 | new NamedSiteswap("97428", 2, "The One to Concentrate"),
77 | new NamedSiteswap("86277", 2, "why not")
78 | );
79 |
80 | static public List getListOfNamedSiteswaps() {
81 | return namedSiteswapsList;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/ConfirmRemoveFavoriteDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import androidx.fragment.app.DialogFragment;
26 | import androidx.fragment.app.FragmentManager;
27 | import androidx.appcompat.app.AlertDialog;
28 | import android.view.View;
29 | import android.widget.Button;
30 | import android.widget.TextView;
31 | import android.widget.Toast;
32 |
33 | /**
34 | * Created by tilman on 29.10.17.
35 | */
36 |
37 | public class ConfirmRemoveFavoriteDialog extends DialogFragment {
38 |
39 | private static final String STATE_SITESWAP_ENTIIY = "STATE_SITESWAP_ENTIIY";
40 | private TextView mFavoriteTextView;
41 | private SiteswapEntity mSiteswapEntity;
42 |
43 | @Override
44 | public Dialog onCreateDialog(Bundle savedInstanceState) {
45 |
46 | if(savedInstanceState != null) {
47 | mSiteswapEntity = (SiteswapEntity) savedInstanceState.getSerializable(STATE_SITESWAP_ENTIIY);
48 | }
49 |
50 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
51 |
52 | builder.setView(R.layout.layout_confirm_remove_favorite)
53 | .setTitle(getString(R.string.confirm_remove_favorite__title))
54 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
55 | @Override
56 | public void onClick(DialogInterface dialog, int which) {
57 |
58 | }
59 | }).setPositiveButton(getString(R.string.remove), null);
60 | final AlertDialog dialog = builder.create();
61 | dialog.setOnShowListener(new DialogInterface.OnShowListener() {
62 | @Override
63 | public void onShow(final DialogInterface dialog) {
64 | Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
65 | button.setOnClickListener(new View.OnClickListener() {
66 | @Override
67 | public void onClick(View v) {
68 | deleteSiteswapFromFavorites();
69 | dialog.dismiss();
70 | }
71 | });
72 | }
73 | });
74 | return dialog;
75 | }
76 |
77 | @Override
78 | public void onStart() {
79 | super.onStart();
80 |
81 | mFavoriteTextView = (TextView) getDialog().findViewById(R.id.favorite_text_view);
82 | mFavoriteTextView.setText(
83 | getString(R.string.confirm_remove_favorite__name) + " " + mSiteswapEntity.getName() + "\n" +
84 | getString(R.string.confirm_remove_favorite__jugglers) + " " + mSiteswapEntity.getJuggerNames() + "\n" +
85 | getString(R.string.confirm_remove_favorite__location) + " " + mSiteswapEntity.getLocation() + "\n" +
86 | getString(R.string.confirm_remove_favorite__date) + " " + mSiteswapEntity.getDate());
87 |
88 | }
89 |
90 |
91 | @Override
92 | public void onSaveInstanceState(Bundle outState) {
93 | super.onSaveInstanceState(outState);
94 |
95 | outState.putSerializable(STATE_SITESWAP_ENTIIY, mSiteswapEntity);
96 | }
97 |
98 | @Override
99 | public void onStop() {
100 | super.onStop();
101 | }
102 |
103 | private void deleteSiteswapFromFavorites() {
104 |
105 | new Thread(new Runnable() {
106 | @Override
107 | public void run() {
108 | try {
109 | AppDatabase db = AppDatabase.getAppDatabase(getContext());
110 | FavoriteDao dao = db.siteswapDao();
111 | dao.deleteFavorite(mSiteswapEntity);
112 | getActivity().runOnUiThread(new Runnable() {
113 | @Override
114 | public void run() {
115 | Toast.makeText(getContext(), getString(R.string.detailed_siteswap__toast_favorite_removed), Toast.LENGTH_LONG).show();
116 | }
117 | });
118 | } catch (android.database.sqlite.SQLiteConstraintException e) {
119 | } catch (NullPointerException e) {
120 | }
121 | }
122 | }).start();
123 |
124 | }
125 |
126 | public void show(FragmentManager manager, String tag, SiteswapEntity siteswapEntity) {
127 | mSiteswapEntity = siteswapEntity;
128 | show(manager, tag);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/EnterSiteswapDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Dialog;
23 | import android.content.DialogInterface;
24 | import android.content.Intent;
25 | import android.os.Bundle;
26 | import androidx.fragment.app.DialogFragment;
27 | import androidx.fragment.app.FragmentManager;
28 | import androidx.appcompat.app.AlertDialog;
29 | import android.view.View;
30 | import android.widget.Button;
31 | import android.widget.CheckBox;
32 | import android.widget.EditText;
33 |
34 | import siteswaplib.Siteswap;
35 |
36 | /**
37 | * Created by tilman on 29.10.17.
38 | */
39 |
40 | public class EnterSiteswapDialog extends DialogFragment {
41 |
42 | private EditText mSiteswapTextEdit;
43 | private EditText mNumberOfJugglersTextEdit;
44 | private CheckBox mIsSynchronouscheckbox;
45 | private int mNumberOfJugglersDefault;
46 | private boolean mIsSyncDefault;
47 |
48 | @Override
49 | public Dialog onCreateDialog(Bundle savedInstanceState) {
50 |
51 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
52 |
53 | builder.setView(R.layout.layout_enter_siteswap)
54 | .setTitle(getString(R.string.enter_siteswap__title))
55 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
56 | @Override
57 | public void onClick(DialogInterface dialog, int which) {
58 |
59 | }
60 | }).setPositiveButton(getString(R.string.ok), null);
61 | final AlertDialog dialog = builder.create();
62 | dialog.setOnShowListener(new DialogInterface.OnShowListener() {
63 | @Override
64 | public void onShow(final DialogInterface dialog) {
65 | Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
66 | button.setOnClickListener(new View.OnClickListener() {
67 | @Override
68 | public void onClick(View v) {
69 | if (validateAndShowSiteswap())
70 | dialog.dismiss();
71 | }
72 | });
73 | }
74 | });
75 | return dialog;
76 | }
77 |
78 | @Override
79 | public void onStart() {
80 | super.onStart();
81 |
82 | mSiteswapTextEdit = (EditText) getDialog().findViewById(R.id.enter_siteswap_siteswap_text_edit);
83 | mNumberOfJugglersTextEdit = (EditText) getDialog().findViewById(R.id.enter_siteswap_number_of_jugglers_text_edit);
84 | mIsSynchronouscheckbox = (CheckBox) getDialog().findViewById(R.id.enter_siteswap_sync_mode_checkbox);
85 | mNumberOfJugglersTextEdit.setText(String.valueOf(mNumberOfJugglersDefault));
86 | mIsSynchronouscheckbox.setChecked(mIsSyncDefault);
87 | }
88 |
89 |
90 | @Override
91 | public void onStop() {
92 | super.onStop();
93 | }
94 |
95 | private boolean validateAndShowSiteswap() {
96 | try {
97 | int numberOfJugglers = Integer.valueOf(mNumberOfJugglersTextEdit.getText().toString());
98 | boolean isSync = mIsSynchronouscheckbox.isChecked();
99 | int numberOfSynchronousHands = 1;
100 | if (isSync) {
101 | numberOfSynchronousHands = numberOfJugglers;
102 | }
103 | Siteswap siteswap = new Siteswap(mSiteswapTextEdit.getText().toString(), numberOfJugglers);
104 | siteswap.setNumberOfSynchronousHands(numberOfSynchronousHands);
105 | if (!siteswap.isValid() )
106 | throw new IllegalArgumentException(siteswap.toString());
107 | Intent intent = new Intent(getContext(), DetailedSiteswapActivity.class);
108 | intent.putExtra(getString(R.string.intent_detailed_siteswap_view__siteswap), siteswap);
109 | startActivity(intent);
110 | return true;
111 | }
112 | catch (IllegalArgumentException e) {
113 | AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
114 | builder.setMessage(getString(R.string.main_activity__invalid_site_swap) + e.getMessage())
115 | .setNeutralButton(getString(R.string.back), null);
116 | builder.create().show();
117 | }
118 | return false;
119 | }
120 |
121 | public void show(FragmentManager manager, String tag, int numberOfJugglers,
122 | boolean isSynchrounous) {
123 | mNumberOfJugglersDefault = numberOfJugglers;
124 | mIsSyncDefault = isSynchrounous;
125 | show(manager, tag);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/GenerationParameterEntity.java:
--------------------------------------------------------------------------------
1 | package namlit.siteswapgenerator;
2 |
3 | import androidx.room.ColumnInfo;
4 | import androidx.room.Entity;
5 | import androidx.room.PrimaryKey;
6 | import androidx.annotation.NonNull;
7 |
8 | import java.io.Serializable;
9 |
10 | import siteswaplib.FilterList;
11 | import siteswaplib.Siteswap;
12 |
13 | @Entity(tableName = "generation_parameters")
14 | public class GenerationParameterEntity implements Serializable {
15 |
16 | @PrimaryKey(autoGenerate = true)
17 | @ColumnInfo(name = "uid")
18 | private int uid;
19 |
20 | @ColumnInfo(name = "name")
21 | private String name;
22 |
23 | @ColumnInfo(name = "numberOfObjects")
24 | private int numberOfObjects;
25 |
26 | @ColumnInfo(name = "periodLength")
27 | private int periodLength;
28 |
29 | @ColumnInfo(name = "maxThrow")
30 | private int maxThrow;
31 |
32 | @ColumnInfo(name = "minThrow")
33 | private int minThrow;
34 |
35 | @ColumnInfo(name = "numberOfJugglers")
36 | private int numberOfJugglers;
37 |
38 | @ColumnInfo(name = "maxResults")
39 | private int maxResults;
40 |
41 | @ColumnInfo(name = "timeout")
42 | private int timeout;
43 |
44 | @ColumnInfo(name = "isSynchronous")
45 | private boolean isSynchronous;
46 |
47 | @ColumnInfo(name = "isRandomMode")
48 | private boolean isRandomMode;
49 |
50 | @ColumnInfo(name = "isZips")
51 | private boolean isZips;
52 |
53 | @ColumnInfo(name = "isZaps")
54 | private boolean isZaps;
55 |
56 | @ColumnInfo(name = "isHolds")
57 | private boolean isHolds;
58 |
59 | @ColumnInfo(name = "filterListString")
60 | private String filterListString;
61 |
62 | public GenerationParameterEntity() {
63 | name = "";
64 | numberOfObjects = 7;
65 | periodLength = 5;
66 | maxThrow = 10;
67 | minThrow = 2;
68 | numberOfJugglers = 2;
69 | maxResults = 100;
70 | timeout = 5;
71 | isSynchronous = false;
72 | isRandomMode = false;
73 | isZips = false;
74 | isZaps = false;
75 | isHolds = false;
76 | setFilterList(new FilterList(numberOfJugglers, 1));
77 | }
78 |
79 | public int getUid() {
80 | return uid;
81 | }
82 |
83 | public void setUid(int uid) {
84 | this.uid = uid;
85 | }
86 |
87 | public int getNumberOfObjects() {
88 | return numberOfObjects;
89 | }
90 |
91 | public void setNumberOfObjects(int numberOfObjects) {
92 | this.numberOfObjects = numberOfObjects;
93 | }
94 |
95 | public int getPeriodLength() {
96 | return periodLength;
97 | }
98 |
99 | public void setPeriodLength(int periodLength) {
100 | this.periodLength = periodLength;
101 | }
102 |
103 | public int getMaxThrow() {
104 | return maxThrow;
105 | }
106 |
107 | public void setMaxThrow(int maxThrow) {
108 | this.maxThrow = maxThrow;
109 | }
110 |
111 | public int getMinThrow() {
112 | return minThrow;
113 | }
114 |
115 | public void setMinThrow(int minThrow) {
116 | this.minThrow = minThrow;
117 | }
118 |
119 | public int getNumberOfJugglers() {
120 | return numberOfJugglers;
121 | }
122 |
123 | public void setNumberOfJugglers(int numberOfJugglers) {
124 | this.numberOfJugglers = numberOfJugglers;
125 | }
126 |
127 | public int getMaxResults() {
128 | return maxResults;
129 | }
130 |
131 | public void setMaxResults(int maxResults) {
132 | this.maxResults = maxResults;
133 | }
134 |
135 | public int getTimeout() {
136 | return timeout;
137 | }
138 |
139 | public void setTimeout(int timeout) {
140 | this.timeout = timeout;
141 | }
142 |
143 | public boolean isSynchronous() {
144 | return isSynchronous;
145 | }
146 |
147 | public void setSynchronous(boolean is_synchronous) {
148 | this.isSynchronous = is_synchronous;
149 | }
150 |
151 | public boolean isRandomMode() {
152 | return isRandomMode;
153 | }
154 |
155 | public void setRandomMode(boolean is_random_mode) {
156 | this.isRandomMode = is_random_mode;
157 | }
158 |
159 | public boolean isZips() {
160 | return isZips;
161 | }
162 |
163 | public void setZips(boolean zips) {
164 | isZips = zips;
165 | }
166 |
167 | public boolean isZaps() {
168 | return isZaps;
169 | }
170 |
171 | public void setZaps(boolean zaps) {
172 | isZaps = zaps;
173 | }
174 |
175 | public boolean isHolds() {
176 | return isHolds;
177 | }
178 |
179 | public void setHolds(boolean holds) {
180 | isHolds = holds;
181 | }
182 |
183 | public void setFilterListString(String filterListString) {
184 | this.filterListString = filterListString;
185 | }
186 |
187 | public String getFilterListString() {
188 | return filterListString;
189 | }
190 |
191 | public void setFilterList(FilterList filter_list) {
192 | setFilterListString(filter_list.toParsableString());
193 | }
194 |
195 | public String getName() {
196 | return name;
197 | }
198 |
199 | public void setName(String name) {
200 | this.name = name;
201 | }
202 |
203 | public Siteswap toSiteswap() {
204 | Siteswap siteswap = new Siteswap(getName());
205 | return siteswap;
206 | }
207 |
208 | @Override
209 | public String toString() {
210 | return getName();
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/app/schemas/namlit.siteswapgenerator.AppDatabase/1.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 1,
5 | "identityHash": "154b1659e9cecece6224a8eb7f620019",
6 | "entities": [
7 | {
8 | "tableName": "favorites",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `siteswap` TEXT, `name` TEXT, `juggler_names` TEXT, `location` TEXT, `date` TEXT)",
10 | "fields": [
11 | {
12 | "fieldPath": "uid",
13 | "columnName": "uid",
14 | "affinity": "INTEGER",
15 | "notNull": true
16 | },
17 | {
18 | "fieldPath": "siteswap",
19 | "columnName": "siteswap",
20 | "affinity": "TEXT",
21 | "notNull": false
22 | },
23 | {
24 | "fieldPath": "name",
25 | "columnName": "name",
26 | "affinity": "TEXT",
27 | "notNull": false
28 | },
29 | {
30 | "fieldPath": "juggerNames",
31 | "columnName": "juggler_names",
32 | "affinity": "TEXT",
33 | "notNull": false
34 | },
35 | {
36 | "fieldPath": "location",
37 | "columnName": "location",
38 | "affinity": "TEXT",
39 | "notNull": false
40 | },
41 | {
42 | "fieldPath": "date",
43 | "columnName": "date",
44 | "affinity": "TEXT",
45 | "notNull": false
46 | }
47 | ],
48 | "primaryKey": {
49 | "columnNames": [
50 | "uid"
51 | ],
52 | "autoGenerate": true
53 | },
54 | "indices": [],
55 | "foreignKeys": []
56 | },
57 | {
58 | "tableName": "generation_parameters",
59 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `numberOfObjects` INTEGER NOT NULL, `periodLength` INTEGER NOT NULL, `maxThrow` INTEGER NOT NULL, `minThrow` INTEGER NOT NULL, `numberOfJugglers` INTEGER NOT NULL, `maxResults` INTEGER NOT NULL, `timeout` INTEGER NOT NULL, `isSynchronous` INTEGER NOT NULL, `isRandomMode` INTEGER NOT NULL, `isZips` INTEGER NOT NULL, `isZaps` INTEGER NOT NULL, `isHolds` INTEGER NOT NULL, `filterListString` TEXT)",
60 | "fields": [
61 | {
62 | "fieldPath": "uid",
63 | "columnName": "uid",
64 | "affinity": "INTEGER",
65 | "notNull": true
66 | },
67 | {
68 | "fieldPath": "name",
69 | "columnName": "name",
70 | "affinity": "TEXT",
71 | "notNull": false
72 | },
73 | {
74 | "fieldPath": "numberOfObjects",
75 | "columnName": "numberOfObjects",
76 | "affinity": "INTEGER",
77 | "notNull": true
78 | },
79 | {
80 | "fieldPath": "periodLength",
81 | "columnName": "periodLength",
82 | "affinity": "INTEGER",
83 | "notNull": true
84 | },
85 | {
86 | "fieldPath": "maxThrow",
87 | "columnName": "maxThrow",
88 | "affinity": "INTEGER",
89 | "notNull": true
90 | },
91 | {
92 | "fieldPath": "minThrow",
93 | "columnName": "minThrow",
94 | "affinity": "INTEGER",
95 | "notNull": true
96 | },
97 | {
98 | "fieldPath": "numberOfJugglers",
99 | "columnName": "numberOfJugglers",
100 | "affinity": "INTEGER",
101 | "notNull": true
102 | },
103 | {
104 | "fieldPath": "maxResults",
105 | "columnName": "maxResults",
106 | "affinity": "INTEGER",
107 | "notNull": true
108 | },
109 | {
110 | "fieldPath": "timeout",
111 | "columnName": "timeout",
112 | "affinity": "INTEGER",
113 | "notNull": true
114 | },
115 | {
116 | "fieldPath": "isSynchronous",
117 | "columnName": "isSynchronous",
118 | "affinity": "INTEGER",
119 | "notNull": true
120 | },
121 | {
122 | "fieldPath": "isRandomMode",
123 | "columnName": "isRandomMode",
124 | "affinity": "INTEGER",
125 | "notNull": true
126 | },
127 | {
128 | "fieldPath": "isZips",
129 | "columnName": "isZips",
130 | "affinity": "INTEGER",
131 | "notNull": true
132 | },
133 | {
134 | "fieldPath": "isZaps",
135 | "columnName": "isZaps",
136 | "affinity": "INTEGER",
137 | "notNull": true
138 | },
139 | {
140 | "fieldPath": "isHolds",
141 | "columnName": "isHolds",
142 | "affinity": "INTEGER",
143 | "notNull": true
144 | },
145 | {
146 | "fieldPath": "filterListString",
147 | "columnName": "filterListString",
148 | "affinity": "TEXT",
149 | "notNull": false
150 | }
151 | ],
152 | "primaryKey": {
153 | "columnNames": [
154 | "uid"
155 | ],
156 | "autoGenerate": true
157 | },
158 | "indices": [],
159 | "foreignKeys": []
160 | }
161 | ],
162 | "setupQueries": [
163 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
164 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"154b1659e9cecece6224a8eb7f620019\")"
165 | ]
166 | }
167 | }
--------------------------------------------------------------------------------
/app/schemas/namlit.siteswapgenerator.AppDatabase/2.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 2,
5 | "identityHash": "154b1659e9cecece6224a8eb7f620019",
6 | "entities": [
7 | {
8 | "tableName": "favorites",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `siteswap` TEXT, `name` TEXT, `juggler_names` TEXT, `location` TEXT, `date` TEXT)",
10 | "fields": [
11 | {
12 | "fieldPath": "uid",
13 | "columnName": "uid",
14 | "affinity": "INTEGER",
15 | "notNull": true
16 | },
17 | {
18 | "fieldPath": "siteswap",
19 | "columnName": "siteswap",
20 | "affinity": "TEXT",
21 | "notNull": false
22 | },
23 | {
24 | "fieldPath": "name",
25 | "columnName": "name",
26 | "affinity": "TEXT",
27 | "notNull": false
28 | },
29 | {
30 | "fieldPath": "juggerNames",
31 | "columnName": "juggler_names",
32 | "affinity": "TEXT",
33 | "notNull": false
34 | },
35 | {
36 | "fieldPath": "location",
37 | "columnName": "location",
38 | "affinity": "TEXT",
39 | "notNull": false
40 | },
41 | {
42 | "fieldPath": "date",
43 | "columnName": "date",
44 | "affinity": "TEXT",
45 | "notNull": false
46 | }
47 | ],
48 | "primaryKey": {
49 | "columnNames": [
50 | "uid"
51 | ],
52 | "autoGenerate": true
53 | },
54 | "indices": [],
55 | "foreignKeys": []
56 | },
57 | {
58 | "tableName": "generation_parameters",
59 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `numberOfObjects` INTEGER NOT NULL, `periodLength` INTEGER NOT NULL, `maxThrow` INTEGER NOT NULL, `minThrow` INTEGER NOT NULL, `numberOfJugglers` INTEGER NOT NULL, `maxResults` INTEGER NOT NULL, `timeout` INTEGER NOT NULL, `isSynchronous` INTEGER NOT NULL, `isRandomMode` INTEGER NOT NULL, `isZips` INTEGER NOT NULL, `isZaps` INTEGER NOT NULL, `isHolds` INTEGER NOT NULL, `filterListString` TEXT)",
60 | "fields": [
61 | {
62 | "fieldPath": "uid",
63 | "columnName": "uid",
64 | "affinity": "INTEGER",
65 | "notNull": true
66 | },
67 | {
68 | "fieldPath": "name",
69 | "columnName": "name",
70 | "affinity": "TEXT",
71 | "notNull": false
72 | },
73 | {
74 | "fieldPath": "numberOfObjects",
75 | "columnName": "numberOfObjects",
76 | "affinity": "INTEGER",
77 | "notNull": true
78 | },
79 | {
80 | "fieldPath": "periodLength",
81 | "columnName": "periodLength",
82 | "affinity": "INTEGER",
83 | "notNull": true
84 | },
85 | {
86 | "fieldPath": "maxThrow",
87 | "columnName": "maxThrow",
88 | "affinity": "INTEGER",
89 | "notNull": true
90 | },
91 | {
92 | "fieldPath": "minThrow",
93 | "columnName": "minThrow",
94 | "affinity": "INTEGER",
95 | "notNull": true
96 | },
97 | {
98 | "fieldPath": "numberOfJugglers",
99 | "columnName": "numberOfJugglers",
100 | "affinity": "INTEGER",
101 | "notNull": true
102 | },
103 | {
104 | "fieldPath": "maxResults",
105 | "columnName": "maxResults",
106 | "affinity": "INTEGER",
107 | "notNull": true
108 | },
109 | {
110 | "fieldPath": "timeout",
111 | "columnName": "timeout",
112 | "affinity": "INTEGER",
113 | "notNull": true
114 | },
115 | {
116 | "fieldPath": "isSynchronous",
117 | "columnName": "isSynchronous",
118 | "affinity": "INTEGER",
119 | "notNull": true
120 | },
121 | {
122 | "fieldPath": "isRandomMode",
123 | "columnName": "isRandomMode",
124 | "affinity": "INTEGER",
125 | "notNull": true
126 | },
127 | {
128 | "fieldPath": "isZips",
129 | "columnName": "isZips",
130 | "affinity": "INTEGER",
131 | "notNull": true
132 | },
133 | {
134 | "fieldPath": "isZaps",
135 | "columnName": "isZaps",
136 | "affinity": "INTEGER",
137 | "notNull": true
138 | },
139 | {
140 | "fieldPath": "isHolds",
141 | "columnName": "isHolds",
142 | "affinity": "INTEGER",
143 | "notNull": true
144 | },
145 | {
146 | "fieldPath": "filterListString",
147 | "columnName": "filterListString",
148 | "affinity": "TEXT",
149 | "notNull": false
150 | }
151 | ],
152 | "primaryKey": {
153 | "columnNames": [
154 | "uid"
155 | ],
156 | "autoGenerate": true
157 | },
158 | "indices": [],
159 | "foreignKeys": []
160 | }
161 | ],
162 | "setupQueries": [
163 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
164 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"154b1659e9cecece6224a8eb7f620019\")"
165 | ]
166 | }
167 | }
--------------------------------------------------------------------------------
/images/rotate_default_icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
152 |
--------------------------------------------------------------------------------
/app/src/main/java/siteswaplib/FilterList.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2017 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package siteswaplib;
20 |
21 | import java.io.Serializable;
22 | import java.util.LinkedList;
23 | import java.util.List;
24 |
25 | import siteswaplib.NumberFilter.Type;
26 |
27 | public class FilterList extends LinkedList implements Serializable {
28 |
29 | public FilterList() {
30 | }
31 |
32 |
33 | public FilterList(int numberOfJugglers, int numberOfSynchronousHands) {
34 | addDefaultFilters(numberOfJugglers, numberOfSynchronousHands);
35 | }
36 |
37 | // TODO add and use method updateNumberOfJugglersAndSynchronousHands
38 |
39 | public void addDefaultFilters(int numberOfJugglers, int minThrow,
40 | int numberOfSynchronousHands) {
41 | if (numberOfJugglers <= 1)
42 | return;
43 |
44 | // remove Filters first, to avoid duplicate filters
45 | removeDefaultFilters(numberOfJugglers, minThrow, numberOfSynchronousHands);
46 | addFirst(new NumberFilter(Siteswap.PASS, Type.GREATER_EQUAL, 1, numberOfSynchronousHands));
47 | for (int i = minThrow; i < 2*numberOfJugglers; ++i) {
48 | if ( Siteswap.isPass(i, numberOfJugglers)) {
49 | NumberFilter filter = new NumberFilter(i, Type.EQUAL, 0, numberOfSynchronousHands);
50 | if (!contains(filter))
51 | addFirst(filter);
52 | }
53 | }
54 | }
55 |
56 | public void addDefaultFilters(int numberOfJugglers, int numberOfSynchronousHands) {
57 | addDefaultFilters(numberOfJugglers, 0, numberOfSynchronousHands);
58 | }
59 |
60 | public void addZips(int numberOfJugglers, int numberOfSynchronousHands) {
61 |
62 | while (remove(new NumberFilter(numberOfJugglers, Type.EQUAL, 0, numberOfSynchronousHands)))
63 | ;
64 | }
65 |
66 | public void addZaps(int numberOfJugglers, int numberOfSynchronousHands) {
67 |
68 | int max = 3*numberOfJugglers;
69 | if (numberOfSynchronousHands > 1 && numberOfJugglers > 1)
70 | max = 2 * numberOfJugglers + 2; // Where is just one zap in synchronous patters "2p"
71 | for (int i = 2 * numberOfJugglers + 1; i < max; ++i) {
72 | if ( Siteswap.isPass(i, numberOfJugglers))
73 | while (remove(new NumberFilter(i, Type.EQUAL, 0,
74 | numberOfSynchronousHands)))
75 | ;
76 | }
77 | }
78 |
79 | public void addHolds(int numberOfJugglers, int numberOfSynchronousHands) {
80 | remove(new NumberFilter(2 * numberOfJugglers, Type.EQUAL, 0, numberOfSynchronousHands));
81 | }
82 |
83 | public void removeDefaultFilters(int numberOfJugglers, int minThrow,
84 | int numberOfSynchronousHands) {
85 | if (numberOfJugglers <= 1)
86 | return;
87 | while (remove(new NumberFilter(Siteswap.PASS, Type.GREATER_EQUAL, 1,
88 | numberOfSynchronousHands)))
89 | ;
90 | for (int i = minThrow; i < 2*numberOfJugglers; ++i) {
91 | if ( Siteswap.isPass(i, numberOfJugglers))
92 | while (remove(new NumberFilter(i, Type.EQUAL, 0,
93 | numberOfSynchronousHands)))
94 | ;
95 | }
96 | }
97 |
98 | public void removeDefaultFilters(int numberOfJugglers,
99 | int numberOfSynchronousHands) {
100 | removeDefaultFilters(numberOfJugglers, 0, numberOfSynchronousHands);
101 | }
102 |
103 | public void removeZips(int numberOfJugglers, int numberOfSynchronousHands) {
104 |
105 | addZips(numberOfJugglers, numberOfSynchronousHands);
106 | addFirst(new NumberFilter(numberOfJugglers, Type.EQUAL, 0, 1));
107 | }
108 |
109 | public void removeZaps(int numberOfJugglers, int numberOfSynchronousHands) {
110 |
111 | addZaps(numberOfJugglers, numberOfSynchronousHands);
112 | int max = 3*numberOfJugglers;
113 | if (numberOfSynchronousHands > 1 && numberOfJugglers > 1)
114 | max = 2 * numberOfJugglers + 2; // Where is just one zap in synchronous patters "2p"
115 | for (int i = 2 * numberOfJugglers + 1; i < max; ++i) {
116 | if ( Siteswap.isPass(i, numberOfJugglers))
117 | addFirst(new NumberFilter(i, Type.EQUAL, 0,
118 | numberOfSynchronousHands));
119 | }
120 | }
121 |
122 | public void removeHolds(int numberOfJugglers, int numberOfSynchronousHands) {
123 |
124 | addHolds(numberOfJugglers, numberOfSynchronousHands);
125 | addFirst(new NumberFilter(2 * numberOfJugglers, Type.EQUAL, 0, 1));
126 | }
127 |
128 | public String toParsableString() {
129 | String str = new String();
130 | for (Filter filter : this) {
131 | if (filter instanceof LocalPatternFilter) {
132 | str += Filter.FilterType.LOCAL_PATTERN_FILTER.toString() + ":";
133 | str += filter.toParsableString() + ";";
134 | }
135 | else if (filter instanceof LocalInterfaceFilter) {
136 | str += Filter.FilterType.LOCAL_INTERFACE_FILTER.toString() + ":";
137 | str += filter.toParsableString() + ";";
138 | }
139 | else if (filter instanceof PatternFilter) {
140 | str += Filter.FilterType.PATTERN_FILTER.toString() + ":";
141 | str += filter.toParsableString() + ";";
142 | }
143 | else if (filter instanceof InterfaceFilter) {
144 | str += Filter.FilterType.INTERFACE_FILTER.toString() + ":";
145 | str += filter.toParsableString() + ";";
146 | }
147 | else if (filter instanceof NumberFilter) {
148 | str += Filter.FilterType.NUMBER_FILTER.toString() + ":";
149 | str += filter.toParsableString() + ";";
150 | }
151 | }
152 | return str;
153 | }
154 |
155 | public FilterList fromParsableString(String str) {
156 | clear();
157 | String[] filters = str.split(";");
158 | for (String f : filters) {
159 | String[] filter = f.split(":");
160 | if (filter.length != 2)
161 | continue;
162 | if (Filter.FilterType.valueOf(filter[0]).equals(Filter.FilterType.LOCAL_PATTERN_FILTER)) {
163 | add(new LocalPatternFilter(filter[1]));
164 | }
165 | else if (Filter.FilterType.valueOf(filter[0]).equals(Filter.FilterType.LOCAL_INTERFACE_FILTER)) {
166 | add(new LocalInterfaceFilter(filter[1]));
167 | }
168 | else if (Filter.FilterType.valueOf(filter[0]).equals(Filter.FilterType.PATTERN_FILTER)) {
169 | add(new PatternFilter(filter[1]));
170 | }
171 | else if (Filter.FilterType.valueOf(filter[0]).equals(Filter.FilterType.INTERFACE_FILTER)) {
172 | add(new InterfaceFilter(filter[1]));
173 | }
174 | else if (Filter.FilterType.valueOf(filter[0]).equals(Filter.FilterType.NUMBER_FILTER)) {
175 | add(new NumberFilter(filter[1]));
176 | }
177 | }
178 | return this;
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/app/src/main/java/namlit/siteswapgenerator/AddToFavoritesDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Siteswap Generator: Android App for generating juggling siteswaps
3 | * Copyright (C) 2018 Tilman Sinning
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | package namlit.siteswapgenerator;
20 |
21 |
22 | import android.app.Activity;
23 | import android.app.Dialog;
24 | import android.content.DialogInterface;
25 | import android.os.Bundle;
26 | import androidx.fragment.app.DialogFragment;
27 | import androidx.fragment.app.FragmentManager;
28 | import androidx.appcompat.app.AlertDialog;
29 |
30 | import android.widget.ArrayAdapter;
31 | import android.widget.AutoCompleteTextView;
32 | import android.widget.EditText;
33 |
34 | import java.util.Date;
35 | import java.text.DateFormat;
36 | import java.util.List;
37 |
38 | import siteswaplib.Siteswap;
39 |
40 | /**
41 | * Created by tilman on 22.07.18.
42 | */
43 |
44 | public class AddToFavoritesDialog extends DialogFragment {
45 |
46 | public interface DatabaseTransactionComplete {
47 | public void databaseTransactionComplete();
48 | }
49 |
50 | private static final String STATE_SITESWAP = "STATE_SITESWAP";
51 | private EditText mSiteswapNameTextEdit;
52 | private AutoCompleteTextView mJugglerNameTextEdit;
53 | private AutoCompleteTextView mLocationTextEdit;
54 | private EditText mDateTextEdit;
55 | private Siteswap mSiteswap;
56 | private String mSiteswapName;
57 | private String mJugglerName;
58 | private String mLocation;
59 | private String mDate;
60 | private DatabaseTransactionComplete mDatabaseTransactionComplete;
61 | private Activity mActivity;
62 | private ArrayAdapter mJugglerAdapter;
63 | private ArrayAdapter mLocationAdapter;
64 |
65 | @Override
66 | public Dialog onCreateDialog(Bundle savedInstanceState) {
67 |
68 | if(savedInstanceState != null) {
69 | mSiteswap = (Siteswap) savedInstanceState.getSerializable(STATE_SITESWAP);
70 | }
71 |
72 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
73 | mDatabaseTransactionComplete = (DatabaseTransactionComplete) getActivity();
74 | mActivity = getActivity();
75 |
76 | builder.setView(R.layout.layout_add_to_favorites)
77 | .setTitle(getString(R.string.add_to_favorites__title))
78 | .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
79 | @Override
80 | public void onClick(DialogInterface dialog, int which) {
81 |
82 | }
83 | })
84 | .setPositiveButton(getString(R.string.add), new DialogInterface.OnClickListener() {
85 | @Override
86 | public void onClick(DialogInterface dialog, int which) {
87 | addSiteswapToFavorites();
88 | }
89 | });
90 | return builder.create();
91 | }
92 |
93 | @Override
94 | public void onStart() {
95 | super.onStart();
96 | mSiteswapNameTextEdit = (EditText) getDialog().findViewById(R.id.siteswap_name_text_edit);
97 | mJugglerNameTextEdit = (AutoCompleteTextView) getDialog().findViewById(R.id.juggler_name_text_edit);
98 | mLocationTextEdit = (AutoCompleteTextView) getDialog().findViewById(R.id.location_text_edit);
99 | mDateTextEdit= (EditText) getDialog().findViewById(R.id.date_text_edit);
100 | setupAutocomplete();
101 |
102 | if (mSiteswap.getSiteswapName() == "")
103 | mSiteswapNameTextEdit.setText(mSiteswap.toString());
104 | else
105 | mSiteswapNameTextEdit.setText(mSiteswap.getSiteswapName() + ": " + mSiteswap.toString());
106 | mDateTextEdit.setText(DateFormat.getDateInstance().format(new Date()));
107 | }
108 |
109 |
110 | @Override
111 | public void onSaveInstanceState(Bundle outState) {
112 | super.onSaveInstanceState(outState);
113 |
114 | outState.putSerializable(STATE_SITESWAP, mSiteswap);
115 | }
116 |
117 | @Override
118 | public void onStop() {
119 | super.onStop();
120 | }
121 |
122 | private void addSiteswapToFavorites()
123 | {
124 | mSiteswapName = mSiteswapNameTextEdit.getText().toString();
125 | mSiteswap.setSiteswapName(mSiteswapName);
126 | mJugglerName = mJugglerNameTextEdit.getText().toString();
127 | mLocation = mLocationTextEdit.getText().toString();
128 | mDate = mDateTextEdit.getText().toString();
129 |
130 | new Thread(new Runnable() {
131 | @Override
132 | public void run() {
133 | try {
134 | AppDatabase db = AppDatabase.getAppDatabase(getContext());
135 | db.siteswapDao().insertFavorites(new SiteswapEntity(mSiteswap, mSiteswapName,
136 | mJugglerName, mLocation, mDate));
137 | mActivity.runOnUiThread(new Runnable() {
138 | @Override
139 | public void run() {
140 | mDatabaseTransactionComplete.databaseTransactionComplete();
141 | }
142 | });
143 | } catch (android.database.sqlite.SQLiteConstraintException e) {
144 | }
145 | }
146 | }).start();
147 |
148 | }
149 |
150 | private void setupAutocomplete() {
151 |
152 | new Thread(new Runnable() {
153 | @Override
154 | public void run() {
155 | try {
156 | AppDatabase db = AppDatabase.getAppDatabase(getContext());
157 | List jugglers = db.siteswapDao().getJugglers();
158 | List locations = db.siteswapDao().getLocations();
159 | mJugglerAdapter = new ArrayAdapter(
160 | getContext(), android.R.layout.simple_list_item_1, jugglers);
161 | mLocationAdapter = new ArrayAdapter(
162 | getContext(), android.R.layout.simple_list_item_1, locations);
163 | mActivity.runOnUiThread(new Runnable() {
164 | @Override
165 | public void run() {
166 | mJugglerNameTextEdit.setAdapter(mJugglerAdapter);
167 | mJugglerNameTextEdit.setThreshold(1);
168 | mLocationTextEdit.setAdapter(mLocationAdapter);
169 | mLocationTextEdit.setThreshold(1);
170 | }
171 | });
172 | } catch (android.database.sqlite.SQLiteConstraintException e) {
173 | }
174 | }
175 | }).start();
176 |
177 | }
178 |
179 | public void show(FragmentManager manager, String tag, Siteswap siteswap) {
180 | mSiteswap = siteswap;
181 | show(manager, tag);
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Description
2 |
3 | This is an Andoid App for generating juggling [Siteswaps](https://en.wikipedia.org/wiki/Siteswap), especially designed for passing. The following features are supported:
4 |
5 | - Find all possible Siteswaps for a given period length and number of objects
6 | - Easy filtering of zips, zaps and holds via check boxes
7 | - Automatic filtering of non-passable patterns
8 | - Support for pattern and interface filters
9 | - Generation of local Siteswaps and calculation of start position
10 | - Support for asynchronous passing patters with more than two jugglers
11 | - Generation of very long patterns in a random mode
12 |
13 | # Get the App
14 |
15 |
16 |
17 |
18 |
19 |
20 | ## Becoming a Beta Tester
21 |
22 | App updates are usually released as beta versions first. To get the newest features as soon as they are available you can enter the beta testing with the following link:
23 |
24 | # How to use the App
25 |
26 | ## Generating Siteswaps
27 |
28 | The following parameters need to be adjusted for Siteswap generation:
29 |
30 |
31 |
Number of Objects:
32 |
33 | The number of objects for the passing pattern. The default value on first App startup is seven.
34 |
35 |
36 |
Period Length:
37 |
38 | The period length of the juggling pattern. The default value is five, but also very long periods are possible. For long periods the [Random Generation Mode](#using-the-random-generation-mode) can be used.
39 |
40 |
41 |
Max Throw:
42 |
43 | The maximum throw height to be considered.
44 |
45 |
46 |
Min Throw:
47 |
48 | The minimum throw height to be considered. For passing Siteswaps with two jugglers and no empty hands this can usually be set to two.
49 |
50 |
51 |
Number of Jugglers:
52 |
53 | The number of jugglers for the passing pattern. The number of jugglers is only used for correct filtering and generation of local Siteswaps. The Siteswap generation algorithm itself does not use this parameter.
54 |
55 |
56 |
Max Results:
57 |
58 | The maximum number of juggling patterns to be generated. The Siteswap generation algorithm will be aborted, when the maximum number of results is reached. Generating a very large number of Siteswaps can lead to long generation times.
59 |
60 |
61 |
Timeout:
62 |
63 | The maximum time for Siteswap generation. When the time limit is reached, the Siteswap generation algorithm is aborted. For generation of a large number of Siteswaps, this value can be increased
64 |