отчет диплома. отчет2.2. Отчет по производственной практике по профилю специальности
Скачать 398.41 Kb.
|
Государственное бюджетное профессиональное образовательное учреждение Самарской области «Тольяттинский политехнический колледж» Отчет по производственной практике по профилю специальности обучающегося Анисимова Андрея Александровича Специальность 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 - Перечень и описание выходной информации
Формы документов выходной информации представлены на рисунках 2.1 - 2.3. Вх - 01 Список клиентов
Р исунок 2.1 – Форма выходного документа “Список клиентов” Вх - 02 Цена услуги
Р Вх - 03 исунок 2.2 - Форма выходного документа “ Цена услуги” Заказ
Рисунок 2.3 – Форма выходного документа “Заказ” Перечень и описание реквизитов выходной информации представлены в таблице 2.2
2.2 Описание входной информации
Таблица 2.3 – Перечень и описание условно-постоянной информации Формы документов представлены на рисунке 2.4 В - 01 Клиет
Рисунок 2.4 – Форма входного документа “Информация о городе” Перечень и описание запросных форм представлены в таблице 2.4. Запросные формы изображены на рисунке 2.5 Таблица 2.4 – Перечень и описание запросных форм
ЗФ-01 Введите город Добавить Перечень и описание реквизитов входной информации представлены в таблице 2.5. Таблица 2.6 – Перечень и описание реквизитов входной информации
3. Разработка информационного обеспечения задачи3.1 Исходные данные контрольного примераДля проверки алгоритма решения задачи разработан контрольный пример, данные которого предназначены для тестирования, отладки и демонстрации решения задачи. Данные контрольного примера представлены в таблицах 3.1 – 3.2. Таблица 3.1 – “Список городов”
Таблица 3.2 – “Детальная информация о городе”
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 } |