Разработка аналитического инструментария к мобильному учётному приложению для велосипедиста

Модификация приложения "Дневник Велосипедиста", предназначенного для учёта данных спортсмена. Получение расширенной информации для регулировки тренировочной нагрузки в режиме реального времени. Оценка данных по видам активности, построение графиков.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 02.09.2018
Размер файла 4,5 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Определение элементов CheckBox и массива CheckBox'ов:

CheckBox cb_pulseM, cb_pulseA, cb_pulseB, cb_calories, cb_cadence, cb_capacity, cb_speedM, cb_speedA, cb_distance, cb_accent, cb_descend, cb_series, cb_repetition, cb_weight; CheckBox[] checkboxes = new CheckBox[14];

Заполнение массива управляющих элементов:

checkboxes[0] = cb_pulseM; checkboxes[1] = cb_pulseA; checkboxes[2] = cb_pulseB; checkboxes[3] = cb_calories; checkboxes[4] = cb_cadence; checkboxes[5] = cb_capacity; checkboxes[6] = cb_speedM; checkboxes[7] = cb_speedA; checkboxes[8] = cb_distance; checkboxes[9] = cb_accent; checkboxes[10] = cb_descend; checkboxes[11] = cb_series; checkboxes[12] = cb_repetition; checkboxes[13] = cb_weight;

Добавление столбцов в таблицу при их выборе в дополнительном всплывающем диалоге:

TableRow headerTableRow = (TableRow) tableLayout.getChildAt(0); int indexOfChild = 3; for (int i=0; i<checkboxes.length;i++) { if (checkboxes[i].isChecked()) { if (additionalHeaders[i].getVisibility() == View.VISIBLE) isSomethingHaveAlreadyVisible = true; else { headerTableRow.addView(additionalHeaders[i], indexOfChild); int margin = getResources().getDimensionPixelSize(R.dimen.header_textView_margin); TableRow.LayoutParams lp = (TableRow.LayoutParams) additionalHeaders[i].getLayoutParams(); lp.setMargins(margin,margin,margin,margin); additionalHeaders[i].setVisibility(View.VISIBLE); } visibleHeaders[i] = true; nothingChecked = false; indexOfChild++; } else { if (additionalHeaders[i].getVisibility() != View.GONE) { headerTableRow.removeViewAt(indexOfChild); additionalHeaders[i].setVisibility(View.GONE); whatWasGone.add(headersNames[i]); visibleHeaders[i]=false; } } }

После долгой отладки модуля был достигнут желаемый результат: ошибок больше нет, таблица отображается как было запланировано при любых изменениях. Нельзя исключать возникновения новых ошибок, поэтому при их возникновении необходимо будет снова вернуться к отладке этого модуля.

1.13 Проектирование нового модуля

UML-диаграммы

При проектировании нового аналитического модуля будут использованы диаграммы прецедентов, активности и описание прецедентов, подготовленные на этапе разработки учётного модуля системы. Диаграммы расположены в прил. A.

Алгоритмы

Ниже описаны алгоритмы для двух фрагментов одной функции.

1) Формирование списка списков тренировок для заполнения элемента расширенного списка, в котором верхний уровень - даты, а вложенные элементы - тренировки на эту дату.

Если есть считанные данные, то проверяем существование текущей даты в списке дат. Если датf, то переменной newDate присваивается значение false и цикл принудительно прерывается break, иначе true. Если newDate, то index =1 (номер записи для даты). Получаем значение тренировки из БД, добавляем в список тренировок. Если newDate, то добавляем в массив дат (вспомогательная переменная для сортировки) значение даты, эту же дату добавляем в список дат под ключом groupDate. Дальше проверяем размер списка элементов - детей для даты, если он не пустой, то добавляем в список списка тренировок по датам список тренировок. Обновляем список тренировок. Дальше добавляем тренировку в список тренировок по ключам index, name, specification. Дальше получаем значение идентификатора записи, добавляем в список идентификаторов (для последующего использования при нажатии на тренировку). Когда данные уже закончились добавляем список тренировок в список списка тренировок по датам, если первый не пустой.

2) Синхронная сортировка трёх списков различной сложности (список списков тренировок, список тренировок, список целых значений):

Задаём временные переменные списка тренировок по датам, списка тренировок и списка целых чисел для хранения идентификаторов записей. Т.к. все списки обновлялись во время считывания синхронно, то каждый новый элемент списков относится к определённой дате, т.е. сортировать нужно также синхронно. Задаём внешний цикл для дат по количеству элементов во вспомогательном цикле. Вложенный цикл также идём по датам в списке дат, где проверяем условие равенства дат. В тот момент, когда даты будут равны, индекс внутреннего цикла будет означать индекс списка тренировок в списке списка тренировок, который соответствует отсортированной дате. Записываем этот список во временную переменную списка списков тренировок, аналогично переписываем дату под найденным индексом во временный список дат. Дальше открывается новый цикл для перераспределения идентификаторов. Для этого понадобится новая переменная номера следующего элемента, который изменяется на единицу, каждый раз в цикле и на количество списков тренировок под найденным индексом, если в первом найденном списке текущая дата не соответствует искомой. Во втором вложенном цикле также происходит перезапись идентификаторов во временный список. Переписываем основные списки отсортированными для следующего наполнения расширенного списка в окне Истории в порядке убывания дат.

Проектирование интерфейса

На главном экране должны выводиться суммарные показатели по выбранному сезону, для этого необходимо добавить соответствующие управляющие элементы на экран (см. рис. 4.1).

Экран Статистики должен содержать выбор параметров, по которым будет реализована возможность строить графики, а также выбор периода, за который будут построены графики, с возможностью выбора установленных периодов: неделя, 10 дней, 2 недели, месяц, 3 месяца, полгода, год, всё время и другое, при выборе которого можно задавать диапазон дат, по которым хочется увидеть график. Дополнительные кнопки сохранения и отправки графика тоже добавим на экран, но действия по нажатию на эти кнопки будет реализованы по возможности (см. рис. 4.2).

