├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── splash.png
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-hdpi
│ │ │ │ ├── ic_check_white_24dp.png
│ │ │ │ ├── ic_info_white_24dp.png
│ │ │ │ ├── ic_list_white_24dp.png
│ │ │ │ ├── ic_pause_white_24dp.png
│ │ │ │ ├── ic_compare_white_24dp.png
│ │ │ │ ├── ic_language_white_24dp.png
│ │ │ │ ├── ic_settings_white_24dp.png
│ │ │ │ ├── ic_color_lens_white_24dp.png
│ │ │ │ ├── ic_play_arrow_white_24dp.png
│ │ │ │ └── ic_settings_backup_restore_white_24dp.png
│ │ │ ├── drawable-mdpi
│ │ │ │ ├── ic_check_white_24dp.png
│ │ │ │ ├── ic_info_white_24dp.png
│ │ │ │ ├── ic_list_white_24dp.png
│ │ │ │ ├── ic_pause_white_24dp.png
│ │ │ │ ├── ic_compare_white_24dp.png
│ │ │ │ ├── ic_language_white_24dp.png
│ │ │ │ ├── ic_settings_white_24dp.png
│ │ │ │ ├── ic_color_lens_white_24dp.png
│ │ │ │ ├── ic_play_arrow_white_24dp.png
│ │ │ │ └── ic_settings_backup_restore_white_24dp.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ ├── ic_check_white_24dp.png
│ │ │ │ ├── ic_info_white_24dp.png
│ │ │ │ ├── ic_list_white_24dp.png
│ │ │ │ ├── ic_pause_white_24dp.png
│ │ │ │ ├── ic_compare_white_24dp.png
│ │ │ │ ├── ic_color_lens_white_24dp.png
│ │ │ │ ├── ic_language_white_24dp.png
│ │ │ │ ├── ic_play_arrow_white_24dp.png
│ │ │ │ ├── ic_settings_white_24dp.png
│ │ │ │ └── ic_settings_backup_restore_white_24dp.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ ├── ic_info_white_24dp.png
│ │ │ │ ├── ic_list_white_24dp.png
│ │ │ │ ├── ic_check_white_24dp.png
│ │ │ │ ├── ic_pause_white_24dp.png
│ │ │ │ ├── ic_compare_white_24dp.png
│ │ │ │ ├── ic_language_white_24dp.png
│ │ │ │ ├── ic_settings_white_24dp.png
│ │ │ │ ├── ic_color_lens_white_24dp.png
│ │ │ │ ├── ic_play_arrow_white_24dp.png
│ │ │ │ └── ic_settings_backup_restore_white_24dp.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ │ ├── ic_check_white_24dp.png
│ │ │ │ ├── ic_info_white_24dp.png
│ │ │ │ ├── ic_list_white_24dp.png
│ │ │ │ ├── ic_pause_white_24dp.png
│ │ │ │ ├── ic_compare_white_24dp.png
│ │ │ │ ├── ic_language_white_24dp.png
│ │ │ │ ├── ic_settings_white_24dp.png
│ │ │ │ ├── ic_color_lens_white_24dp.png
│ │ │ │ ├── ic_play_arrow_white_24dp.png
│ │ │ │ └── ic_settings_backup_restore_white_24dp.png
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── layout
│ │ │ │ ├── log_item.xml
│ │ │ │ ├── fragment_log.xml
│ │ │ │ ├── activity_app_about.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── nav_header.xml
│ │ │ │ ├── fragment_sort.xml
│ │ │ │ ├── fragment_multi_sort.xml
│ │ │ │ ├── fragment_control.xml
│ │ │ │ ├── content_main.xml
│ │ │ │ ├── control_panel.xml
│ │ │ │ └── content_app_about.xml
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── do_not_translate.xml
│ │ │ │ ├── key_pref.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ ├── xml
│ │ │ │ └── setting.xml
│ │ │ ├── menu
│ │ │ │ └── menu_drawer.xml
│ │ │ └── values-vi
│ │ │ │ └── strings.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── duy
│ │ │ │ └── algorithm
│ │ │ │ ├── SortCompletionListener.java
│ │ │ │ ├── algorithms
│ │ │ │ ├── IDataHandler.java
│ │ │ │ ├── algo
│ │ │ │ │ ├── SelectionSortThread.java
│ │ │ │ │ ├── ShellSortThread.java
│ │ │ │ │ ├── QuickSortThread.java
│ │ │ │ │ ├── CountingSortThread.java
│ │ │ │ │ ├── MergeSortThread.java
│ │ │ │ │ ├── InsertionSortThread.java
│ │ │ │ │ ├── BogoSortThread.java
│ │ │ │ │ ├── BubbleSortThread.java
│ │ │ │ │ └── CocktailShakerSortThread.java
│ │ │ │ ├── SortAlgorithmThread.java
│ │ │ │ └── AlgorithmThread.java
│ │ │ │ ├── SettingsActivity.java
│ │ │ │ ├── customview
│ │ │ │ ├── EditTextInputArray.java
│ │ │ │ ├── LogView.java
│ │ │ │ └── SortView.java
│ │ │ │ ├── userinterface
│ │ │ │ └── ThemeEngine.java
│ │ │ │ ├── AppAboutActivity.java
│ │ │ │ ├── notify
│ │ │ │ └── RateManager.java
│ │ │ │ ├── utils
│ │ │ │ └── ArrayUtils.java
│ │ │ │ ├── AbstractSortAlgorithmFragment.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── AbstractAppCompatActivity.java
│ │ │ │ ├── SortAlgorithmFragment.java
│ │ │ │ └── SortSpeedTestFragmentSort.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── duy
│ │ │ └── algorithm
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── duy
│ │ └── algorithm
│ │ └── ExampleInstrumentedTest.java
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── .idea
├── copyright
│ └── profiles_settings.xml
├── modules.xml
├── runConfigurations.xml
├── gradle.xml
├── compiler.xml
└── misc.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── screenshot
├── Screenshot_20170205-132701_framed.png
├── Screenshot_20170205-132705_framed.png
├── Screenshot_20170205-132709_framed.png
├── Screenshot_20170205-132717_framed.png
├── Screenshot_20170205-132727_framed.png
├── Screenshot_20170205-132741_framed.png
└── Screenshot_20170205-132753_framed.png
├── gradle.properties
├── README.md
├── gradlew.bat
├── .gitignore
├── gradlew
└── LICENCE
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
11 | * Include precision of calculate. Font, theme, style. Dev mode, trace mode.
12 | */
13 | public class SettingsActivity extends PreferenceActivity {
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setTitle(R.string.setting);
18 | getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
19 | }
20 |
21 | @Override
22 | protected void onResume() {
23 | super.onResume();
24 | }
25 |
26 | public static class MyPreferenceFragment extends PreferenceFragment {
27 | @Override
28 | public void onCreate(final Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | addPreferencesFromResource(R.xml.setting);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
31 | * auto set theme when user changed theme 32 | *
33 | * Created by Duy on 19/7/2016 34 | */ 35 | public abstract class AbstractAppCompatActivity extends AppCompatActivity 36 | implements SharedPreferences.OnSharedPreferenceChangeListener { 37 | public static final String TAG = "MainActivity"; 38 | protected SharedPreferences mPreferences; 39 | public static final String APP_ID = BuildConfig.APPLICATION_ID; 40 | 41 | 42 | /** 43 | * set theme and init mHistoryDatabase for history 44 | * 45 | * @param savedInstanceState 46 | */ 47 | @Override 48 | protected void onCreate(@Nullable Bundle savedInstanceState) { 49 | super.onCreate(savedInstanceState); 50 | 51 | // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 52 | // WindowManager.LayoutParams.FLAG_FULLSCREEN); 53 | // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 54 | // Window w = getWindow(); // in Activity's onCreate() for instance 55 | // w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, 56 | // WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); 57 | // } 58 | mPreferences = PreferenceManager.getDefaultSharedPreferences(this); 59 | 60 | setLocale(false); 61 | 62 | //set theme for app 63 | setTheme(false); 64 | } 65 | 66 | /** 67 | * set language 68 | * 69 | * @param create 70 | */ 71 | 72 | private void setLocale(boolean create) { 73 | Locale locale; 74 | String code = mPreferences.getString(getString(R.string.key_pref_lang), "default_lang"); 75 | if (code.equals("default_lang")) { 76 | Log.d(TAG, "setLocale: default"); 77 | locale = Locale.getDefault(); 78 | } else { 79 | locale = new Locale(code); 80 | } 81 | Locale.setDefault(locale); 82 | Configuration config = new Configuration(); 83 | config.locale = locale; 84 | Resources resources = getResources(); 85 | resources.updateConfiguration(config, resources.getDisplayMetrics()); 86 | if (create) recreate(); 87 | } 88 | 89 | 90 | @Override 91 | public void onBackPressed() { 92 | super.onBackPressed(); 93 | } 94 | 95 | @Override 96 | protected void onStart() { 97 | super.onStart(); 98 | if (mPreferences != null) 99 | mPreferences.registerOnSharedPreferenceChangeListener(this); 100 | // Monitor launch times and interval from installation 101 | RateThisApp.onStart(this); 102 | // If the criteria is satisfied, "Rate this app" dialog will be shown 103 | RateThisApp.showRateDialogIfNeeded(this); 104 | RateThisApp.setCallback(new RateThisApp.Callback() { 105 | @Override 106 | public void onYesClicked() { 107 | rateApp(null); 108 | } 109 | 110 | @Override 111 | public void onNoClicked() { 112 | } 113 | 114 | @Override 115 | public void onCancelClicked() { 116 | } 117 | }); 118 | 119 | } 120 | 121 | @Override 122 | protected void onResume() { 123 | super.onResume(); 124 | } 125 | 126 | /** 127 | * set theme for app 128 | * 129 | * @param recreate -call method onCreate 130 | */ 131 | protected void setTheme(boolean recreate) { 132 | String name = mPreferences.getString(getResources().getString(R.string.key_pref_theme), ""); 133 | ThemeEngine themeEngine = new ThemeEngine(getApplicationContext()); 134 | int themeId = themeEngine.getTheme(name); 135 | if (themeId != ThemeEngine.THEME_NOT_FOUND) { 136 | super.setTheme(themeId); 137 | if (recreate) recreate(); 138 | Log.d(TAG, "Set theme ok"); 139 | } else { 140 | Log.d(TAG, "Theme not found"); 141 | } 142 | } 143 | 144 | @Override 145 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { 146 | if (s.equals(getResources().getString(R.string.key_pref_theme))) { 147 | setTheme(true); 148 | } else if (s.equals(getString(R.string.key_pref_lang))) { 149 | setLocale(true); 150 | Toast.makeText(this, getString(R.string.change_lang_msg), Toast.LENGTH_SHORT).show(); 151 | } 152 | } 153 | 154 | @Override 155 | protected void onPause() { 156 | super.onPause(); 157 | } 158 | 159 | @Override 160 | protected void onDestroy() { 161 | super.onDestroy(); 162 | if (mPreferences != null) 163 | mPreferences.unregisterOnSharedPreferenceChangeListener(this); 164 | } 165 | 166 | 167 | /** 168 | * share app 169 | */ 170 | public void shareApp(View view) { 171 | Intent intent = new Intent(); 172 | intent.setAction(Intent.ACTION_SEND); 173 | intent.putExtra(Intent.EXTRA_TEXT, "http://play.google.com/store/apps/details?id=" + APP_ID); 174 | intent.setType("text/plain"); 175 | startActivity(intent); 176 | } 177 | 178 | /** 179 | * show dialog with title and messenger 180 | * 181 | * @param title - title 182 | * @param msg - messenger 183 | */ 184 | protected void showDialog(String title, String msg) { 185 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 186 | builder.setTitle(title).setMessage(msg); 187 | builder.setNegativeButton(this.getString(R.string.close), new DialogInterface.OnClickListener() { 188 | @Override 189 | public void onClick(DialogInterface dialogInterface, int i) { 190 | dialogInterface.cancel(); 191 | } 192 | }); 193 | builder.create().show(); 194 | } 195 | 196 | /** 197 | * show dialog with title and messenger 198 | * 199 | * @param msg - messenger 200 | */ 201 | protected void showDialog(String msg) { 202 | this.showDialog("", msg); 203 | } 204 | 205 | 206 | 207 | public void rateApp(View view) { 208 | Uri uri = Uri.parse("market://details?id=" + APP_ID); 209 | Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri); 210 | // To count with Play market backstack, After pressing back button, 211 | // to taken back to our application, we need to add following flags to intent. 212 | goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | 213 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 214 | try { 215 | startActivity(goToMarket); 216 | } catch (ActivityNotFoundException e) { 217 | startActivity(new Intent(Intent.ACTION_VIEW, 218 | Uri.parse("http://play.google.com/store/apps/details?id=" + APP_ID))); 219 | } 220 | } 221 | 222 | public void moreApp(View view) { 223 | Uri uri = Uri.parse("market://search?q=pub:Trần Lê Duy"); 224 | Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri); 225 | // To count with Play market backstack, After pressing back button, 226 | // to taken back to our application, we need to add following flags to intent. 227 | goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | 228 | 229 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 230 | try { 231 | startActivity(goToMarket); 232 | } catch (ActivityNotFoundException e) { 233 | startActivity(new Intent(Intent.ACTION_VIEW, 234 | Uri.parse("http://play.google.com/store/search?q=pub:Trần Lê Duy"))); 235 | } 236 | } 237 | 238 | protected void hideKeyboard(EditText editText) { 239 | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 240 | imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); 241 | } 242 | 243 | 244 | } 245 | -------------------------------------------------------------------------------- /app/src/main/java/com/duy/algorithm/SortAlgorithmFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Naman Dwivedi 3 | * 4 | * Licensed under the GNU General Public License v3 5 | * 6 | * This is free software: you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 9 | * 10 | * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | * See the GNU General Public License for more details. 13 | */ 14 | 15 | package com.duy.algorithm; 16 | 17 | import android.os.Bundle; 18 | import android.util.Log; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.Toast; 23 | 24 | import com.duy.algorithm.algorithms.SortAlgorithmThread; 25 | import com.duy.algorithm.algorithms.algo.BubbleSortThread; 26 | import com.duy.algorithm.algorithms.algo.CocktailShakerSortThread; 27 | import com.duy.algorithm.algorithms.algo.InsertionSortThread; 28 | import com.duy.algorithm.algorithms.algo.MergeSortThread; 29 | import com.duy.algorithm.algorithms.algo.QuickSortThread; 30 | import com.duy.algorithm.algorithms.algo.SelectionSortThread; 31 | import com.duy.algorithm.algorithms.algo.ShellSortThread; 32 | import com.duy.algorithm.customview.LogView; 33 | import com.duy.algorithm.customview.SortView; 34 | import com.duy.algorithm.utils.ArrayUtils; 35 | 36 | import java.util.regex.Pattern; 37 | 38 | import static com.duy.algorithm.algorithms.AlgorithmThread.ALGORITHM_NAME.BUBBLE_SORT; 39 | import static com.duy.algorithm.algorithms.AlgorithmThread.ALGORITHM_NAME.COCKTAIL_SORT; 40 | import static com.duy.algorithm.algorithms.AlgorithmThread.ALGORITHM_NAME.INSERTION_SORT; 41 | import static com.duy.algorithm.algorithms.AlgorithmThread.ALGORITHM_NAME.MERGE_SORT; 42 | import static com.duy.algorithm.algorithms.AlgorithmThread.ALGORITHM_NAME.QUICK_SORT; 43 | import static com.duy.algorithm.algorithms.AlgorithmThread.ALGORITHM_NAME.SELECTION_SORT; 44 | import static com.duy.algorithm.algorithms.AlgorithmThread.ALGORITHM_NAME.SHELL_SORT; 45 | import static com.duy.algorithm.algorithms.AlgorithmThread.COMMAND_START_ALGORITHM; 46 | import static com.duy.algorithm.algorithms.AlgorithmThread.KEY_ALGORITHM; 47 | 48 | public class SortAlgorithmFragment extends AbstractSortAlgorithmFragment { 49 | 50 | private final static String TAG = SortAlgorithmFragment.class.getSimpleName(); 51 | protected SortAlgorithmThread thread; 52 | private SortView mSortView; 53 | private int mCountData = 50; 54 | private LogView mLogger; 55 | 56 | public static SortAlgorithmFragment newInstance(String algorithm) { 57 | SortAlgorithmFragment fragment = new SortAlgorithmFragment(); 58 | Bundle bundle = new Bundle(); 59 | bundle.putString(KEY_ALGORITHM, algorithm); 60 | fragment.setArguments(bundle); 61 | return fragment; 62 | } 63 | 64 | @Override 65 | public View getView(LayoutInflater inflater, ViewGroup container) { 66 | return inflater.inflate(R.layout.fragment_sort, container, false); 67 | } 68 | 69 | @Override 70 | protected void createSortView() { 71 | mSortView = (SortView) findViewById(R.id.sortView); 72 | mLogger = (LogView) findViewById(R.id.rc_log); 73 | mLogger.setmEmptyView(findViewById(R.id.empty_view)); 74 | } 75 | 76 | @Override 77 | public void setupFragment(String algorithmKey) { 78 | switch (algorithmKey) { 79 | case BUBBLE_SORT: 80 | thread = new BubbleSortThread(mSortView, getActivity()); 81 | break; 82 | case INSERTION_SORT: 83 | thread = new InsertionSortThread(mSortView, getActivity()); 84 | break; 85 | case SELECTION_SORT: 86 | thread = new SelectionSortThread(mSortView, getActivity()); 87 | break; 88 | case QUICK_SORT: 89 | thread = new QuickSortThread(mSortView, getActivity()); 90 | break; 91 | case MERGE_SORT: 92 | thread = new MergeSortThread(mSortView, getActivity()); 93 | break; 94 | case SHELL_SORT: 95 | thread = new ShellSortThread(mSortView, getActivity()); 96 | break; 97 | case COCKTAIL_SORT: 98 | thread = new CocktailShakerSortThread(mSortView, getActivity()); 99 | break; 100 | } 101 | thread.setStarted(false); 102 | thread.setCompletionListener(this); 103 | thread.setLogger(mLogger); 104 | generateRandomData(); 105 | } 106 | 107 | @Override 108 | public void enableView() { 109 | mEditArray.setEnabled(true); 110 | mEditNumber.setEnabled(true); 111 | btnRandom.setEnabled(true); 112 | } 113 | 114 | 115 | @Override 116 | protected void setDelayTime(int value) { 117 | if (thread.isStarted()) 118 | thread.setDelayTime(value + 10); 119 | } 120 | 121 | @Override 122 | protected void startSort() { 123 | if (createData()) { 124 | thread.sendMessage(COMMAND_START_ALGORITHM); 125 | mPlay.setImageResource(R.drawable.ic_pause_white_24dp); 126 | mPlayAnimation.show(); 127 | disableView(); 128 | } 129 | } 130 | 131 | @Override 132 | protected void fabClick() { 133 | if (!thread.isStarted()) {//If you have sorted or not sorted 134 | startSort(); 135 | } else { //if it is sorting, pause or resume thread 136 | if (thread.isPaused()) 137 | resumeSort(); 138 | else 139 | pauseSort(); 140 | } 141 | } 142 | 143 | 144 | @Override 145 | public void generateRandomData() { 146 | //check empty length of array 147 | if (mEditNumber.getText().toString().isEmpty()) { 148 | mCountData = Integer.parseInt(mEditNumber.getHint().toString()); 149 | } else { 150 | mCountData = Integer.parseInt(mEditNumber.getText().toString()); 151 | } 152 | 153 | int[] array = ArrayUtils.createIntArray(mCountData); 154 | thread.setData(array); 155 | mEditArray.setText(ArrayUtils.arrayToString(array)); 156 | } 157 | 158 | @Override 159 | public boolean createData() { 160 | Log.d(TAG, "createData: "); 161 | 162 | //set time sleep for thread 163 | int delayTime = mTimeBar.getProgress(); 164 | thread.setDelayTime(delayTime); 165 | 166 | //check empty length of array 167 | if (mEditNumber.getText().toString().isEmpty()) { 168 | mCountData = Integer.parseInt(mEditNumber.getHint().toString()); 169 | } else { 170 | mCountData = Integer.parseInt(mEditNumber.getText().toString()); 171 | } 172 | 173 | String raw = mEditArray.getText().toString(); 174 | final String strArray[] = raw.split(Pattern.quote(",")); 175 | if (strArray.length == mCountData) { 176 | int[] array = ArrayUtils.arrayStringToInt(strArray); 177 | 178 | //If receive an error during conversion 179 | if (array[0] == -1) { 180 | return false; 181 | } 182 | thread.setData(array); 183 | return true; 184 | } else { 185 | // mSlidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); 186 | if (strArray.length > mCountData) { 187 | Toast.makeText(getActivity(), "Please remove " + 188 | +(strArray.length - mCountData) 189 | + " entry of array, length of array is " 190 | + strArray.length, Toast.LENGTH_LONG).show(); 191 | } else { 192 | Toast.makeText(getActivity(), "Please add " 193 | + (-strArray.length + mCountData) 194 | + " entry of array, length of array is " 195 | + strArray.length, Toast.LENGTH_LONG).show(); 196 | } 197 | 198 | return false; 199 | } 200 | } 201 | 202 | @Override 203 | public void pauseSort() { 204 | if (thread.isStarted()) { 205 | thread.setPaused(true); 206 | mPlay.setImageResource(R.drawable.ic_play_arrow_white_24dp); 207 | mPlayAnimation.hide(); 208 | disableView(); 209 | } 210 | } 211 | 212 | @Override 213 | protected void resumeSort() { 214 | if (thread.isPaused()) { 215 | thread.setPaused(false); 216 | mPlay.setImageResource(R.drawable.ic_pause_white_24dp); 217 | mPlayAnimation.show(); 218 | disableView(); 219 | } 220 | } 221 | 222 | @Override 223 | public void onSortCompleted() { 224 | if (getActivity() != null) { 225 | getActivity().runOnUiThread(new Runnable() { 226 | @Override 227 | public void run() { 228 | Toast.makeText(getActivity().getApplicationContext(), R.string.sorted, Toast.LENGTH_SHORT).show(); 229 | enableView(); 230 | mPlayAnimation.hide(); 231 | mPlay.setImageResource(R.drawable.ic_settings_backup_restore_white_24dp); 232 | } 233 | }); 234 | } 235 | super.onSortCompleted(); 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /app/src/main/java/com/duy/algorithm/SortSpeedTestFragmentSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Naman Dwivedi 3 | * 4 | * Licensed under the GNU General Public License v3 5 | * 6 | * This is free software: you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 9 | * 10 | * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | * See the GNU General Public License for more details. 13 | */ 14 | 15 | package com.duy.algorithm; 16 | 17 | import android.os.Bundle; 18 | import android.util.Log; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.Toast; 23 | 24 | import com.duy.algorithm.algorithms.AlgorithmThread; 25 | import com.duy.algorithm.algorithms.SortAlgorithmThread; 26 | import com.duy.algorithm.algorithms.algo.BubbleSortThread; 27 | import com.duy.algorithm.algorithms.algo.CocktailShakerSortThread; 28 | import com.duy.algorithm.algorithms.algo.InsertionSortThread; 29 | import com.duy.algorithm.algorithms.algo.MergeSortThread; 30 | import com.duy.algorithm.algorithms.algo.QuickSortThread; 31 | import com.duy.algorithm.algorithms.algo.SelectionSortThread; 32 | import com.duy.algorithm.algorithms.algo.ShellSortThread; 33 | import com.duy.algorithm.customview.SortView; 34 | import com.duy.algorithm.utils.ArrayUtils; 35 | import com.sothree.slidinguppanel.SlidingUpPanelLayout; 36 | 37 | import java.util.regex.Pattern; 38 | 39 | import static com.duy.algorithm.algorithms.AlgorithmThread.KEY_ALGORITHM; 40 | 41 | public class SortSpeedTestFragmentSort extends AbstractSortAlgorithmFragment { 42 | private final static String TAG = SortSpeedTestFragmentSort.class.getSimpleName(); 43 | private final int mCount = 7; 44 | private SortAlgorithmThread[] threads = new SortAlgorithmThread[mCount]; 45 | private SortView[] mSortViews = new SortView[mCount]; 46 | private int mCountData = 50; 47 | private int numThreadCompleted = 0; 48 | 49 | public static SortSpeedTestFragmentSort newInstance(String algorithm) { 50 | SortSpeedTestFragmentSort fragment = new SortSpeedTestFragmentSort(); 51 | Bundle bundle = new Bundle(); 52 | bundle.putString(KEY_ALGORITHM, algorithm); 53 | fragment.setArguments(bundle); 54 | return fragment; 55 | } 56 | 57 | @Override 58 | public View getView(LayoutInflater inflater, ViewGroup v) { 59 | return inflater.inflate(R.layout.fragment_multi_sort, v, false); 60 | } 61 | 62 | @Override 63 | protected void createSortView() { 64 | mSortViews[0] = (SortView) findViewById(R.id.sortView0); 65 | mSortViews[0].setName(R.string.bubble_sort); 66 | 67 | mSortViews[1] = (SortView) findViewById(R.id.sortView1); 68 | mSortViews[1].setName(R.string.insert_sort); 69 | 70 | mSortViews[2] = (SortView) findViewById(R.id.sortView2); 71 | mSortViews[2].setName(R.string.selection_sort); 72 | 73 | mSortViews[3] = (SortView) findViewById(R.id.sortView3); 74 | mSortViews[3].setName(R.string.quick_sort); 75 | 76 | mSortViews[4] = (SortView) findViewById(R.id.sortView4); 77 | mSortViews[4].setName(R.string.merge_sort); 78 | 79 | mSortViews[5] = (SortView) findViewById(R.id.sortView5); 80 | mSortViews[5].setName(R.string.shell_sort); 81 | 82 | mSortViews[6] = (SortView) findViewById(R.id.sortView6); 83 | mSortViews[6].setName(R.string.cocktail_sort); 84 | } 85 | 86 | @Override 87 | protected void setDelayTime(int value) { 88 | for (AlgorithmThread thread : threads) { 89 | thread.setDelayTime(value + 10); 90 | } 91 | } 92 | 93 | @Override 94 | protected void fabClick() { 95 | boolean ended = true; 96 | 97 | for (AlgorithmThread thread : threads) { 98 | if (thread.isStarted()) { 99 | ended = false; 100 | break; 101 | } 102 | } 103 | 104 | if (ended) {//If you have sorted or not sorted 105 | startSort(); 106 | } else { //if it is sorting, pause or resume threads 107 | boolean isAllPause = true; 108 | for (AlgorithmThread thread : threads) { 109 | if (!thread.isPaused()) { 110 | isAllPause = false; 111 | break; 112 | } 113 | } 114 | if (isAllPause) { 115 | resumeSort(); 116 | } else { 117 | pauseSort(); 118 | } 119 | } 120 | } 121 | 122 | protected void startSort() { 123 | if (createData()) { 124 | numThreadCompleted = 0; 125 | for (AlgorithmThread thread : threads) { 126 | thread.sendMessage(AlgorithmThread.COMMAND_START_ALGORITHM); 127 | } 128 | mPlay.setImageResource(R.drawable.ic_pause_white_24dp); 129 | mPlayAnimation.show(); 130 | disableView(); 131 | } 132 | } 133 | 134 | @Override 135 | public void setupFragment(String name) { 136 | mEditNumber.setText("50"); 137 | mTimeBar.setProgress(100); 138 | 139 | threads[0] = new BubbleSortThread(mSortViews[0], getActivity()); 140 | threads[1] = new InsertionSortThread(mSortViews[1], getActivity()); 141 | threads[2] = new SelectionSortThread(mSortViews[2], getActivity()); 142 | threads[3] = new QuickSortThread(mSortViews[3], getActivity()); 143 | threads[4] = new MergeSortThread(mSortViews[4], getActivity()); 144 | threads[5] = new ShellSortThread(mSortViews[5], getActivity()); 145 | threads[6] = new CocktailShakerSortThread(mSortViews[6], getActivity()); 146 | //disable animate 147 | for (SortAlgorithmThread thread : threads) { 148 | thread.setSwapAnimateEnable(false); 149 | thread.setCompletionListener(this); 150 | 151 | } 152 | generateRandomData(); 153 | } 154 | 155 | @Override 156 | protected void generateRandomData() { 157 | //check empty length of array 158 | if (mEditNumber.getText().toString().isEmpty()) { 159 | mCountData = Integer.parseInt(mEditNumber.getHint().toString()); 160 | } else { 161 | mCountData = Integer.parseInt(mEditNumber.getText().toString()); 162 | } 163 | 164 | int[] array = ArrayUtils.createIntArray(mCountData); 165 | for (SortAlgorithmThread thread : threads) { 166 | thread.setData(array.clone()); 167 | } 168 | mEditArray.setText(ArrayUtils.arrayToString(array)); 169 | } 170 | 171 | 172 | @Override 173 | public boolean createData() { 174 | Log.d(TAG, "createData: "); 175 | 176 | //set time sleep for threads[ 177 | int delayTime = mTimeBar.getProgress(); 178 | for (AlgorithmThread thread : threads) { 179 | thread.setDelayTime(delayTime); 180 | } 181 | 182 | //check empty length of array 183 | if (mEditNumber.getText().toString().isEmpty()) { 184 | mCountData = Integer.parseInt(mEditNumber.getHint().toString()); 185 | } else { 186 | mCountData = Integer.parseInt(mEditNumber.getText().toString()); 187 | } 188 | 189 | String raw = mEditArray.getText().toString(); 190 | final String strArray[] = raw.split(Pattern.quote(",")); 191 | if (strArray.length == mCountData) { 192 | int[] array = ArrayUtils.arrayStringToInt(strArray); 193 | 194 | //If receive an error during conversion 195 | if (array[0] == -1) { 196 | return false; 197 | } 198 | for (SortAlgorithmThread thread : threads) { 199 | thread.setData(array.clone()); 200 | } 201 | return true; 202 | } else { 203 | mSlidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); 204 | if (strArray.length > mCountData) { 205 | Toast.makeText(getActivity(), "Please remove " + 206 | +(strArray.length - mCountData) 207 | + " entry of array, length of array is " 208 | + strArray.length, Toast.LENGTH_LONG).show(); 209 | } else { 210 | Toast.makeText(getActivity(), "Please add " 211 | + (-strArray.length + mCountData) 212 | + " entry of array, length of array is " 213 | + strArray.length, Toast.LENGTH_LONG).show(); 214 | } 215 | 216 | return false; 217 | } 218 | } 219 | 220 | @Override 221 | protected void pauseSort() { 222 | for (AlgorithmThread thread : threads) { 223 | thread.setPaused(true); 224 | mPlay.setImageResource(R.drawable.ic_play_arrow_white_24dp); 225 | mPlayAnimation.hide(); 226 | } 227 | } 228 | 229 | @Override 230 | protected void resumeSort() { 231 | for (AlgorithmThread thread : threads) { 232 | thread.setPaused(false); 233 | } 234 | mPlay.setImageResource(R.drawable.ic_pause_white_24dp); 235 | mPlayAnimation.show(); 236 | } 237 | 238 | @Override 239 | public void onSortCompleted() { 240 | numThreadCompleted++; 241 | if (numThreadCompleted == threads.length) { 242 | if (getActivity() != null) { 243 | getActivity().runOnUiThread(new Runnable() { 244 | @Override 245 | public void run() { 246 | Toast.makeText(getActivity().getApplicationContext(), R.string.sorted, 247 | Toast.LENGTH_SHORT).show(); 248 | enableView(); 249 | mPlayAnimation.hide(); 250 | mPlay.setImageResource(R.drawable.ic_settings_backup_restore_white_24dp); 251 | } 252 | }); 253 | } 254 | } 255 | super.onSortCompleted(); 256 | 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /app/src/main/java/com/duy/algorithm/customview/SortView.java: -------------------------------------------------------------------------------- 1 | package com.duy.algorithm.customview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Path; 9 | import android.graphics.Rect; 10 | import android.os.Handler; 11 | import android.support.annotation.UiThread; 12 | import android.util.AttributeSet; 13 | import android.util.Log; 14 | import android.view.View; 15 | 16 | import com.duy.algorithm.R; 17 | 18 | /** 19 | * create by Mr.Duy on 02-Feb-17 20 | */ 21 | public class SortView extends View { 22 | 23 | public static final String TAG = "SortView"; 24 | private static final String NO_DATA = "No Data!"; 25 | private float[][] tmp = new float[2][2]; //save coordinate of two index bar 26 | private int[] array; //input data 27 | private Paint mPaint; 28 | private boolean isDrawing = false; 29 | private String name = ""; 30 | private Context context; 31 | private long mTime = 0; 32 | private int swapAPosition = -1; 33 | private int swapBPosition = -1; 34 | private int tracePosition = -1; 35 | private int targetPosition = -1; 36 | private int completePosition = -1; 37 | private int barColor = Color.WHITE; 38 | private int targetColor = Color.GREEN; 39 | private int swapAColor = Color.RED; 40 | private int swapBColor = Color.MAGENTA; 41 | private int traceColor = Color.BLUE; 42 | private int quadColor = Color.GREEN; 43 | private int completeColor = Color.GREEN; 44 | private int textInfoColor = Color.RED; 45 | private Handler handler = new Handler(); 46 | public float xA = 0; 47 | public float xB = 0; 48 | private float yA = 0; 49 | private float yB = 0; 50 | private int delta = 0; 51 | 52 | public SortView(Context context) { 53 | super(context); 54 | setup(context, null, -1); 55 | } 56 | 57 | public SortView(Context context, AttributeSet attrs) { 58 | super(context, attrs); 59 | setup(context, attrs, -1); 60 | } 61 | 62 | public SortView(Context context, AttributeSet attrs, int defStyleAttr) { 63 | super(context, attrs, defStyleAttr); 64 | 65 | setup(context, attrs, defStyleAttr); 66 | 67 | } 68 | 69 | 70 | public int getCompletePosition() { 71 | return completePosition; 72 | } 73 | 74 | public void setCompletePosition(int completePosition) { 75 | this.completePosition = completePosition; 76 | } 77 | 78 | /** 79 | * find max value in array 80 | * 81 | * @param arr - input array 82 | * @return - max value 83 | */ 84 | private int getMax(int[] arr) { 85 | int N = arr.length; 86 | int max = arr[0]; 87 | for (int i = 1; i < N; i++) { 88 | if (max < arr[i]) max = arr[i]; 89 | } 90 | return max; 91 | } 92 | 93 | public void setup(Context context, AttributeSet attrs, int defStyleAttr) { 94 | this.context = context; 95 | 96 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SortViewAttrs); 97 | 98 | barColor = a.getInteger(R.styleable.SortViewAttrs_bar_color, barColor); 99 | targetColor = a.getInteger(R.styleable.SortViewAttrs_target_color, targetColor); 100 | traceColor = a.getInteger(R.styleable.SortViewAttrs_trace_color, traceColor); 101 | quadColor = a.getInteger(R.styleable.SortViewAttrs_quad_color, quadColor); 102 | completeColor = a.getInteger(R.styleable.SortViewAttrs_complete_color, completeColor); 103 | textInfoColor = a.getInteger(R.styleable.SortViewAttrs_text_info_color, textInfoColor); 104 | swapAColor = a.getInteger(R.styleable.SortViewAttrs_swap_a_color, swapAColor); 105 | swapBColor = a.getInteger(R.styleable.SortViewAttrs_swap_b_color, swapBColor); 106 | a.recycle(); 107 | 108 | mPaint = new Paint(); 109 | mPaint.setStyle(Paint.Style.STROKE); 110 | mPaint.setColor(barColor); 111 | mPaint.setAntiAlias(true); 112 | setTextSize(20f); 113 | array = null; 114 | } 115 | 116 | /** 117 | * calculate and set text size for mPaint 118 | */ 119 | private void setTextSize(float GESTURE_THRESHOLD_DIP) { 120 | // The gesture threshold expressed in dip 121 | // Convert the dips to pixels 122 | final float scale = getContext().getResources().getDisplayMetrics().density; 123 | int mGestureThreshold = (int) (GESTURE_THRESHOLD_DIP * scale + 0.5f); 124 | 125 | mPaint.setTextSize(mGestureThreshold); 126 | } 127 | 128 | /** 129 | * draw data from array @array 130 | * 131 | * @param canvas - canvas 132 | */ 133 | @Override 134 | protected void onDraw(Canvas canvas) { 135 | super.onDraw(canvas); 136 | //if data is available 137 | if (array != null && array.length > 0) { 138 | drawArray(canvas); 139 | } else { 140 | drawNoData(canvas); 141 | } 142 | drawInfo(canvas); 143 | } 144 | 145 | /** 146 | * draw text name and mTime in top-left of view 147 | */ 148 | private void drawInfo(Canvas canvas) { 149 | mPaint.setStyle(Paint.Style.FILL); 150 | mPaint.setStrokeWidth(1.0f); 151 | mPaint.setColor(textInfoColor); 152 | setTextSize(10f); 153 | 154 | Rect rect = new Rect(); 155 | mPaint.getTextBounds("A", 0, 1, rect); 156 | 157 | int x = rect.width(); 158 | int y = rect.height() + rect.height() / 2; 159 | 160 | canvas.drawText(name, x, y, mPaint); 161 | 162 | y += (rect.height() + rect.height() / 2); 163 | canvas.drawText("Complexity: " + mTime, x, y, mPaint); 164 | } 165 | 166 | /** 167 | * draw array data 168 | * 169 | * @param canvas 170 | */ 171 | private void drawArray(Canvas canvas) { 172 | int width = getWidth(); //get width of view 173 | int height = getHeight(); //get height of view 174 | //number entry of array 175 | int N = array.length; 176 | 177 | //calculate width of bar 178 | float barWidth = width / (N + 1); 179 | mPaint.setStrokeWidth(barWidth * 0.8f); 180 | 181 | int max = getMax(array); 182 | 183 | //calculate dip per bar entry 184 | float per = height / (max + 1); 185 | 186 | //start x, start y, start y is height because axis of screen 187 | // top-left (0;0) -> right-bottom (width;height) 188 | float x = 0; 189 | float y = height; 190 | 191 | //start index 192 | int index = 0; 193 | 194 | //foreach 195 | for (int a : array) { 196 | x += barWidth;//coordinate of next bar 197 | if (index <= completePosition) { 198 | //set color for bar entry 199 | mPaint.setColor(completeColor); 200 | canvas.drawLine(x, y, x, y - (a * per), mPaint);//draw bar 201 | } else { 202 | if (index == swapAPosition) { //swap0 203 | // Log.d(TAG, "drawArray: " + swapAPosition); 204 | mPaint.setColor(swapAColor); 205 | //draw highlight bar 206 | canvas.drawLine(xA, yA, xA, yA + (a * per), mPaint); 207 | 208 | } else if (index == swapBPosition) { //swap1 209 | // Log.d(TAG, "drawArray: " + swapBPosition); 210 | mPaint.setColor(swapBColor); 211 | //draw highlight bar 212 | canvas.drawLine(xB, yB, xB, yB + (a * per), mPaint); 213 | 214 | } else if (index == tracePosition) { //trace 215 | mPaint.setColor(traceColor); 216 | canvas.drawLine(x, y, x, y - (a * per), mPaint);//draw highlight bar 217 | } else { 218 | //set color for bar entry 219 | mPaint.setColor(barColor); 220 | canvas.drawLine(x, y, x, y - (a * per), mPaint);//draw bar 221 | } 222 | if (index == targetPosition) { //target 223 | 224 | //set color for bar entry 225 | mPaint.setColor(targetColor); 226 | canvas.drawLine(x, y, x, y - (a * per), mPaint);//draw highlight bar 227 | } 228 | } 229 | index++; 230 | } 231 | if (swapAPosition != swapBPosition) { 232 | mPaint.setStyle(Paint.Style.STROKE); 233 | mPaint.setStrokeWidth(2.0f); 234 | mPaint.setColor(quadColor); 235 | Path path = new Path(); 236 | path.moveTo(xA, yA); 237 | 238 | path.quadTo(xA + Math.abs(xB - xA) * 2 / 3, y - max * per, xB, yB); 239 | canvas.drawPath(path, mPaint); 240 | } 241 | } 242 | 243 | private void drawNoData(Canvas canvas) { 244 | mPaint.setStyle(Paint.Style.FILL); 245 | mPaint.setStrokeWidth(1.0f); 246 | mPaint.setColor(textInfoColor); 247 | canvas.drawText(NO_DATA, getWidth() / 2, getHeight() / 2, mPaint); 248 | } 249 | 250 | public void setTracePosition(int index) { 251 | this.tracePosition = index; 252 | invalidate(); 253 | } 254 | 255 | public void setArray(int[] arr) { 256 | this.array = arr; 257 | } 258 | 259 | @UiThread 260 | public void setSwapPosition(int i1, int i2) { 261 | setSwapPosition(i1, i2, true); 262 | } 263 | 264 | @UiThread 265 | public void setSwapPosition(int i1, int i2, boolean redraw) { 266 | if (i1 < 0 || i2 < 0) { 267 | swapAPosition = i1; 268 | swapBPosition = i2; 269 | if (redraw) invalidate(); 270 | return; 271 | } 272 | if (i1 < i2) { 273 | swapAPosition = i1; 274 | swapBPosition = i2; 275 | } else { 276 | swapAPosition = i2; 277 | swapBPosition = i1; 278 | } 279 | 280 | int width = getWidth(); //get width of view 281 | int height = getHeight(); //get height of view 282 | int N = array.length; 283 | float barWidth = width / (N + 1); 284 | int max = getMax(array); 285 | //calculate pixel per bar entry 286 | float per = height / (max + 1); 287 | 288 | xA = barWidth * (swapAPosition + 1); 289 | yA = height - (array[swapAPosition] * per); 290 | 291 | xB = barWidth * (swapBPosition + 1); 292 | yB = height - (array[swapBPosition] * per); 293 | delta = (int) Math.abs(xB - xA); 294 | if (redraw) invalidate(); 295 | } 296 | 297 | 298 | public int getSizeArray() { 299 | return array.length; 300 | } 301 | 302 | public String getName() { 303 | return name; 304 | } 305 | 306 | public void setName(String name) { 307 | this.name = name; 308 | } 309 | 310 | public void setName(int id) { 311 | this.name = context.getString(id); 312 | } 313 | 314 | @UiThread 315 | public void setTargetPosition(int targetPosition) { 316 | this.targetPosition = targetPosition; 317 | invalidate(); 318 | } 319 | 320 | public void setTime(long time) { 321 | this.mTime = time; 322 | } 323 | 324 | public void addTimeUnit(long time) { 325 | this.mTime += time; 326 | } 327 | 328 | /** 329 | * change value of xA, xB 330 | */ 331 | @UiThread 332 | public void incPositionSwap(float v) { 333 | xA += v; 334 | xB -= v; 335 | invalidate(); 336 | } 337 | 338 | public int getDelta() { 339 | return delta; 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | --------------------------------------------------------------------------------