Главная страница
Навигация по странице:

  • «Тольяттинский политехнический колледж» Отчет по производственной практике по профилю специальности

  • 09.02.07 Информационные системы и программирование

  • отчет диплома. отчет2.2. Отчет по производственной практике по профилю специальности


    Скачать 398.41 Kb.
    НазваниеОтчет по производственной практике по профилю специальности
    Анкоротчет диплома
    Дата27.06.2022
    Размер398.41 Kb.
    Формат файлаdocx
    Имя файлаотчет2.2.docx
    ТипОтчет
    #617909

    Государственное бюджетное профессиональное образовательное учреждение
    Самарской области


    «Тольяттинский политехнический колледж»

    Отчет

    по производственной практике по профилю специальности


    обучающегося Анисимова Андрея Александровича

    Специальность 09.02.07 Информационные системы и программирование
    Курс 4

    Профессиональный модуль ПМ. 02 Осуществление интеграции программных модулей
    Наименование практики ПП.02 Производственная (по профилю специальности)
    Организация прохождения производственной практики:
    ____________________________________________________________________________________________
    ____________________________________________________________________________________________
    Подпись студента __________________ ________________________

    (подпись, дата) (инициалы, фамилия)


    Тольятти, 2021 г



    Содержание



    1 Обследование предметной области автоматизации 3

    1.1 Описание предметной области 3

    1.2 Документы предметной области, содержащие информацию для решения задачи 4

    2 Постановка задачи 5

    2.1 Описание выходной информации 5

    2.2 Описание входной информации 8

    3. Разработка информационного обеспечения задачи 10

    3.1 Исходные данные контрольного примера 10

    4. Реакция программы на ошибочные ситуации 11

    5. Специальный раздел 12

    5.1 Аппаратная и программная части задачи 12

    5.2 Форма представления и способы ввода данных 13

    5.3 Форма представления и способы вывода результатов 14

    5.4 Организация пользовательского интерфейса 16

    5.5 Функциональная схема работы программы 18

    5.6 Выбор входных данных для всестороннего тестирования программы в нормальных и экстремальных ситуациях 19

    5.7 Установка, запуск и порядок работы с программой 20

    Заключение 21

    Перечень принятых сокращений 22

    Список использованных источников 23

    ПРИЛОЖЕНИЕ А 24


    1 Обследование предметной области автоматизации

    1.1 Описание предметной области


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

    Любое готовое изделие можно строго подогнать под Вашу фигуру.

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

    Возможна и такая схема: при перебоях в работе отшиваете изделия на продажу.

    Времени на изготовление одного экземпляра, всегда уходит больше, чем когда эти же вещи делаются на потоке. Изделие делается с учетом Ваших пожеланий, Вы можете в процессе менять, дополнять, убавлять, по мере возможности, детали для достижения оптимального результата. Изделие эксклюзивно . Точной копии нет ни у кого. Чаще всего, даже если мастер делает повтор, то два изделия все равно не получаются абсолютно идентичными. Мне приятно осознавать, что некоторых вещи есть только у меня. Мастер очень тщательно контролирует весь процесс изготовления. Его изделие – это его репутация и его имя. Он не может себе позволить сделать некачественную вещь. Много времени уходит на подбор материалов. Мало найти нужные материалы, важно чтобы всё это идеально сочеталось. Сайт создается для того чтобы люди знали цену за услугу, которую они хотят получить, так называемый прайс.

    1.2 Документы предметной области, содержащие информацию для решения задачи


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

    К условно-постоянной информации относятся:

    • «Город»

    К оперативно-учетной информации относятся документы:

    • Документ «Информация о городе», содержащий данные о городе (температура, влажность, видимость);

    2 Постановка задачи


    На основании проведённого анализа требуется разработать сайт Ателье. Сайт должен предусматривать просмотр всех услуг которые предоставлены предприятием.

    Основной задачей данной предметной области является необходимость создание более удобной сайта для пользования. Для этого нужно создать базу данных и приложение.

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

    2.1 Описание выходной информации


    В результате решения задачи необходимо получить следующие выходные документы:

    • «Список клиентов»;

    • «Цена услуги»;

    • «Список заказов»;

    Перечень и описание выходной информации представлены в таблице 2.1.

    Таблица 2.1 - Перечень и описание выходной информации


    Наименование выходной информации

    Идентификатор выходной информации

    Форма представления

    Сроки выдачи

    Получатель информации

    1

    2

    3

    4

    5

    Список клиентов

    Вх-01

    Экранная форма

    По

    требованию

    Клиент

    Цена услуги

    Вх-02

    Экранная форма

    По

    требованию

    Клиент

    Заказ

    Вх-03

    Экранная форма

    По

    требованию

    Сотрудник



    Формы документов выходной информации представлены на рисунках 2.1 - 2.3.





    Вх - 01



    Список клиентов

    Код клиента

    ФИО клиента

    Телефон





















    Р исунок 2.1 – Форма выходного документа “Список клиентов”

    Вх - 02



    Цена услуги


    Код услуги

    Пошив одежды детской

    Ремонт одежды детской

    Пошив одежды взрослый

    Ремонт одежды взрослый
































    Р
    Вх - 03
    исунок 2.2 - Форма выходного документа “ Цена услуги”


    Заказ



    Номер заказа

    Код клиента

    Код клиента

    Дата примерки

    Срок изготовления

    Сумма







































    Рисунок 2.3 – Форма выходного документа “Заказ”

    Перечень и описание реквизитов выходной информации представлены в таблице 2.2



    Наименование

    реквизита

    Идентификатор

    реквизита

    Идентификатор выходного

    документа

    Характеристика реквизита

    Код клиента

    Kod_klient

    Вх-01, Вх-03

    9(5), 9(5)

    ФИО клиента

    Fio_klient

    Вх-01

    A(50)

    Телефон

    Phone

    Вх-01

    A(10)

    Код услуги

    Kod_usl

    Вх-02, Вх-03

    9(5).9(5)

    Пошив одежды детской

    Pohiv-det

    Вх-02

    A(50)

    Ремонт одежды детской

    Rem_det

    Вх-02

    A(50)

    Пошив одежды взрослой

    Pohiv_vzr

    Вх-02

    A(50)

    Ремонт одежды взрослой

    Rem_vzr

    Вх-02

    A(50)

    Номер заказа

    Namber_zak

    Вх-02

    9(6)

    Дата примерки

    Data

    Вх-03

    A(15)

    Срок изготовления

    Srok

    Вх-03

    A(15)

    Сумма

    Sum

    Вх-03

    9(10)

    2.2 Описание входной информации


    Наименование УПИ

    Идентификатор

    Форма представления

    1

    2

    3

    Клиент

    В-01

    Документ

    Услуга

    В-02

    Документ

    Заказ

    В-03

    Документ

    Таблица 2.3 – Перечень и описание условно-постоянной информации
    Формы документов представлены на рисунке 2.4




    В - 01


    Клиет


    Температура

    Описание

    Ощущается

    как

    Влажность

    Направление

    ветра

    Скорость

    ветра

    Облачность

    Видимость

    1

    2

    3

    4

    5

    6

    7

    8


























    Рисунок 2.4 – Форма входного документа “Информация о городе”
    Перечень и описание запросных форм представлены в таблице 2.4. Запросные формы изображены на рисунке 2.5

    Таблица 2.4 – Перечень и описание запросных форм

    Наименование ЗФ

    Идентификатор

    Форма представления

    1

    2

    3

    Добавление нового города

    ЗФ-01

    Документ



    ЗФ-01


    Введите город


    Добавить

    Перечень и описание реквизитов входной информации представлены в таблице 2.5.

    Таблица 2.6 – Перечень и описание реквизитов входной информации


    Наименование

    реквизита

    Идентификатор

    реквизита

    Идентификатор выходного

    документа

    Характеристика реквизита

    1

    2

    3

    4

    Температура

    tvTemp

    В-01

    9(6).9(2)

    Описание

    tvDescription

    В-01

    A(50)

    Ощущается как

    tvFeelsLike

    В-01

    9(6).9(2)

    Влажность

    tvHumidity

    В-01

    9(6)

    Направление ветра

    tvWindDeg

    В-01

    A(50)

    Скорость ветра

    tvWindSpeed

    В-01

    9(6)

    Облачность

    tvClouds

    В-01

    9(6)

    Видимость

    tvVisibility

    В-01

    9(6)


    3. Разработка информационного обеспечения задачи

    3.1 Исходные данные контрольного примера


    Для проверки алгоритма решения задачи разработан контрольный пример, данные которого предназначены для тестирования, отладки и демонстрации решения задачи. Данные контрольного примера представлены в таблицах 3.1 – 3.2.

    Таблица 3.1 – “Список городов”


    № п/п

    Наименование

    Градусы

    1

    2

    3

    1

    Екатеринбург

    2

    2

    Сызрань

    13.09

    3

    Самара

    12

    4

    Ульяновск

    11

    5

    Пенза

    6.08

    6

    Сочи

    5

    7

    Казань

    1.95

    8

    Москва

    12

    9

    Тольятти

    18.74


    Таблица 3.2 – “Детальная информация о городе”

    № п/п

    Наименование

    Информация

    1

    2




    1

    Температура

    2

    2

    Описание

    Небольшая морось

    3

    Ощущается как

    -1.1

    4

    Влажность

    100%

    5

    Направление ветра

    Северо-западный

    6

    Скорость ветра

    3м/с

    7

    Облачность

    90%

    8

    Видимость

    2600м



    4. Реакция программы на ошибочные ситуации


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

    - при вводе повторяющего города, информация о нём будет обновлена на главной странице, а сам город повторно добавлен не будет

    - при попытке воспользоваться приложением не имея доступ к интернету, будет выведена соответствующая ошибка , но приложение продолжит работать, взяв последние сохранённые данные из бд и отобразит их.

    5. Специальный раздел

    5.1 Аппаратная и программная части задачи


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

    • процессор AMD Ryzen 3 1200 Quad-Core или выше; 

    • оперативная память 4 ГБ и более; 

    • объем свободного места на жёстком диске не менее 100 Мб; 

    • видеоадаптер GeForce GTX; 

    • клавиатура; 

    • мышь; 

    • дисплей VGA; 

    • принтер.

    Требования к программному обеспечению:

    • операционная система Windows 7 и выше;

    • драйвер устройств ввода, вывода (мышь, монитор);

    • Android Studio 2017, Kotlin и выше;

    • Ms Office 2010 и выше.

    5.2 Форма представления и способы ввода данных


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

    Ф
    орма ввода нового города изображена на рисунке 5.1

    Рисунок 6.1 – Форма ввода нового города

    5.3 Форма представления и способы вывода результатов


    После добавления города, он отобразиться на главном экране, справа от названия можно увидеть краткую информацию о погоде. После нажатия на город появится детальная информация о погоде

    Ф
    ормы выходных документов представлены на рисунках 6.2 – 6.3.
    Рисунок 6.2 – Выходная форма “Список городов”




    Рисунок 6.3 – Выходная форма “Детальная информация о городе”

    5.4 Организация пользовательского интерфейса


    При запуске программы на экране появится главная форма – меню (рисунок 5.4), которое дает наиболее удобный доступ к функциям программы.

    Шрифт интерфейса легко читается. Это достигается за счет использования шрифта Microsoft Sans Serif.

    На всех формах программы используются стандартные компоненты: поле ввода (рисунок 5.5), кнопка (рисунок 5.6) При работе с программой пользователь может пользоваться как клавиатурой, так и «мышью».

    Таким образом, в программе «Weather» реализован удобный интерфейс, позволяющий пользователю, не имеющему специального образования, хорошо ориентироваться в программе.





    Рисунок 5.4 – Главная форма программы





    Рисунок 5.5 – Вид компонента “Поле ввода”


    Рисунок 5.6 – Вид компонента “Кнопка”

    5.5 Функциональная схема работы программы


    Функциональная схема решения задачи представлена на рисунке 5.7.



    Рисунок 5.7 – Функциональная схема работы приложения

    5.6 Выбор входных данных для всестороннего тестирования программы в нормальных и экстремальных ситуациях


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

    • Тест №1. Не заполнено поле для добавления нового города. При попытке внесения записи ничего не будет добавлено и пользователю будет предложено повторить попытку;

    • Тест № 2. При попытке воспользоваться приложением без доступа к интернету, будет выведена соответствующая ошибка, но приложение продолжит работать, подтянув из бд последние сохранённые данные.

    5.7 Установка, запуск и порядок работы с программой


    1. Установка программы:

    1.1. Подключить телефон на базе операционной системы Android к компьютеру;

    1.2. Скопировать папку проекта «Weather» с носителя на жесткий диск.

    2. Запуск программы:

    2.1. Перейти в папку с программой;

    2.2. Запустить проект через Android Studio.

    3. Работа с программой:

    3.1. Ввод данных:

    3.1.1. На главной странице нажать на знак плюса в нижнем правом углу экоана;

    3.1.2. Откроется окно для добавления нового города;

    3.1.3. Ввести нужный город и нажать кнопку «Добавить»;

    3.1.4. После добавления будет выполнен переход на главный экран.

    3.2. Удаление данных:

    3.2.1. На главном экране сделать свай влево по нужному городу

    3.2.2. После свайпа откроется окно с двумя кнопками и будет задан вопрос, точно ли вы хотите удалить город;

    3.2.3. Нажать кнопку «Отмена», если вы не хотите удалять город;

    3.2.4. Нажать кнопку «Удалить», если вы хотите удалить город;

    Заключение


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

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

    Для тестирования поставленной задачи был разработан контрольный пример. Создан программный продукт «Weather», написана инструкция пользователя.

    В результате решения задачи получена выходная информация:

    • Список городов с краткой информацией;

    • Отчёт по выбранному городу;

    • Отчёт по компасу.

    Программный продукт может использоваться на различных предприятиях без доработки.

    Перечень принятых сокращений


    УПИ – условно-постоянная информация;

    ОУИ – оперативно-учетная информация;

    БД – база данных;

    ПО – программное обеспечение;


    Список использованных источников


    1.  Голощапов, Алексей Google Android. Программирование для мобильных устройств (+ CD-ROM) / Алексей Голощапов. - М.: БХВ-Петербург, 2011. - 438 c.

    2.  Давыдов, Станислав IntelliJ IDEA. Профессиональное программирование на Java. Наиболее полное руководство (+ CD-ROM) / Станислав Давыдов , Алексей Ефимов. - М.: БХВ-Петербург, 2011. - 800 c.

    3. Майер, Рето Android 2. Программирование приложений для планшетных компьютеров и смартфонов / Рето Майер. - М.: "Издательство "Эксмо", 2011. - 672 c.

    4.  Мартин, К. Соломон Oracle. Программирование на языке Java / Мартин К. Соломон, Нирва Мориссо-Леруа , Джули Басу. - М.: ЛОРИ, 2010. - 512 c.

    5. Машнин, Т. С. Eclipse. Разработка RCP-, Web-, Ajax- и Android-приложений на Java / Т.С. Машнин. - М.: БХВ-Петербург, 2013. - 384 c.

    6. Нотон Java. Справочное руководство. Все, что необходимо для программирования на Java / Нотон, Патрик. - М.: Бином, 2015. - 448 c.

    7. Роджерс, Рик Android. Разработка приложений / Рик Роджерс и др. - М.: ЭКОМ Паблишерз, 2010. - 400 c.

    ПРИЛОЖЕНИЕ А


    package dmitry.davydov.weather.fragments

    import android.os.Bundle
    import android.util.Log
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.view.WindowManager
    import android.widget.Toast
    import com.arellomobile.mvp.MvpAppCompatFragment
    import com.arellomobile.mvp.presenter.InjectPresenter
    import dmitry.davydov.weather.R
    import dmitry.davydov.weather.db.model.City
    import dmitry.davydov.weather.presenters.DbPresenter
    import dmitry.davydov.weather.presenters.NetworkPresenter
    import dmitry.davydov.weather.views.DbView
    import dmitry.davydov.weather.views.NetworkView
    import kotlinx.android.synthetic.main.fragment_add_city.*
    import kotlinx.android.synthetic.main.toolbar.*

    class AddCityFragment: MvpAppCompatFragment(), NetworkView, DbView {

    @InjectPresenter
    lateinit var networkPresenter: NetworkPresenter
    @InjectPresenter
    lateinit var dbPresenter: DbPresenter

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.fragment_add_city, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    buildInterface()
    }

    override fun getWeatherSuccess(city: City) {
    dbPresenter.addCity(city = city) }

    override fun cityAdded() {
    activity?.onBackPressed() }

    override fun startLoading() {
    progressBar.visibility = View.VISIBLE
    activity?.window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
    }

    override fun finishLoading() {
    progressBar.visibility = View.GONE
    activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
    }

    override fun showError(error: Int) { Toast.makeText(context, getString(error), Toast.LENGTH_SHORT).show() }

    override fun showError(error: String) { Toast.makeText(context, error, Toast.LENGTH_SHORT).show() }

    override fun citiesGetted(cities: ArrayList) {}
    override fun cityDeleted(city: City) {}
    override fun infoGetted(city: City) {}

    private fun buildInterface() {
    ivBack.visibility = View.VISIBLE
    ivBack.setOnClickListener { activity?.onBackPressed() }

    tvHeader.text = getString(R.string.add_city)

    btnAdd.setOnClickListener { checkInput() }
    }

    private fun checkInput() {
    if (edtCity.text.toString().isNotEmpty())
    networkPresenter.getWeather(cityName = edtCity.text.toString())
    else
    Toast.makeText(context, getString(R.string.isCityEmpty), Toast.LENGTH_SHORT).show()
    }

    }
    package dmitry.davydov.weather.fragments

    import android.content.Context
    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.view.WindowManager
    import android.widget.Toast
    import androidx.recyclerview.widget.ItemTouchHelper
    import androidx.recyclerview.widget.LinearLayoutManager
    import androidx.recyclerview.widget.RecyclerView
    import com.arellomobile.mvp.MvpAppCompatFragment
    import com.arellomobile.mvp.presenter.InjectPresenter
    import dmitry.davydov.weather.R
    import dmitry.davydov.weather.adapters.CitiesAdapter
    import dmitry.davydov.weather.db.model.City
    import dmitry.davydov.weather.dialogs.RemoveCityDialog
    import dmitry.davydov.weather.helpers.Common
    import dmitry.davydov.weather.helpers.FragmentHelper
    import dmitry.davydov.weather.helpers.SwipeToDeleteCallback
    import dmitry.davydov.weather.presenters.DbPresenter
    import dmitry.davydov.weather.views.DbView
    import kotlinx.android.synthetic.main.fragment_add_city.*
    import kotlinx.android.synthetic.main.fragment_cities.*
    import kotlinx.android.synthetic.main.toolbar.*

    class CitiesFragment : MvpAppCompatFragment(), DbView {

    @InjectPresenter
    lateinit var dbPresenter: DbPresenter

    private lateinit var ctx: Context
    private lateinit var cities: ArrayList
    private lateinit var adapter: CitiesAdapter
    private val tagDialog = "removeDialog"

    override fun onAttach(context: Context) {
    super.onAttach(context)
    ctx = context
    }

    override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View? {
    return inflater.inflate(R.layout.fragment_cities, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    buildInterface()
    dbPresenter.getCities()
    }

    override fun cityAdded() {
    activity?.onBackPressed()
    }

    override fun citiesGetted(cities: ArrayList) {
    this.cities = cities
    adapter = CitiesAdapter(context = ctx, cities = cities) { toFragment(position = it) }
    rv.adapter = adapter
    }

    override fun cityDeleted(city: City) {
    this.cities.remove(city)
    rv.adapter?.notifyDataSetChanged()
    }

    override fun infoGetted(city: City) {}

    override fun startLoading() {
    progressBar.visibility = View.VISIBLE
    activity?.window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
    }

    override fun finishLoading() {
    progressBar.visibility = View.GONE
    activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
    }

    override fun showError(error: Int) {
    Toast.makeText(context, getString(error), Toast.LENGTH_SHORT).show()
    }

    override fun showError(error: String) {
    Toast.makeText(context, error, Toast.LENGTH_SHORT).show()
    }

    private fun buildInterface() {
    tvHeader.text = getString(R.string.app_name)
    ivCompass.visibility = View.VISIBLE
    ivCompass.setOnClickListener {
    FragmentHelper().goToFragment(fragmentManager, CompassFragment(), true)
    }

    fabAddCity.setOnClickListener {
    FragmentHelper().goToFragment(fragmentManager, AddCityFragment(), true)
    }

    rv.setHasFixedSize(true)
    val layoutManager = LinearLayoutManager(ctx)
    rv.layoutManager = layoutManager
    rvScroll()
    createSwipe()
    }

    private fun createSwipe() {
    val swipeHandler = object : SwipeToDeleteCallback(ctx) {
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    openRemoveDialog(position = viewHolder.adapterPosition)
    }
    }
    val itemTouchHelper = ItemTouchHelper(swipeHandler)
    itemTouchHelper.attachToRecyclerView(rv)
    }

    private fun openRemoveDialog(position: Int) {
    val dialog = RemoveCityDialog(city = cities[position].city,
    delete = { dbPresenter.deleteCity(city = cities[position]) },
    dismiss = { adapter.notifyDataSetChanged()} )
    activity?.let { dialog.show(it.supportFragmentManager, tagDialog) }
    }

    private fun toFragment(position: Int) {
    val bundle = Bundle()
    bundle.putString(Common.EXTRA_CITY_NAME, cities[position].city)
    FragmentHelper().goToFragment(fragmentManager, DetailFragment.getNewInstance(args = bundle), true)
    }

    private fun rvScroll(){
    rv.addOnScrollListener(object: RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
    super.onScrolled(recyclerView, dx, dy)
    if (dy > 0 && fabAddCity.visibility == View.VISIBLE) {
    fabAddCity.hide() }
    else if (dy < 0 && fabAddCity.visibility == View.GONE) {
    fabAddCity.show()
    }
    }
    })
    }
    }

    package dmitry.davydov.weather.fragments

    import android.content.Context.SENSOR_SERVICE
    import android.hardware.Sensor
    import android.hardware.SensorEvent
    import android.hardware.SensorEventListener
    import android.hardware.SensorManager
    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.fragment.app.Fragment
    import dmitry.davydov.weather.R
    import kotlinx.android.synthetic.main.fragment_compass.*
    import kotlinx.android.synthetic.main.toolbar.*

    class CompassFragment : Fragment() {

    private var sensorManager: SensorManager? = null
    private var sensorAccelerometer: Sensor? = null
    private var sensorMagneticField: Sensor? = null
    private var sensorEventListenerAccelrometer: SensorEventListener? = null
    private var sensorEventListenerMagneticField: SensorEventListener? = null

    private var floatGravity = FloatArray(3)
    private var floatGeoMagnetic = FloatArray(3)

    private val floatOrientation = FloatArray(3)
    private val floatRotationMatrix = FloatArray(9)


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.fragment_compass, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    buildInterface()
    makeSensor()
    }

    private fun makeSensor(){
    sensorManager = activity?.getSystemService(SENSOR_SERVICE) as SensorManager?

    sensorAccelerometer = sensorManager?.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    sensorMagneticField = sensorManager?.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)

    sensorEventListenerAccelrometer = object : SensorEventListener {
    override fun onSensorChanged(event: SensorEvent) {
    floatGravity = event.values
    SensorManager.getRotationMatrix(floatRotationMatrix, null, floatGravity, floatGeoMagnetic)
    SensorManager.getOrientation(floatRotationMatrix, floatOrientation)
    ivCompassArrow.rotation = (-floatOrientation[0] * 180 / 3.14159).toFloat()
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
    }

    sensorEventListenerMagneticField = object : SensorEventListener {
    override fun onSensorChanged(event: SensorEvent) {
    floatGeoMagnetic = event.values
    SensorManager.getRotationMatrix(floatRotationMatrix, null, floatGravity, floatGeoMagnetic)
    SensorManager.getOrientation(floatRotationMatrix, floatOrientation)
    ivCompassArrow.rotation = (-floatOrientation[0] * 180 / 3.14159).toFloat()
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
    }

    sensorManager?.registerListener(sensorEventListenerAccelrometer, sensorAccelerometer, SensorManager.SENSOR_DELAY_NORMAL)
    sensorManager?.registerListener(sensorEventListenerMagneticField, sensorMagneticField, SensorManager.SENSOR_DELAY_NORMAL)
    }

    private fun buildInterface() {
    ivBack.visibility = View.VISIBLE
    ivBack.setOnClickListener { activity?.onBackPressed() }

    tvHeader.text = getString(R.string.compass)
    }

    override fun onPause() {
    super.onPause()
    sensorEventListenerAccelrometer?.let { sensorManager?.unregisterListener(sensorEventListenerAccelrometer) }
    sensorEventListenerMagneticField?.let { sensorManager?.unregisterListener(sensorEventListenerMagneticField) }
    }

    override fun onResume() {
    super.onResume()
    sensorEventListenerAccelrometer?.let { sensorManager?.registerListener(sensorEventListenerAccelrometer, sensorAccelerometer, SensorManager.SENSOR_DELAY_NORMAL) }
    sensorEventListenerMagneticField?.let { sensorManager?.registerListener(sensorEventListenerMagneticField, sensorMagneticField, SensorManager.SENSOR_DELAY_NORMAL) }
    }

    }

    package dmitry.davydov.weather.fragments

    import android.annotation.SuppressLint
    import android.os.Bundle
    import android.util.Log
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.Toast
    import com.arellomobile.mvp.MvpAppCompatFragment
    import com.arellomobile.mvp.presenter.InjectPresenter
    import com.squareup.picasso.Picasso
    import dmitry.davydov.weather.R
    import dmitry.davydov.weather.db.model.City
    import dmitry.davydov.weather.helpers.Common
    import dmitry.davydov.weather.presenters.DbPresenter
    import dmitry.davydov.weather.presenters.NetworkPresenter
    import dmitry.davydov.weather.views.DbView
    import dmitry.davydov.weather.views.NetworkView
    import kotlinx.android.synthetic.main.fragment_detail.*
    import kotlinx.android.synthetic.main.toolbar.*

    class DetailFragment : MvpAppCompatFragment(), NetworkView, DbView {

    @InjectPresenter
    lateinit var networkPresenter: NetworkPresenter
    @InjectPresenter
    lateinit var dbPresenter: DbPresenter

    private lateinit var cityName: String
    private val iconPath = "https://openweathermap.org/img/wn/"
    private val iconExpansion = "@2x.png"

    companion object {
    fun getNewInstance(args: Bundle?): DetailFragment {
    val fragment = DetailFragment()
    fragment.arguments = args
    return fragment
    }
    }

    override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View? {
    return inflater.inflate(R.layout.fragment_detail, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    arguments?.getString(Common.EXTRA_CITY_NAME, "")?.let { cityName = it }

    buildInterface()
    dbPresenter.getInfo(cityName = cityName)
    }

    override fun cityAdded() {
    }

    override fun citiesGetted(cities: ArrayList) {
    }

    override fun cityDeleted(city: City) {
    }


    override fun infoGetted(city: City) {
    updateInfo(city = city)

    networkPresenter.getWeather(cityName = cityName)
    }

    override fun getWeatherSuccess(city: City) {
    updateInfo(city = city)
    dbPresenter.addCity(city = city)
    }

    override fun startLoading() {
    progressBar2.visibility = View.VISIBLE
    }

    override fun finishLoading() {
    progressBar2.visibility = View.GONE
    }

    override fun showError(error: Int) {
    Toast.makeText(context, getString(error), Toast.LENGTH_SHORT).show()
    }

    override fun showError(error: String) {
    Toast.makeText(context, error, Toast.LENGTH_SHORT).show()
    fabRefresh.visibility = View.VISIBLE
    }


    @SuppressLint("SetTextI18n")
    private fun buildInterface() {
    ivBack.visibility = View.VISIBLE
    ivBack.setOnClickListener { activity?.onBackPressed() }
    fabRefresh.setOnClickListener{
    networkPresenter.getWeather(cityName = cityName)
    fabRefresh.visibility = View.GONE
    }

    tvHeader.text = getString(R.string.detail_info)
    tvCityHeader.text = "${getString(R.string.detail_info)} ${getString(R.string.about_city)} $cityName"
    }

    @SuppressLint("SetTextI18n")
    private fun updateInfo(city: City) {
    tvTemp.text = city.temp + " \u2103"
    tvDescription.text = city.description
    tvFeelsLike.text = city.feelsLike + " \u2103"
    tvHumidity.text = city.humidity + getString(R.string.percent)
    tvWindSpeed.text = city.windSpeed + getString(R.string.ms)
    tvClouds.text = city.clouds + getString(R.string.percent)
    tvVisibility.text = city.visibility.toString() + getString(R.string.m)
    city.windDeg?.let { degConvert(deg = it) }
    Picasso.get().load("$iconPath${city.icon}$iconExpansion").into(ivIcon)
    }

    private fun degConvert(deg: Int){
    when (deg) {
    90 -> {
    tvWindDeg.text = getString(R.string.east)
    }
    in 91..179 -> {
    tvWindDeg.text = getString(R.string.southeastern)
    }
    180 -> {
    tvWindDeg.text = getString(R.string.south)
    }
    in 181..269 -> {
    tvWindDeg.text = getString(R.string.southwestern)
    }
    270 -> {
    tvWindDeg.text = getString(R.string.west)
    }
    in 271..359 -> {
    tvWindDeg.text = getString(R.string.northwestern)
    }
    in 1..89 -> {
    tvWindDeg.text = getString(R.string.northeastern)
    }
    else -> {
    tvWindDeg.text = getString(R.string.northern)
    }
    }
    }
    }

    package dmitry.davydov.weather.db.dao

    import androidx.room.*
    import dmitry.davydov.weather.db.model.City
    import io.reactivex.Completable
    import io.reactivex.Single

    @Dao
    interface WeatherModuleDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(city: City): Completable

    @Query("SELECT * FROM Weather")
    fun getCities(): Single>

    @Delete
    fun deleteCity(city: City): Completable

    @Query("SELECT * FROM Weather WHERE city LIKE :city LIMIT 1")
    fun getInfo(city: String): Single

    }

    package dmitry.davydov.weather.db.model

    import androidx.room.Entity
    import androidx.room.PrimaryKey
    import com.google.gson.annotations.SerializedName

    @Entity(tableName = "Weather")
    class City {

    @PrimaryKey
    @SerializedName("city")
    var city: String = ""

    @SerializedName("temp")
    var temp: String? = null

    @SerializedName("description")
    var description: String? = null

    @SerializedName("feels_like")
    var feelsLike: String? = null

    @SerializedName("humidity")
    var humidity: String? = null

    @SerializedName("wind_deg")
    var windDeg: Int? = null

    @SerializedName("wind_speed")
    var windSpeed: String? = null

    @SerializedName("clouds")
    var clouds: String? = null

    @SerializedName("visibility")
    var visibility: Int? = null

    @SerializedName("icon")
    var icon: String? = null
    }


    написать администратору сайта