Экран Истории включает в себя строку, о том, что база данных пуста, если никакие данные не были сохранены (см. рис. 4.3), иначе появляется расширенный список со вложенным списком. Верхний уровень должен содержать в себе дату, когда были тренировки, а при открытии верхнего уровня должны появляться все тренировки за выбранный день (см. рис. 4.4).

Проектирование запросов к БД

Использование базы данных SQLite привело к тому, что пришлось некоторые сложные типы данных заменить на строки (текст), а также использование некоторых конструкций запросов, типа функций выделения подстроки из строки (Substring) не поддерживаются при выполнении запроса. Поэтому проектирование последующих запросов будет связано использованием стандартной конструкции «SELECT … FROM … WHERE … ORDER BY …». Простая конструкция позволит получить все данные, которые необходимы, а далее эти данные уже будут обработаны в коде. Такой подход позволит снизить затраты во времени на обращение к базе данных и избежать проблем с отладкой запроса (код отладить намного проще).

На данном этапе необходимо составить 4 запроса:

1. Получение дат для определения наличия данных по сезонам (например, сезон 2017, сезон 2018). Данный запрос должен быть использован для заполнения выпадающего списка на главном экране, при выборе элемента, по значению которого должны обновляться данные общего километража, расстоянию, которое было преодолено на плавании, количестве подъёмов на трамплины. Получается, что необходимо получить только даты из таблицы Records, причём желательно получить даты без повторений, т.е. использовать функцию Distinct.

2. Для раздела Истории тренировок необходимо создать запрос, подобный запросу, используемому для заполнения имеющихся записей на определённую дату (при добавлении или изменении записей есть список, в котором используется подобный запрос). Необходимость создания подобного запроса связана с тем, что нужно получить ещё и дату, помимо краткого описания, вида занятия и идентификатора, поэтому запрос можно скопировать и добавить поле Дата.

3. Получение даты, расстояния и количества повторов по указанному виду тренировки/соревнования. При этом сложение параметров будет осуществляться программно, исходя из того, к какому сезону относится запись, т.е. будет проверятся год из даты, а т.к. дата хранится в строковом типе, то будет сравниваться 4 последних символа строки даты с выбранным сезоном.

4. Ещё один запрос - для отображения графиков по выбранным параметрам: расстояние, пульс максимальны, скорость средняя, оценка самочувствия. В этот запрос также нужно включить дополнительные поля: дату, время, максимальную скорость и средний пульс. Средний пульс будет использоваться для подсчёта интенсивности тренировки, а время и максимальная скорость останется на тот случай, если для расчёта интенсивности тренировки будет определена более сложная формула.

1.14 Листинг

Интерфейс

Далее будет представлены фрагменты XML-разметки, описывают интерфейс созданных активностей либо дополнений к существующей.

1) Добавленные элементы к главному окну.

· строка «Итого за сезон:» и выпадающий список для выбора интересующего сезона, выделенные в отдельную область для горизонтального расположения элементов.

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:text="@string/total_season_text" android:textSize="18sp" android:textStyle="bold" /> <Spinner android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:id="@+id/choose_season"> </Spinner> </LinearLayout>

Дальше в отдельных блоках выводятся вид тренировки (шоссе, МТБ, лыжи, бег, плавание, трамплины) и общий велокилометраж, как текстовый элемент, после которого в отдельном текстовом элементе выводится знак равно, после которого располагается текстовое поле, в котором будет выводится значение, полученное из БД, и дальше снова текстовый элемент с единицей измерения. Ниже представлен такой фрагмент для блока, относящегося к данным по шоссе, остальные блоки выполнены аналогичным образом.

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:text="@string/form_road" android:textSize="16sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:layout_margin="5dp" android:text="="/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:layout_margin="5dp" android:text="0" android:id="@+id/total_road"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:layout_margin="5dp" android:text="@string/kilometre"/> </LinearLayout>

2) Разметка окна для отображения Истории.

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_history" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="markvirervladlenadmitrievna.cyclistdiary.HistoryActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:textSize="24sp" android:id="@+id/empty_message" android:text="@string/empty_message" android:gravity="center_horizontal|center_vertical" android:textColor="@color/colorRed"/> <ExpandableListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/historyExpandableList" android:text=""> </ExpandableListView> </LinearLayout> </RelativeLayout>

3) Разметка окна Статистики.

Основной элемент этого окна - элемент построения графиков GraphView, полная разметку см. прил. B.

<com.jjoe64.graphview.GraphView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/graph_view" android:padding="16dp" />

Алгоритмы

1) Формирование списка списков тренировок:

do { _date = cursor.getString(dateIndex); boolean newDate = true; for (int i=0;i<dates.size();i++) { if

(

dates.get(i).containsValue(_date)) { newDate = false; break;

} else newDate = true; } if (newDate)

index=1; exercise=new Exercise(index, this.getString(cursor.getInt(tIndex)) + ", " + this.getString(cursor.getInt(fIndex)), cursor.getString(dIndex)); ex.add(exercise); if (newDate) { map = new HashMap<>(); map.put("groupDate", _date); datesMass.add(_date); dates.add(map); if (

childDataItem.size()!=0) childDataList.add(childDataItem); childDataItem = new ArrayList<>(); }

map = new HashMap<>(); map.put("index", String.valueOf(exercise.getIndex())); map.put("name", exercise.getName()); map.put("specification", exercise.getSpecification()); childDataItem.add(map);

int _id_record = cursor.getInt(idIndex); ids.add(_id_record); index = index + 1; } while (cursor.moveToNext());

if

(

childDataItem.size()!=0) childDataList.add(childDataItem

);

2) Сортировка массива дат по убыванию даты с переопределением метода compare, который сравнивает две строки, преобразованные в даты.

Collections.sort(datesMass, new Comparator<String>() { @Override public int compare(String o1, String o2) { Date d1 = new Date(); Date d2 = new Date(); try { d1 = sdf.parse(o1); d2 = sdf.parse(o2); }

catch (ParseException e) { e.printStackTrace(); } return d2.compareTo(d1); } });

3) Синхронная сортировка трёх списков различной сложности:

ArrayList<ArrayList<Map<String, String>>> tempList = new ArrayList<>(); ArrayList<Map<String, String>> tempDates = new ArrayList<>(); ArrayList<Integer> tempIds = new ArrayList<>();

//сортировка индексов для работы с бд после сортировки дат и списка тренировок по датам

int nextElementIndex = 0; for(int i = 0; i<datesMass.size();i++) { nextElementIndex =0; for (int j = 0; j < dates.size(); j++) { if (dates.get(j).containsValue(datesMass.get(i))) { tempList.add(childDataList.get(j)); tempDates.add(dates.get(j)); for (int k=0; k<childDataList.get(j).size();k++) { tempIds.add(ids.get(nextElementIndex)); nextElementIndex++; } } else nextElementIndex += childDataList.get(j).size(); } }

childDataList = tempList; dates = tempDates; ids = tempIds;

Запросы

На основании спроектированных запросов были написаны следующие методы, для вызова в программе:

public static String getShortDescriptionExerciseForHistory() { return "SELECT TypesForms.cTYPE AS cTYPE, TypesForms.cFORM AS cFORM, " + CyclistContract.RecordsEntry.COLUMN_RECORD_DATE + " AS DATE," + CyclistContract.RecordsEntry.COLUMN_RECORD_SHORT_DESCRIPTION+" AS DESCRIPTION, " + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS+ "." +CyclistContract.RecordsEntry._ID + " AS _ID_records " + "FROM ((" + getTypesForms() + ") AS TypesForms) INNER JOIN " + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS + " ON " + CyclistContract.RecordsEntry.COLUMN_RECORD_ID_FORM_IN_RECORDS+ "=TypesForms._ID "+ "Order By " + CyclistContract.RecordsEntry.COLUMN_RECORD_DATE; }

public static String getDatesForSeasons() { return "SELECT Distinct(" + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS + "." + CyclistContract.RecordsEntry.COLUMN_RECORD_DATE + ") " + "FROM " + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS; }

public static String getTotalKm(Integer form) { return "SELECT " + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS + "." + CyclistContract.RecordsEntry.COLUMN_RECORD_DATE + " AS DATE, " + CyclistContract.AdditionalsEntry.COLUMN_ADDITIONALS_DISTANCE + " AS DISTANCE, " + CyclistContract.PowersEntry.COLUMN_POWERS_SERIES + " AS SERIES " + "FROM ((((" + CyclistContract.LapsEntry.TABLE_NAME_LAPS + " LEFT OUTER JOIN " + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS + " ON " + CyclistContract.LapsEntry.COLUMN_LAPS_ID_RECORD_IN_LAPS + "=" + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS + "." + CyclistContract.RecordsEntry._ID + ") LEFT OUTER JOIN " + CyclistContract.FormsEntry.TABLE_NAME_FORMS + " ON " + CyclistContract.RecordsEntry.COLUMN_RECORD_ID_FORM_IN_RECORDS + "=" + CyclistContract.FormsEntry.TABLE_NAME_FORMS+ "." + CyclistContract.FormsEntry._ID+ ") LEFT OUTER JOIN " + CyclistContract.AdditionalsEntry.TABLE_NAME_ADDITIONALS + " ON " + CyclistContract.LapsEntry.COLUMN_LAPS_ID_ADDITIONAL_IN_LAPS + "=" + CyclistContract.AdditionalsEntry.TABLE_NAME_ADDITIONALS + "." + CyclistContract.AdditionalsEntry._ID + ") LEFT OUTER JOIN " + CyclistContract.PowersEntry.TABLE_NAME_POWERS + " ON " + CyclistContract.LapsEntry.COLUMN_LAPS_ID_POWER_IN_LAPS + "=" + CyclistContract.PowersEntry.TABLE_NAME_POWERS + "." + CyclistContract.PowersEntry._ID + ") " + "WHERE " + CyclistContract.FormsEntry.TABLE_NAME_FORMS + "." + CyclistContract.FormsEntry.COLUMN_FORMS_CLASSIFICATION_FORM + "=" + form; }

public static String getEveryDataForStatistics() { return "SELECT "+ CyclistContract.RecordsEntry.COLUMN_RECORD_DATE + " AS DATE, " + CyclistContract.AdditionalsEntry.COLUMN_ADDITIONALS_DISTANCE + " AS DISTANCE, " + CyclistContract.FunctionalsEntry.COLUMN_FUNCTIONALS_PULSE_MAX +" AS PULSE_MAX, " + CyclistContract.AdditionalsEntry.COLUMN_ADDITIONALS_SPEED_AVERAGE+" AS SPEED_AVG, " +CyclistContract.LapsEntry.COLUMN_LAPS_FEELING_MARK + " AS MARK_FEEL, " + CyclistContract.LapsEntry.COLUMN_LAPS_TIME + " AS TIME, " + CyclistContract.AdditionalsEntry.COLUMN_ADDITIONALS_SPEED_MAX +" AS SPEED_MAX, " + CyclistContract.FunctionalsEntry.COLUMN_FUNCTIONALS_PULSE_AVERAGE+" AS PULSE_AVG " + "FROM (((" + CyclistContract.LapsEntry.TABLE_NAME_LAPS + " LEFT OUTER JOIN " + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS + " ON " + CyclistContract.LapsEntry.COLUMN_LAPS_ID_RECORD_IN_LAPS + "=" + CyclistContract.RecordsEntry.TABLE_NAME_RECORDS + "." + CyclistContract.RecordsEntry._ID + ") LEFT OUTER JOIN " + CyclistContract.FunctionalsEntry.TABLE_NAME_FUNCTIONALS + " ON " + CyclistContract.LapsEntry.COLUMN_LAPS_ID_FUNCTIONAL_IN_LAPS + "=" + CyclistContract.FunctionalsEntry.TABLE_NAME_FUNCTIONALS + "." + CyclistContract.FunctionalsEntry._ID + ") LEFT OUTER JOIN " + CyclistContract.AdditionalsEntry.TABLE_NAME_ADDITIONALS + " ON " + CyclistContract.LapsEntry.COLUMN_LAPS_ID_ADDITIONAL_IN_LAPS + "=" + CyclistContract.AdditionalsEntry.TABLE_NAME_ADDITIONALS + "." + CyclistContract.AdditionalsEntry._ID + ") " + "ORDER BY " + CyclistContract.RecordsEntry.COLUMN_RECORD_DATE; }

Графики

В прил. C приведён код метода обновления элемента разметки GraphView при каком-либо действии пользователя: выбирает ли он какой-либо параметр, снимает с него галочку или меняет период, за который желает отобразить диаграмму.

Пример построенных диаграмм можно увидеть ниже (см. рис. 4.5, рис. 4.6).

Конфигурации системы

В первую очередь был изменён шрифт в приложении на тот, что задан в Material Design, а именно на шрифт семейства Roboto. Для этого были скачаны шрифты Roboto и добавлены в папку приложения assets, где была создана директория fonts, куда уже были перемещены шрифты.

Затем создан класс-утилита, создающий TyperFace и конвертирующий все элементы в окнах в нужный шрифт.

public class TypefaceUtil { public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) { try { final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets); final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride); defaultFontTypefaceField.setAccessible(true); defaultFontTypefaceField.set(null, customFontTypeface); } catch (Exception e) { String str = "Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride; Log.e("font",str); } } }

Далее создан класс-наследник Application, в котором переопределён класс TypeFaceUtils для того, чтобы можно было охватить всю программу.

public class MyApp extends Application { @Override public void onCreate() { TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/Roboto-Regular.ttf"); } }

Последний шаг - добавить в файл styles.xml строку, назначающую шрифт на все элементы приложения.

<style name="AppTheme" parent="Theme.AppCompat.Light"> <!-- Customize your theme here. --> <item name="actionMenuTextColor">@color/colorBlack</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:windowFullscreen">true</item> <item name="@attr/customTextViewStyleForCell">@style/cellStyle</item> <item name="android:typeface">serif</item> </style>

Заключение

Основные поставленные в работе задачи были успешно выполнены. Приложение готово к использованию. В приложении реализованы и отлажены функции учёта данных и аналитики. Ниже представлены основные выполненные шаги на основе анализа требований потенциальных пользователей:

· появилась возможность получения агрегированных данных по основным видам тренировок/соревнований (была изменена главная страница Приложения, полный код см. в прил. D);

· для удобства оценки прогресса для пользователя строятся графики;

· можно выбирать интересующую тренировку для более детального просмотра из истории и др.

За время разработки была изучена новая библиотека GraphView, были подобраны нетривиальные алгоритмы синхронной сортировки сложных типов данных, а также были усовершенствованы навыки программирования на Java, XML, SQL.

Данное приложение выполнено для учебных задач, поэтому на данный момент требуются такие усовершенствования, как добавление функций экспорта/импорта данных, сохранения и отправки графиков в виде картинки, изменение некоторых деталей интерфейса и реализация пользовательской настройки приложения.

Библиографический список

11. ВелоЖизнь. Тренировка велосипедиста. [Электронный ресурс]. Режим доступа: http://boldarev.ru/trenirovka-velosipedista/. Дата обращения: 09 января 2017 г.

12. Галушкин А.И. Нейронные сети: основы теории. М.: Горячая линия Телеком, 2012. 496 с.

13. Джо Фрил. Библия велосипедиста // М.: Изд-во Манн, Иванов, Фербер, 2011. 419 с. (перевод с англ.)

14. Дневник. [Электронный ресурс]. Режим доступа: http://sportsdestiny.com/content.php?id=41&tbl=tbl_database&descr=main_text&name=дневник. Дата обращения: 09 января 2017 г.

15. Зобнина М. Методическое пособие по курсу «Интернет-предпринимательство»: под редакцией М.Р.Зобниной. - [б. м.]: Издательские решения, 2016. - 266 с. - ISBN_978_5-4474-8778-2.

16. Как вести дневник тренировок? [Электронный ресурс]. Режим доступа: http://omskvelo.ru/index.php?/topic/6583-как-вести-велосипедный-тренировочный-дневник/. Дата обращения: 09 января 2017 г.

17. Паттерны для новичков: MVC vs MVP vs MVVM. [Электронный ресурс]. Режим доступа: https://habrahabr.ru/post/215605/. Дата обращения: 19 февраля 2018 г.

18. Разработка приложения для учёта тренировочного процесса велосипедиста / Под ред. Марквирер В.Д. - Пермь: Пермский филиал Национального исследовательского университета - Высшей школы экономики, Кафедра информационных технологий в бизнесе, 2017. - 85 с.: ил.

19. Тренировки и велосипеды: планирование программы подготовки и ведение дневника. [Электронный ресурс]. Режим доступа: http://travelbooze.com/trenirovki-i-velosipedyi-planirovanie-programmyi-podgotovki-i-vedenie-dnevnika/. Дата обращения: 09 января 2017 г.

20. Ясницкий Л.Н. Искусственный интеллект. Элективный курс : учебное пособие. М.: БИНОМ. Лаборатория знаний, 2011. 197 с. : ил.

21. Ясницкий Л.Н. Интеллектуальные системы. : учебник. М.: Лаборатория знаний, 2016. 221 с. : ил. - (Учебник для высшей школы).

22. Ahmadi, A., Mitchell, E., Richter, C., et al. (2015). Towards automatic activity classification and movement assessment during a sports training session. IEEE Internet of Things Journal, Vol. 2, iss. 1, pp. 23-32, DOI: 10.1109/JIOT.2014.2377238.

23. Berentowicz, M., Zaj№c, P., Zabierowski W. (2017). The use of mobile technology on the example of health and sports statistics application. Polyana Svalyava (Zakarpattya): Ukraine MEMSTECH, pp. 187-189.

24. Difference Between Android Studio and Eclipse. (2018 January 26). Retrieved (date), from http://differencebetween.com/difference-between-android-studio-andvs-eclipse/

25. Dorosh, N., Kuchmiy, H., Boyko, O., et al. (2016). Development the software applications for mobile medical systems based on OS Android. TCSET, pp. 808-810.

26. Friel, J. (2009). The cyclist's training bible. 4th ed.

27. Garcнa, B., Welford, J., Smith, B. (2015). Using a smartphone app in qualitative research: the good, the bad and the ugly. SAGE, Qualitative Research, pp. 1-18, DOI: 10.1177/1468794115593335.

28. GraphView - open source graph plotting library for Android. Jonas Gehring. http://www.android-graphview.org/.

29. Iervolino, R., Bonavolontа, F., Cavallari, A. (2017). A wearable device for sport performance analysis and monitoring. IEEE Conferences, pp. 1-6.

30. La, H.J., Kim, S.D. (2010). Balanced MVC architecture for developing service-based mobile applications. IEEE Computer Society, pp. 292 299.

31. Lamiaa, A. et al. (2017). Real-time face detection and tracking on mobile phones for criminal detection. IEEE.

32. Martinez-Nicolas, A., Muntaner-Mas, A., Ortega, F.B. (2016). Runkeeper: a complete app for monitoring outdoor sports. Br J Sports Med Published Online First, DOI:10.1136/bjsports-2016-096678.

33. MPAndroidChart. Philipp Jahoda. https://github.com/PhilJay/MPAndroidChart

34. Seshadri, D., Drummond, C., Craker, J., Rowbottom, J., Voos, J. (2017). New integrated technologies allow coaches, physicians, and trainers to better understand the physical demands of athletes in real time. IEEE Pulse, Vol. 8, iss. 1, pp. 38-43, DOI: 10.1109/MPUL.2016.2627240.

35. WilliamChart. Diogo Bernardino. https://github.com/diogobernardino/WilliamChart

36. Yanchapaxi, P., Tipantuсa, C., Calderуn, X. (2017). Wearable system for monitoring of human physical activities. IEEE.

37. Zeng, J., Jia, J. (2017). The impact of big data on school sports and competitive sports. Chinese Automation Congress (CAC), pp. 596-599.

38. Zhao, J., Freeman, B., Li, M. (2016). Can mobile phone apps influence people's health behavior change? An evidence review. Journal of medical internet research, Vol. 18, iss. 11, e287, pp.1-12, DOI: 10.2196/jmir.5692.

Приложение

Диаграммы UML

Рисунок А.1. Описание прецедента «Редактировать тренировку»

Рисунок А.2. Описание прецедента «Удалить тренировку»

Рисунок А.3. Описание прецедента «Отправить данные»

Рисунок А.4. Описание прецедента «Обновить данные»

Рисунок А.5. Описание прецедента «Посмотреть историю тренировок»

Рисунок А.6. Описание прецедента «Посмотреть данные по определённой тренировке»

Рисунок А.7. Описание прецедента «Посмотреть статистику»

Рисунок А.8. Описание прецедента «Экспорт выбранной статистики в Excel, IMG, PDF»

Рисунок А.9. Описание прецедента «Проверить соединение с Интернетом»

Рисунок А.10. Диаграмма последовательности для прецедента «Изменить тренировку»

Рисунок А.11. Диаграмма последовательности для прецедента «Удалить тренировку»

Рисунок А.12. Диаграмма последовательности для прецедента «Отправить данные» (синхронизация)

Рисунок А.13. Диаграмма последовательности для прецедента «Обновить данные»

Рисунок А.14. Диаграмма последовательности для прецедента «Посмотреть историю тренировок»

Рисунок А.15. Диаграмма последовательности для прецедента «Посмотреть данные по определённой тренировке»

Рисунок А.16. Диаграмма последовательности для прецедента «Посмотреть статистику»

Рисунок А.17. Диаграмма последовательности для прецедента «Экспорт выбранной статистики в Excel, IMG, PDF»

Рисунок А.18. Диаграмма последовательности для прецедента «Проверить соединение с Интернетом»

Приложение

Разметка StatisticLayout

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_statistic" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="markvirervladlenadmitrievna.cyclistdiary.StatisticActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_horizontal" android:weightSum="2"> <LinearLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/parameters" android:textSize="18sp"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/additional_distance" android:textSize="16sp" android:id="@+id/cb_distance" android:foregroundGravity="center" android:textColor="@android:color/black"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/functional_pulseM" android:textSize="16sp" android:id="@+id/cb_pulseM" android:foregroundGravity="center" android:textColor="@android:color/holo_blue_dark"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/additional_speedA" android:textSize="16sp" android:id="@+id/cb_speedA" android:foregroundGravity="center" android:textColor="@color/colorPrimaryDark"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/feels" android:textSize="16sp" android:id="@+id/cb_feels" android:foregroundGravity="center" android:textColor="@android:color/holo_orange_dark"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/intensity" android:textSize="16sp" android:id="@+id/cb_intensity" android:foregroundGravity="center" android:textColor="@android:color/holo_purple"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:orientation="vertical" android:layout_weight="1"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="start"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/period" android:textSize="18sp"/> <Spinner android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/period_spinner"> </Spinner> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:id="@+id/from" android:layout_gravity="start"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:text="@string/from"/> <Button android:id="@+id/from_date" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:maxLines="1" android:textColor="@color/colorBlack" android:textAlignment="center" android:textAllCaps="false" android:textSize="16sp" android:gravity="center" android:paddingLeft="5dp" android:paddingRight="5dp" android:background="@color/transparent" android:text="дата"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:id="@+id/to" android:layout_gravity="start"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:text="@string/to"/> <Button android:id="@+id/to_date" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:maxLines="1" android:textColor="@color/colorBlack" android:textAlignment="center" android:textAllCaps="false" android:textSize="16sp" android:gravity="center" android:paddingLeft="5dp" android:paddingRight="5dp" android:background="@color/transparent" android:text="дата"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:weightSum="2"> <Button android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="@string/save" android:id="@+id/save_picture" android:layout_gravity="bottom"/> <Button android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="@string/share" android:id="@+id/share_picture" android:layout_gravity="bottom"/> </LinearLayout> </LinearLayout> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.jjoe64.graphview.GraphView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/graph_view" android:padding="16dp" /> </RelativeLayout> </LinearLayout> </RelativeLayout>

Метод обновления области диаграмм

private void refreshGraph()

{graphView.removeAllSeries(); graphView.getSecondScale().removeAllSeries(); Double maxYValue = 0.0; for(int c = checkBoxes.length-1; c>=0;c--) { if (checkBoxes[c].isChecked()) { if (!databaseValues.isEmpty()) { ArrayList<Double> doubleValues = new ArrayList<Double>(); ArrayList<Date> axleDates = new ArrayList<Date>(); Date from = new Date(), to = new Date(); try { from = sdf.parse(from_button.getText().toString()); to = sdf.parse(to_button.getText().toString()); } catch (ParseException e) { e.printStackTrace(); } double value; do { value = 0.0; if (dates.contains(sdf.format(to))) { int index = dates.indexOf(sdf.format(to)); ArrayList<String[]> elements = databaseValues.get(index); for (int i = 0; i < elements.size(); i++) { switch (c) { case 1: { if (!elements.get(i)[c].isEmpty()) if (Double.parseDouble(elements.get(i)[c]) > value) value = Double.parseDouble(elements.get(i)[c]); }; break; case 0: case 2: case 3: { if (!elements.get(i)[c].isEmpty()) value += Double.parseDouble(elements.get(i)[c]); else value += 0.0; }; break; case 4: { if (!elements.get(i)[elements.get(i).length - 1].isEmpty()) value += Double.parseDouble(elements.get(i)[elements.get(i).length - 1]); else value += 0.0; }; break; } } if (c!=0 && c!=1) { value = value/elements.size(); if (c==4) { value = value/220*100; } } doubleValues.add(value); } else doubleValues.add(0.0); axleDates.add(to); String[] mass = sdf.format(to).split("\\."); int day = Integer.parseInt(mass[0]); int month = Integer.parseInt(mass[1]); int year = Integer.parseInt(mass[2]); try { to = sdf.parse(minusDay(day, month, year)); } catch (ParseException e) { e.printStackTrace(); } } while (to.compareTo(from) >= 0); Collections.reverse(axleDates); Collections.reverse(doubleValues); DataPoint[] dp = new DataPoint[doubleValues.size()]; for (int i = 0; i < doubleValues.size(); i++) dp[i] = new DataPoint(axleDates.get(i), doubleValues.get(i)); LineGraphSeries<DataPoint> series = new LineGraphSeries<>(); BarGraphSeries<DataPoint> seriesBar = new BarGraphSeries<>(); if (c!=4) { series = new LineGraphSeries<>(dp); series.setColor(colors[c]); series.setTitle(titles[c]); if (!series.isEmpty() && !graphView.getSeries().contains(series)) if (c != 3) graphView.addSeries(series); else { graphView.getSecondScale().addSeries(series); } } else{ seriesBar = new BarGraphSeries<>(dp); seriesBar.setColor(colors[c]); seriesBar.setTitle(titles[c]); seriesBar.setSpacing(15); if (!seriesBar.isEmpty() && !graphView.getSeries().contains(seriesBar)) graphView.addSeries(seriesBar); } graphView.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(context)); graphView.getGridLabelRenderer().setNumHorizontalLabels(3); graphView.getViewport().setMinX(from.getTime()); try { to = sdf.parse(to_button.getText().toString()); }

catch (ParseException e) { e.printStackTrace(); } graphView.getViewport().setMaxX(to.getTime()); graphView.getViewport().setXAxisBoundsManual(true); graphView.getGridLabelRenderer().setHumanRounding(true); graphView.getGridLabelRenderer().setNumVerticalLabels(10); graphView.getViewport().setMinY(0); if (c!=3)

{ if (maxYValue < Collections.max(doubleValues)) maxYValue = Collections.max(doubleValues); graphView.getViewport().setMaxY(maxYValue);

} else { graphView.getSecondScale().setMaxY(Collections.max(doubleValues)); graphView.getSecondScale().setMinY(0); } graphView.getViewport().setYAxisBoundsManual(true); } } } }

Код класса «MainActivity»

public class MainActivity extends AppCompatActivity { Intent intent; SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy"); String date; Spinner chooseSeason; CyclistDbHelper dbHelper; SQLiteDatabase database; TextView roadKm, mtbKm, skiKm, swimKm, runKm, jumpTimes, mileage; TextView[] totals; Integer[] whatTotalsReferences; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); dbHelper = new CyclistDbHelper(MainActivity.this); database = dbHelper.getReadableDatabase(); setContentView(R.layout.activity_main); roadKm = (TextView) findViewById(R.id.total_road); mtbKm = (TextView) findViewById(R.id.total_mtb); skiKm = (TextView) findViewById(R.id.total_skiing); runKm = (TextView) findViewById(R.id.total_running); swimKm = (TextView) findViewById(R.id.total_swimming); jumpTimes = (TextView) findViewById(R.id.total_uptoskijump); mileage = (TextView) findViewById(R.id.total_velo); mileage.setText("0"); totals = new TextView[6]; totals[0]=roadKm; totals[1]=mtbKm; totals[2]=skiKm; totals[3]=runKm; totals[4]=swimKm; totals[5]=jumpTimes; whatTotalsReferences = new Integer[12]; whatTotalsReferences[0] = R.string.form_road; whatTotalsReferences[1] = R.string.form_roadrace; whatTotalsReferences[2] = R.string.form_cyclocross; whatTotalsReferences[3] = R.string.form_cyclocrossrace; whatTotalsReferences[4] = R.string.form_mtb; whatTotalsReferences[5] = R.string.form_mtbrace; whatTotalsReferences[6] = R.string.form_skiing; whatTotalsReferences[7] = R.string.form_skiingrace; whatTotalsReferences[8] = R.string.form_running; whatTotalsReferences[9] = R.string.form_swimming; whatTotalsReferences[10] = R.string.form_swimming_time; whatTotalsReferences[11] = R.string.form_uptoskijump; date = sdf.format(new Date()); TextView phrase = (TextView) findViewById(R.id.phrase); phrase.setText("Если меня что-то двигает вперёд,\nто только моя слабость,\nкоторую я ненавижу\nи превращаю в мою силу.\n\n© Майкл Джордан"); ImageButton add = (ImageButton) findViewById(R.id.add); add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { intent = new Intent(MainActivity.this, AddActivity.class); intent.putExtra("date", date); startActivity(intent); } }); ImageButton history = (ImageButton) findViewById(R.id.history); history.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { intent = new Intent(MainActivity.this, HistoryActivity.class); intent.putExtra("date", date); startActivity(intent); } }); ImageButton statistic = (ImageButton) findViewById(R.id.stat); statistic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { intent = new Intent(MainActivity.this, StatisticActivity.class); intent.putExtra("date", date); startActivity(intent); } }); chooseSeason = (Spinner) findViewById(R.id.choose_season); setUpSeasonSpinner(); chooseSeason.setSelection(0); chooseSeason.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { refresh(); } @Override public void onNothingSelected(AdapterView<?> parent) { refresh(); } }); refresh(); } private void setUpSeasonSpinner() { ArrayList<String> seasons = new ArrayList<>(); String currentDate = sdf.format(new Date()).substring(6, 10); seasons.add(currentDate); Cursor cursor = database.rawQuery(DatabaseQueries.getDatesForSeasons(), null); if (cursor.moveToNext()) { do { currentDate = cursor.getString(0).substring(6, 10); if (!seasons.contains(currentDate)) seasons.add(currentDate); } while (cursor.moveToNext()); } else { Log.d("mLog", "0 rows"); } cursor.close(); Collections.sort(seasons, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }); Collections.reverse(seasons); String[] years = new String[seasons.size()]; for (int i = 0; i < seasons.size(); i++) { years[i] = seasons.get(i); } ArrayAdapter<String> seasonSpinnerAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, years); seasonSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line); chooseSeason.setAdapter(seasonSpinnerAdapter); } @Override public void onBackPressed() { Dialogs.quitDialog(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.settings: Toast.makeText(this, "Скоро можно будет настраивать приложение!", Toast.LENGTH_SHORT).show(); //добавить активити return true; case R.id.exit: Dialogs.quitDialog(this); return true; default: return super.onOptionsItemSelected(item); } } public void onRefreshButtonClick(View view) { refresh(); // выводим сообщение Toast.makeText(this, getString(R.string.refreshed), Toast.LENGTH_SHORT).show(); } public void onSynchButtonClick(View view) { // выводим сообщение Toast.makeText(this, "Здесь будет происходить синхронизация!", Toast.LENGTH_SHORT).show(); } @Override protected void onResume() { super.onResume(); refresh(); } private void refresh() { for (int i =0;i<totals.length;i++) totals[i].setText("0"); mileage.setText("0"); Double total_kms = 0.0; Integer total_times = 0; String year = (String) chooseSeason.getItemAtPosition(chooseSeason.getSelectedItemPosition()); Cursor cursor; String yearFromDB; Double kms; Integer times; for (int i = 0; i< whatTotalsReferences.length; i++) { total_kms = 0.0; total_times = 0; cursor = database.rawQuery(DatabaseQueries.getTotalKm(whatTotalsReferences[i]), null); if (cursor.getCount()!=0) { if (i == 0 || i == 2 || i == 6 || i == 8 || i == 9 || i == 11) { total_kms = 0.0; total_times = 0; } while (cursor.moveToNext()){ yearFromDB = cursor.getString(cursor.getColumnIndex("DATE")).substring(6); kms = cursor.getDouble(cursor.getColumnIndex("DISTANCE")); times = cursor.getInt(cursor.getColumnIndex("SERIES")); if ((year.equals(yearFromDB)) && (kms >= 0 || times >= 0)) switch (i) { case 0: case 1: { total_kms = parseDouble(totals[0].getText().toString().replace(',','.')) + kms; totals[0].setText(String.format("%02.2f", total_kms)); } break; case 2: case 3: case 4: case 5: { total_kms = parseDouble(totals[1].getText().toString().replace(',','.')) + kms;; totals[1].setText(String.format("%02.2f", total_kms)); } break; case 6: case 7: { total_kms = parseDouble(totals[2].getText().toString().replace(',','.')) + kms;; totals[2].setText(String.format("%02.2f", total_kms)); } break; case 8: { total_kms = Double.parseDouble(totals[3].getText().toString().replace(',','.')) + kms;; totals[3].setText(String.format("%02.2f", total_kms)); } break; case 9: case 10: { total_kms = Double.parseDouble(totals[4].getText().toString().replace(',','.')) + kms;; totals[4].setText(String.format("%02.2f", total_kms)); } case 11: { total_times = Integer.parseInt(totals[5].getText().toString()) + times;; totals[5].setText(String.format("%01d", total_times)); } break; } }; } cursor.close(); } String tmp = roadKm.getText().toString().replace(',','.'); double d1 = parseDouble(tmp); tmp = mtbKm.getText().toString().replace(',','.'); double d2 = parseDouble(tmp); double d = d1+d2; mileage.setText(String.format("%02.2f", d)); //можно добавить обновление фразы } }

Размещено на Allbest.ru

...

Подобные документы

  • Проектирование базы данных для автоматизации деятельности по учету автотранспорта ГИБДД Вяземского района. Выбор инструментария для разработки базы данных и приложения по её ведению. Описание интерфейса и физической структуры приложения баз данных.

    курсовая работа [2,2 M], добавлен 28.06.2011

  • Классификация баз данных. Выбор системы управления базами данных для создания базы данных в сети. Быстрый доступ и получение конкретной информации по функциям. Распределение функций при работе с базой данных. Основные особенности иерархической модели.

    отчет по практике [1,2 M], добавлен 08.10.2014

  • Разработка моделей данных информационной системы Сall-центра с применением CASE-технологии. Персонал и его функции. Регистрирование заявок в режиме реального времени. Построение диаграммы потоков данных DFD. Список документов и инфологическая модель.

    курсовая работа [1,1 M], добавлен 28.08.2012

  • Логическая и физическая модели базы данных. Запрет на содержание неопределенных значений. Размещение базы данных на сервере. Реализация клиентского приложения управления базой данных. Модульная структура приложения. Основные экранные формы приложения.

    курсовая работа [1,4 M], добавлен 13.06.2012

  • Обзор мобильной операционной системы ios: Архитектура ОС iOS; уровень библиотек; среды разработки приложения (Xcode, Xamarin). Доступ к информации колледжа "Угреша". Требования к мобильному приложению. Подготовка среды разработки. Тестирование приложения.

    дипломная работа [5,6 M], добавлен 10.07.2014

  • Разработка программного приложения WindowsForms для работы с базой данных на языке высокого уровня C# в автономном режиме с использованием ADO.NET. Проектирование реляционной модели базы данных, интерфейса приложения, основных функций и возможностей.

    курсовая работа [4,3 M], добавлен 30.06.2015

  • Постановка задач и требований к проектируемому интернет-приложению. Обоснование выбора системы управления базы данных и языков программирования. Разработка архитектуры заданного интернет-приложения, технико-экономическое обоснование его эффективности.

    дипломная работа [461,3 K], добавлен 24.02.2013

  • Разработка веб-приложения, реализующего функции электронного дневника. Возможность для клиента регистрироваться, смотреть расписание, вести электронный дневник. Сохранение сервером полученных данных в базу на основе MySQL. Описание работы программы.

    курсовая работа [1,1 M], добавлен 27.03.2013

  • Разработка базы данных и приложения для автоматизации ведения кадрового учёта предприятия. Формирование таблицы анкетных данных. Разработка графического интерфейса пользователя клиентских приложений. Возможность подключения к удаленной базе данных.

    дипломная работа [47,6 K], добавлен 17.02.2009

  • Разработка информационной системы учёта данных о клиентах, товарах и услугах в среде MS Access. Технология функционирования существующей ИС компьютерной компании. Модификация инфологической модели БД, проектирование новых экранных форм и отчетов.

    курсовая работа [1,5 M], добавлен 20.06.2014

  • Общая характеристика и анализ требований к разрабатываемому приложению, функциональные особенности и сферы практического применения. Проектирование базы данных и выбор системы управления ею. Тестирование приложения и выбор языка программирования.

    дипломная работа [791,8 K], добавлен 10.07.2017

  • Аналитический обзор целевой аудитории. Создание и заполнение базы данных с помощью Microsoft Access. Разработка интерфейса и функций рабочей области. Построение форм. Функциональные требования к приложению. Его тестирование по методике чёрного ящика.

    дипломная работа [1,6 M], добавлен 09.11.2016

  • Статистическая обработка первичной маркетинговой информации. Определение общих параметров выборки. Составление схемы кодировки анкеты. Способы формирования базы данных в формате SPSS. Ввод данных в компьютер. Кодирование переменных. Модификация данных.

    презентация [533,9 K], добавлен 24.02.2015

  • Исследование создания программного продукта для хранения информации о персональных данных. Характеристика разработки алгоритма программы, предназначенного для выполнения следующих функций: заполнения и удаления информации о людях, чтения и сохранения.

    курсовая работа [33,3 K], добавлен 17.01.2012

  • Рассмотрение основных принципов и методов проектирования систем реального времени. Описание конструктивных и функциональных особенностей объекта управления, построение диаграммы задач. Выбор аппаратной архитектуры, модели процессов-потоков, интерфейса.

    курсовая работа [1,2 M], добавлен 19.01.2015

  • Рассмотрение инфологической и даталогической модели базы данных кинотеатров города. Разработка базы данных в программе MS Access. Описание структуры приложения и интерфейса пользователя. Изучение SQL-запросов на вывод информации о кинотеатре и о фильме.

    курсовая работа [1,1 M], добавлен 04.09.2014

  • Проектирование базы данных "Деканат" в среде MySQL и разработка многопользовательского приложения с целью хранения информации о студентах и учета их успеваемости. Построение графиков оценок по предметам в спроектированной информационной системе.

    курсовая работа [507,2 K], добавлен 16.01.2015

  • Разработка приложения для осуществления работы с медицинскими данными с последующей их визуализацией. Изучение типов данных и свойств полей Access. Компоненты наборов данных. Структура базы данных для клиники. Экранные формы для отображения справочников.

    курсовая работа [1,5 M], добавлен 14.08.2014

  • Разработка приложений баз данных Delphi. Построение концептуальной модели, атрибуты сущностей и связей. Проектирование приложения для ведения базы данных телефонных номеров с возможностью поиска по всем имеющимся полям. Тестирование программного средства.

    курсовая работа [641,7 K], добавлен 17.08.2013

  • Разработка приложения Win32, с помощью которого можно получить атрибуты файла (функция GetFileAttributes). Определение даты и времени создания, последнего доступа и последней записи данных в файл. Получение информации о файле по его идентификатору.

    курсовая работа [187,3 K], добавлен 27.06.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.