Разработка программного средства для поиска кратчайшего пути до места неисправности в инженерных сетях
Характеристика способов представления инженерных сетей в информационных системах. Описание модели базы данных. Моделирование и анализ бизнес-процессов поиска, локализации и устранения неисправности. Особенность реализации и тестирования контроллеров.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 30.07.2016 |
Размер файла | 1,3 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Рисунок 2.3. Форма загрузки фотографии самого маркера
Рисунок 2.4. Загрузка фотографий переходов от заданного маркера
Реализация доменной модели
После создания базы данных можно было приступать к разработке веб-приложения, а именно модели. Для модели был создан специальный отдельный проект в виде библиотеки классов C#. Конечно, можно было создавать всё веб-приложение в одном проекте, но для серьёзных проектов MVC считается правильным выносить модель в отдельный проект.
Классы модели, как и было запланировано на стадии проектирования, созданы с помощью средства EntityFramework на основании структуры базы данных, а затем доработаны. Пример класса модели, а именно код класса Marker в сокращённом виде представлен на рисунке 2.5.
Рисунок 2.5. Код класса Marker
Как видно из рисунка, EntityFramework с помощью технологии CodeSecond успешно справился со своей задачей, сгенерировав свойства класса для соответствующих столбцов таблицы базы данных. Кроме того, все типы данных при генерации были верно подобраны, также отражены поля, позволяющие нулевые значения, а связи с другими таблицами смоделированы с помощью виртуальных свойств (ключевое слово virtual). При этом, так как связь между маркерами имеет тип многие-ко-многим, то в базе данных для этого предусмотрена дополнительная таблица LinksM. Поэтому при генерации в класс Marker были добавлены свойства LinksMs и LinksMs1для отражения связи маркеров и линий связи. Следовательно, чтобы узнать, с какими маркерами связан текущий маркер, нужно сначала с помощью свойства LinksMs или LinksMs1 просмотреть все связи, а потом уже узнать второй маркер для каждой из связей. А чтобы узнать длину линий связи между маркерами, нужно ещё раз просмотреть массив связей и найти нужную. Все эти манипуляции довольно сложны и менее читабельны. Поэтому в класс было добавлено дополнительное свойство Neighbours. Оно представляет собой словарь, в котором ключами являются маркеры, связанные с данным маркером, а значениями - длина линии связи до маркера-ключа. Для заполнения этого свойства был добавлен метод FillMarker(). Аналогичные свойства и методы были добавлены в классы Point и Device, методы FillNeighbours() и FillPorts() для заполнения, соответственно, списка смежных точек помещения и словаря смежных устройств сети с указанием номера порта, к которому они подключены.
Также с помощью EntityFramework была сгенерирована папка Mapping, содержащая классы, описывающие соответствие между столбцами базы данных и полями соответствующих классов модели. Также в этих классах описываются ограничения значений полей, если они существовали для соответствующих столбцов базы данных. Кроме того, был сгенерирован класс IndoorNavigationContext, который описывает контекст базы данных IndoorNavigation. В частности, он содержит метод, инициализирующий контекст при доступе к базе данных в первый раз. Также класс включает свойства, представляющие коллекцию всех сущностей соответствующих классов модели, которые содержатся в контексте или могут быть запрошены из соответствующих таблиц базы данных.
Для создания шаблона «Репозиторий» был добавлен интерфейс IRepository. Его код представлен на рисунке 2.6. Как видно, в интерфейсе определены только свойства и их типы, но не конкретная реализация. Это даёт возможность в дальнейшем обращаться к репозиторию и получать из него данные независимо от того, с помощью какой технологии он реализован.
Рисунок 2.6. Интерфейс репозитория
Для реализации интерфейса IRepository был создан класс EFRepository. Его код представлен на рисунке 2.7. Для взаимодействия с хранилищем данных он использует класс контекста IndoorNavigationContext, описанный выше. Как видим, он инициализирует все свойства интерфейса соответствующими данными из контекста. При желании можно было бы написать реализации интерфейса репозитория и к другим базам данных, при этом не меняя самого интерфейса, и, следовательно, изменяя лишь одну строку в остальной программе.
Рисунок 2.7. Класс, реализующий интерфейс репозитория
Наконец, для вычисления оптимального пути нужно создать ещё один класс доменной модели. Для этого был создан класс ShortestPath. Этот класс содержит вершины и рёбра графа, то есть описывает граф, а также реализует алгоритм Дейкстры для поиска кратчайшего пути из заданного начального в заданный конечный маркер. Кроме того, для работы метода поиска кратчайшего пути были добавлены специальные классы Edge и Vertice, описывающие ребро и вершину графа соответственно. Перед запуском алгоритма необходимо заполнить массивы рёбер и вершин. Для этого были добавлены специальные методы FillEdges(List<Marker> m) и FillVertices(List<Marker> m), на вход которым подаётся массив маркеров. Кроме того, изначально алгоритм ищет кратчайшие пути до всех вершин, но в нашем случае требуется путь только до одной конкретной вершины. Для этого был добавлен специальный метод MinPathToVertice(Marker endMar), который выдаёт кратчайший путь до конкретной вершины. В итоге получилось, что для поиска кратчайшего пути нужно сначала создать экземпляр класса ShortestPath, а затем вызвать для него метод BuildingPath, подав ему на вход начальный и конечный маркеры, а также список всех маркеров.
Чтобы посмотреть код всех классов модели, вы можете обратиться к приложению А отчёта.
Реализация контроллеров
Как было отмечено ранее, для нашего веб-приложения нужно было создать 2 контроллера: HomeController и AccountController. Сначала был создан HomeController, потому что он отвечает за основной функционал приложения.
В первую очередь, в дополнение к стандартному конструктору контроллера без параметров был добавлен ещё один конструктор, который принимает на вход объект, реализующий репозиторий. Эта функция полезна при тестировании, когда контроллер можно протестировать без подключения реальной базы данных, но используя тестовые данные из тестового репозитория. Полученный объект конструктор присваивает добавленному в контроллер полю repo.
Далее, в соответствии со схемой представлений, в контроллер были добавлены необходимые методы действий. В первую очередь был создан метод ActionResult Index(), который предназначен для генерации представления Index, то есть страницы Главная. Этот метод просто возвращает представление Index без дополнительных параметров.
После этого был создан метод действия ViewResult GetAllMarkers(int page =1). Метод позволяет организовать постраничное отображение маркеров, поэтому на вход он получает номер текущей страницы. Этот метод возвращает представление GetAllMarkers(«О маркерах» на схеме представлений, рисунок 2.2) и возвращает в него в качестве модели представления объект класса MarkersListViewModel. Эта модель содержит маркеры для текущей страницы представления, а также информацию о номере текущей страницы, количестве маркеров на одну страницу и количестве всех маркеров. Код класса MarkersListViewModel представлен на рисунке 2.8.
Рисунок 2.8. Класс MarkersListViewModel
Затем были созданы методы действия ActionResultAbout() и ActionResultContact().Так же, как и метод Index(), эти методы просто возвращают представления About («О программе») и Contact («О нас») без дополнительных параметров.
После этого можно было переходить к разработке методов действия, которые составляют основной функционал нашего приложения. В первую очередь это метод ViewResult Search1(). Он генерирует представление Search1, в котором происходит вся работа по вводу информации, поиску кратчайшего пути и выводу информации о пути для пользователя. Кроме того, он передаёт в представление информацию обо всех маркерах системы в виде списка объектов типа Marker. Эти данные будут использоваться в представлении для заполнения элементов ввода. После этого метода действия других методов, которые будут возвращать представления, разрабатывать уже не нужно.
Рисунок 2.8. Методы действия, возвращающие JSON-результат
Ещё раз напомним, что эти методы вызываются из представления с помощью технологии AJAX, а их результат обрабатывает специальная функция в представлении на языке JavaScript. Это позволяет получать данные, обрабатывать их и отображать результат не перезагружая представление целиком.
Первый метод JsonResultGetRoute(int start, int finish) на вход получает номер начального и конечного маркеров. Затем он вычисляет кратчайший путь между этими маркерами, полученный путь имеет вид списка маркеров. Но JSON-сериализатор не может автоматически преобразовать список маркеров в объект формата JSON, да и не все поля объекта типа Marker нужно передавать в представление. Следовательно, кратчайший путь в виде списка маркеров нужно преобразовать в массив объектов анонимного типа, то есть тип переменной заранее не задан, а задаётся только при инициализации (тип такой переменной задаётся ключевым словом var). Затем уже полученный объект анонимного типа сериализуется в формат JSON и передаётся в представление.
Второй метод действия JsonResultGetRoomWithMarkers() предназначен для выдачи данных о помещении и всех его маркерах в формате JSON. Сначала этот метод извлекает из репозитория данные о помещении и маркерах. Затем, как и в предыдущем методе, данные преобразуются из двух коллекций точек помещения и маркеров в единый объект анонимного типа, содержащий необходимые сведения о помещении и маркерах. После этого данный объект сериализуется в формат JSON и передаётся в представление.
Наконец, третий метод JsonResultSearch2Json(int finish, int port).Этот метод действия используется на втором этапе поиска, когда нужно получить маркер, с которым связан текущий маркер через заданный порт. Следовательно, на вход этому методу подаётся номер текущего маркера, а также номер порта. Сначала метод определяет устройство, соответствующее текущему маркеру, а затем с помощью словаря поля Neighbours определяет связанное устройство по заданному порту-ключу и маркер, соответствующий полученному устройству. Затем, как и в предыдущих двух методах, данные преобразуются из двух объектов типа Marker в единый объект анонимного типа, содержащий текущий и найденный маркеры. После этого данный объект сериализуется в формат JSON и передаётся в представление.
Теперь, после реализации контроллера контроллера Home, нужно ещё реализовать контроллер Account. Создатели фреймворка ASP.NETMVC 4 предвидели, что это будет регулярно необходимо, поэтому автоматизировали процесс. При создании проекта веб-приложения с использованием этого фреймворка можно выбрать шаблон каркаса приложения, по которому создастся проект. При выборе шаблона Basic контроллер Account и необходимые представления создаются автоматически. При создании проекта нашего приложения как раз такой шаблон и был выбран, следовательно, после создания мы получили готовое средство для учёта пользователей. Нам же осталось только защитить необходимые части приложения от неавторизованного доступа. Было решено защитить полностью весь HomeController. Защита осуществляется с помощью атрибута Authorize. Это значит, что доступ к методам действия, а, значит, и представлениям этого контроллера получат только авторизованные пользователи.
2.3 Тестирование
В данной работе необходимо было протестировать работу классов доменной модели, классов контроллера, а также работу всего комплекса модели и контроллера. Отдельные классы тестировались с помощью модульного тестирования, благодаря архитектуре MVC получившего широкие возможности в данном приложении. Для проверки же работы системы в целом было создано тестовое представление для моделирования поиска.
Модульное тестирование (или юнит-тестирование) - заключается в изолированной проверке каждого отдельного элемента путем запуска тестов в искусственной среде. Для этого необходимо использовать драйверы и заглушки. Оценивая каждый модуль изолированно и подтверждая корректность его работы, точно установить проблему значительно проще, чем если бы элемент был частью системы[14].
VisualStudio имеет встроенную поддержку модульного тестирования. Кроме того, нужно отметить, что в VisualStudio имеется удобная панель для работы с тестами. На ней можно видеть все пройденные, не пройденные или не выполнявшиеся тесты, а также ошибки с их описанием в случае их возникновения в ходе тестирования. Также в ней можно увидеть время выполнения теста. Кроме того, панель позволяет выполнять различные манипуляции с отдельными тестами или с их группами. Панель показана на рисунке 2.9. сеть база данный контроллер
Для организации модульного тестирования нужно создать отдельный проект в VisualStudio. Чтобы это сделать, нужно при создании проекта приложения ASP.NET MVC 4 поставить галочку в соответствующее поле, и тогда автоматически в том же решении создастся проект для модульного тестирования MVC-проекта. Такой проект уже будет содержать шаблоны тестов для стандартных контроллеров, таких, как HomeController. В этих шаблонах будут модульные тесты для стандартных методов действия этих контроллеров, например, для методов Index, About и Contact. Стоит отметить, что все автоматически сгенерированные тесты будут сразу же созданы в соответствии с паттерном AAA, речь о котором пойдёт несколько позднее.
После создания тестового проекта, которому автоматически было присвоено название IndoorNavigation.Interface.Tests, нужно было добавить к нему ссылки на тестируемые проекты IndoorNavigation.Domain (модель) и IndoorNavigation.Interface (контроллеры). Так как проект тестов был создан вместе с проектом веб-приложения и, следовательно, на его основании, то он содержит автоматически сгенерированные шаблоны тестов для стандартных методов Index(), About() и Contact() контроллера HomeController. Пример такого автоматически сгенерированного тестового метода представлен на рисунке 2.10.
Рисунок 2.10. Автоматически сгенерированный тестовый метод для проверки метода действия Index()
Как видно из рисунка 2.10, при написании методов модульных тестов используется паттерн arrange/act/assert (A/A/A).Данный шаблон всего лишь разделяет и группирует код теста на 3 секции: arrange - установка и инициализация начальных условий, act - выполнение тестируемого метода, assert - проверка полученного значения (например, сравнения с ожидаемым значением). Благодаря шаблону ААА тесты становятся читабельны, понятны, последовательны и сопровождаемы[15].
Также рисунок показывает, что тестовые методы должны быть помечены атрибутом TestMethod, а класс, содержащий эти методы, помечается атрибутом TestClass. Однако, не все методы в классе модульных тестов должны быть юнит-тестами. Такие методы не должны иметь атрибут TestMethod, и тогда VisualStudio не обработает их как тестовые.
Тестирование модели
Для начала были созданы тесты для модели. Было решено тестировать классы Device, Marker, Point и ShortestPath. Остальные классы модели либо простые и тривиальные, либо сгенерированы автоматически, либо их можно протестировать вместе с перечисленными классами.
Тест для класса Device называется GetDeviceNeighbours(). Он показан на рисунке 2.11. Как видно по рисунку, структура метода соответствует шаблону ААА. В этом тесте проверяется работа метода FillPorts() класса Device(), который заполняет порты текущего устройства соседними устройствами. Сначала в части arrangeпроисходит создание класса репозитория данных. Потом происходит создание четырёх экземпляров различных устройств, которые берутся из репозитория по разным Id. Затем в части act тестируемый метод FillPorts() вызывается для каждого из созданных устройств. Наконец, в части аssert сначала для каждого устройства проверяется, что из репозитория было получено действительно нужное устройство. После этого, также для каждого устройства тестируется, произошло ли заполнение поля Neighbours. Для этого сравнивается длина списка (этого свойства) и количество фактических соседей (смежных вершин) данного устройства.
Рисунок 2.11. Модульный тест для метода FillPorts() классаDevice
Кроме предыдущего теста, были ещё написаны тесты для классов Marker и Point. Это методы GetMarkerNeighbours() и GetPointNeighbours(). Они проверяют методы FillMarker() класса Marker и FillNeighbours() классаPoint, которые заполняют, соответственно, словарь соседей текущего маркера соседними сопряжёнными маркерами и список соседних точек текущей точки, с которыми она соединена рёбрами помещений. Структура тестовых методов и способ проверки результата аналогичны тем, которые применялись для класса Device и метода FillPorts(). Код этих тестов можно посмотреть в приложении В.
После этого у нас остаётся не протестированным ещё один важнейший для нашего приложения класс - ShortestPath, который отвечает за создание графа и поиск по нему кратчайшего пути между заданными вершинами. В первую очередь нужно протестировать методы этого класса, которые отвечают за создание графа - методы FillVertices(List<Marker> markers)и FillEdges(List<Marker> markers), а также метод BuildingPath(Marker startMar, Marker finishMar, List<Marker> markers), который непосредственно отвечает за построение кратчайшего пути и выдаёт его на выходе. Тестовые методы для проверки создания графа называются FillVerticesTestMethod() для заполнения вершин и FillEdgesTestMethod() для создания рёбер графа соответственно. Структура их похожа. Сначала в части arrangeсоздаётся экземпляр класса ShortestPath и список маркеров с заполненными соседями. Для заполнения списка маркеров, чтобы не загромождать тестовые методы ненужным кодом и не дублировать этот самый код в разных тестовых методах, был создан обычный нетестовый методGetMarkers(). После этого, в части act происходит заполнение вершин графа по списку маркеров. Для метода, проверяющего создания рёбер, также заполняются рёбра графа. Наконец, в части assert проверяются полученные данные. Для этого сравнивается количество созданных вершин или рёбер с тем, которое должно быть, а также сравниваются некоторые идентификаторы вершин с фактическими. Код этих тестовых методов можно увидеть в приложении В.
Тестовый метод для тестирования метода BuildingPath(Marker startMar, Marker finishMar, List<Marker>markers) называется BuildingPathTestMethod(). Сначала в части arrange создаётся экземпляр класса ShortestPath и список маркеров с заполненными соседями. После этого, в части act происходит нахождение четырёх кратчайших путей. При этом моделируется четыре возможных случая:
1. Когда путь находится между двумя различными вершинами графа (общий случай).
2. Когда путь строится между теми же вершинами, что и в первом пункте, но в противоположном направлении.
3. Когда начало и конец пути заданы одной и той же вершиной.
4. Когда путь строится между соседними вершинами.
Наконец, в части assert проверяются полученные данные. Для этого сравниваются длины полученных маршрутов с фактическими, а также проверяется, совпадает ли длина маршрута с длиной точно такого же, но в противоположном направлении. Кроме того, для одного из маршрутов полностью проверяется, совпадают ли все вершины пути с теми, которые должны быть на самом деле. Часть assert этого тестового метода показана на рисунке ниже.
Рисунок 2.12. Часть assert тестового метода BuildingPathTestMethod()
Тестирование контроллеров
Теперь, после того, как основные классы модели протестированы, можно переходить к тестированию контроллера. Что касается контроллера HomeController, то в нём нужно было провести модульное тестирование всего для двух методов действия: GetAllMarkers(int page = 1) и Search1(), так как остальные методы либо являются тривиальными, либо автоматически сгенерированы, либо являются методами, возвращающими JsonResult, о тестировании которых речь пойдёт позднее.
Итак, для начала рассмотрим тестирование метода GetAllMarkers(int page = 1). Для этого был создан тестовый метод CanSendPaginationViewModel(). При этом, в отличие от предыдущих тестов модели, был использован mock-объект («заглушка») для фиктивной реализации интерфейса IRepository. Mock-объекты позволяют сузить фокус тестов, так чтобы вы могли проверить только тот функционал, в котором заинтересован разработчик[9]. Такие объекты используютсяпри тестировании и при TDD (Test-driven development). Преимуществ использования фиктивных объектов несколько. Во-первых, они упрощают модульный тест и делает его более гибким[9]. Во-вторых, он позволяет полностью изолировать тестируемый объект от других объектов. Если не изолировать тестируемый объект, то мы не будем знать, в каком классе возникла ошибка в случае провала теста. Для создания mock-объекта была использована библиотека Moq. Теперь расскажем про сам тестовый метод. В части arrange создаётся mock-объект mock, который будет реализовывать интерфейс IRepository. Затем этому объекту мы задаём желаемое поведение, то есть, чтобы он возвращал нам список из пяти объектов типа Marker. После этого создаём объект контроллера, передавая в его конструктор экземпляр репозитория в качестве параметра, и устанавливаем, что на одной странице представления должно отображаться 3 маркера. Далее, в части act получаем модель представления, которая формируется при вызове метода действия GetAllMarkers(2), то есть для второй страницы. Кроме того, в этой же части получаем текущую информацию о постраничном отображении, которая содержится в классе PagingInfo. Наконец, в части assert происходит сравнение полученных значений текущего номера страницы, количества элементов на странице, количества всех элементов и количества всех страниц с ожидаемыми значениями. Код этого тестового метода представлен на рисунке ниже:
Теперь перейдём к тесту, который проверяет метод действия Search1(). Он называется Search1Get() и в нём также применяется фиктивный репозиторий. В части arrange там также создаётся mock-объект mock, которому мы указываем то, что он должен возвращать при обращении. После этого создаём объект контроллера, передавая в его конструктор экземпляр репозитория в качестве параметра. Затем из того же репозитория инициализируется ещё один список маркеров, который будет эталонным. В части act мы получаем результат от вызова метода Search1() типа ViewResult. Наконец, в части assert проверяется, соответствуют ли данные модели, передаваемой в представление, ожидаемым значениям. Код этого метода приведён в приложении В.
Рисунок 2.13. Модульный тест для метода действия GetAllMarker
После этого в нашем контроллере Home остались непротестированными только методы, которые возвращают результат типа JsonResult. Дело в том, что такие методы очень легко протестировать с помощью браузера, а удобнее всего с помощью Google Chrome. Для этого нужно просто ввести URL, направленный на метод действия, в адресную строку браузера. Например:
При этом, если метод имеет параметры, то они указываются после знака «?». Разумеется, такой способ не подойдёт, если параметр имеет какой-то сложный тип, но для методов с параметрами простых типов это способ очень удобен. Таким образом были протестированы все методы, возвращающие результат типа JsonResult, то есть методыGetRoute(int start, int finish), GetRoomWithMarkers() и Search2Json(int finish, int port).
Для проверки работы системы в целом было создано тестовое представление Search1 для моделирования поиска. Код этого представления можно увидеть в приложении С. При работе с этим представлением задействуются все классы модели и почти все методы действия контроллеров, то есть с помощью одного представления можно проверить практически всю систему. Рисунок, на котором показано это представление, находится ниже.
Рисунок 2.14. Тестовое представление Search1
Заключение
В ходе работы все поставленные задачи удалось выполнить:
1. Проанализирован способ представления инженерных сетей в информационных системах.
2. Смоделирована инженерная сеть и помещение в информационной системе.
3. Проанализированы существующие алгоритмы поиска кратчайшего пути, выбран оптимальный.
4. Смоделированы, а затем проанализированы бизнес-процессы поиска, локализации и устранения неисправности.
5. Создана модель классов предметной области.
6. Описана модель базы данных информационной системы.
7. Информационная система поиска оптимального маршрута в инженерных сетях была спроектирована. В результате были получены спецификации модулей, а также выбраны средства и технологии, с помощью которых эти модули должны быть реализованы.
8. По сделанному проекту информационная система поиска оптимального маршрута в инженерных сетях была успешна разработана. Разумеется, в данной работе разрабатывалась не вся система целиком, а только серверная её часть, что и планировалось изначально. Остальные части разрабатываются другими специалистами.
Кроме того:
1. Проведено тестирование модели и контроллеров MVC-приложения.
2. Получен опыт работы со средством модульного тестирования в среде Visual Studio 2012.
3. Сделан обзор MVC-фреймворков для веб-приложений.
4. Получен опыт работы с инструментом EntityFramework 6.
5. Изучен шаблон MVC и фреймворк MVC 4 для его реализации.
6. Получен опыт работы с паттерном «Репозиторий».
Библиографический список
1. Гриценко Ю.Б., Ехлаков Ю.П., Жуковский О.И. Геоинформационные технологии мониторинга инженерных сетей: монография - Томск: Изд-во Томского гос. ун-та систем управления и радиоэлектроники, 2010. -148 с.
2. Гудов А.М., Семехина М.В. Имитационное моделирование процессов передачи трафика в вычислительных сетях // Управление большими системами, выпуск 31. - М.: Изд-во института проблем управления им. В.А. Трапезникова РАН, 2010 - 32 с.
3. Обоснование алгоритма поиска кратчайшего пути для построения схемы сети лесовозных дорог // Сибирский государственный технологический университет.
4. Моделирование процесса устранения неисправности сетями Петри // Академия государственной противопожарной службы. Архив публикаций конференций "Системы безопасности".
5. Репин В.В., Елиферов В.Г. Процессный подход к управлению. Моделирование бизнес-процессов. - М.: Манн, Иванов и Фербер, 2013. - 544 с.
6. Фримэн А. Pro ASP.NET MVC 4. 4-еизд. - США, Калифорния: Apress, 2012 - 738 с.
7. Шаллоуей А., Тротт Дж. Р. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию. Пер. с англ. -- М.: ООО "И.Д. Вильямс", 2002 - 288 стр., с ил.
Приложения
Приложение 1
Код классов модели
Код класса Device:
publicclassDevice
{
public Device()
{
this.Markers = newList<Marker>();
this.Ports = newList<Port>();
this.Ports1 = newList<Port>();
this.Neighbours = newDictionary<int, Device>();
}
publicint Id { get; set; }
publicstring Type { get; set; }
publicstring Description { get; set; }
publicNullable<int>PortQuantity { get; set; }
publicDictionary<int, Device>Neighbours { get; set; } //свойствосозданодляудобстваработы
publicvirtualICollection<Marker> Markers { get; set; }
publicvirtualICollection<Port> Ports { get; set; }
publicvirtualICollection<Port> Ports1 { get; set; }
/*метод создан для заполнения поля Neighbours (устройств, соединённых с данным).
* Можно работать с объектом класса и не заполняя его, через поля Ports и Ports1,
* но это менее удобно*/
publicvoidFillPorts()
{
Dictionary<int, Device> n = newDictionary<int, Device>();
foreach (Port p in Ports)
{
n.Add(p.Number, p.Device2);
}
IEnumerable<int>exLinks;
foreach (Portp in Ports1)
{
exLinks = from p1 in n where (p1.Value == p.Device1) select p1.Key;
inti = exLinks.Count();
if (i == 0)
{
n.Add(p.Number, p.Device1);
}
}
Neighbours = n;
}
}
Код класса LinksM:
publicpartialclassLinksM
{
publicint Id { get; set; }
publicint Marker1 { get; set; }
publicint Marker2 { get; set; }
publicint Length { get; set; }
publicbyte[] ImageData { get; set; }
publicvirtualMarkerMarker { get; set; }
publicvirtualMarker Marker3 { get; set; }
}
Код класса LinksP:
publicpartialclassLinksP
{
publicint Id { get; set; }
publicint Point1 { get; set; }
publicint Point2 { get; set; }
publicvirtualPointPoint { get; set; }
publicvirtualPoint Point3 { get; set; }
}
Код класса Point:
publicpartialclassPoint
{
public Point()
{
this.LinksPs = newList<LinksP>();
this.LinksPs1 = newList<LinksP>();
this.Neighbours = newPoint[]{};
}
publicint Id { get; set; }
publicfloat X { get; set; }
publicfloat Y { get; set; }
publicfloat Z { get; set; }
publicstring Description { get; set; }
publicPoint[] Neighbours{ get; set; } //свойствосозданодляудобстваработы
publicvirtualICollection<LinksP>LinksPs { get; set; }
publicvirtualICollection<LinksP> LinksPs1 { get; set; }
/*метод создан для заполнения поля Neighbours (точек, соединённых с данной).
* Можно работать с объектом класса и не заполняя его, через поля LinksPs и LinksPs1,
* но это менее удобно*/
publicvoidFillNeighbours()
{
List<Point> li = newList<Point>();
foreach (LinksP l inLinksPs)
{
li.Add(l.Point3);
}
IEnumerable<Point>exLinks;
foreach (LinksP l in LinksPs1)
{
exLinks = from l1 in li where (l1 == l.Point) select l1;
if (exLinks.Count() == 0)
{
li.Add(l.Point);
}
}
Neighbours = li.ToArray<Point>();
}
}
Код класса Port:
publicpartialclassPort
{
publicint Id { get; set; }
publicint Device { get; set; }
publicNullable<int>DeviceOut { get; set; }
publicint Number { get; set; }
publicvirtualDevice Device1 { get; set; }
publicvirtualDevice Device2 { get; set; }
}
Код класса ShortestPath:
publicclassShortestPath
{
publicList<Vertice> Vertices { get; privateset; }
publicList<Edge> Edges { get; privateset; }
publicVerticeBeginPoint { get; privateset; }
publicList<Marker> Path { get; set; }
//заполнение массива вершин - протестирован
publicvoidFillVertices(List<Marker> m)
{
Vertices = newList<Vertice>();
foreach (Marker m1 in m)
{
VerticecurrentV = newVertice()
{
Id = m1.Id, SomeMarker = m1, IsChecked = false, ValueMetka = Int16.MaxValue
};
Vertices.Add(currentV);
}
}
//заполнение массива рёбер
publicvoidFillEdges(List<Marker> m)
{
Edges = newList<Edge>();
foreach (Vertice v in Vertices)
{
foreach (Marker m1 inv.SomeMarker.Neighbours.Keys)
{
IEnumerable<Vertice> v1 = from v3 in Vertices where (v3.SomeMarker == m1) select v3;
Vertice v2 = v1.First();
EdgecurrentE = newEdge(v, v2, v.SomeMarker.Neighbours[m1]);
IEnumerable<Edge>existingEdge = from e1 in Edges where ((e1.FirstPoint == v2) && (e1.SecondPoint == v)) select e1;
if (existingEdge.Count() == 0)
{
Edges.Add(currentE);
}
}
}
}
///<summary>
///Запуск алгоритма расчета
///</summary>
///<param name="beginp"></param>
publicvoidAlgoritmRun(Verticebeginp)
{
if (this.Vertices.Count() == 0 || this.Edges.Count() == 0)
{
thrownewDekstraException("Массив вершин или ребер не задан!");
}
else
{
BeginPoint = beginp;
OneStep(beginp);
foreach (Vertice point in Vertices)
{
VerticeanotherP = GetAnotherUncheckedPoint();
if (anotherP != null)
{
OneStep(anotherP);
}
else
{
break;
}
}
}
}
///<summary>
/// Метод, делающий один шаг алгоритма. Принимает на вход вершину
///</summary>
///<param name="beginpoint"></param>
publicvoidOneStep(Verticebeginpoint)
{
foreach (VerticenextpinPred(beginpoint))
{
if (nextp.IsChecked == false)//не отмечена
{
floatnewmetka = beginpoint.ValueMetka + GetEdge(nextp, beginpoint).Weight;
if (nextp.ValueMetka>newmetka)
{
nextp.ValueMetka = newmetka;
nextp.predPoint = beginpoint;
}
else
{
}
}
}
beginpoint.IsChecked = true;//вычеркиваем
}
///<summary>
/// Поиск соседей для вершины. Для неориентированного графа ищутся все соседи.
///</summary>
///<param name="currpoint"></param>
///<returns></returns>
privateIEnumerable<Vertice>Pred(Verticecurrpoint)
{
IEnumerable<Vertice>firstpoints = fromffin Edges whereff.FirstPoint == currpointselectff.SecondPoint;
IEnumerable<Vertice>secondpoints = fromspin Edges wheresp.SecondPoint == currpointselectsp.FirstPoint;
IEnumerable<Vertice>totalpoints = firstpoints.Concat<Vertice>(secondpoints);
returntotalpoints;
}
///<summary>
/// Получаем ребро, соединяющее 2 входные точки
///</summary>
///<param name="a"></param>
///<param name="b"></param>
///<returns></returns>
privateEdgeGetEdge (Vertice a, Vertice b)
{//ищемребропо 2 точкам
IEnumerable<Edge>myr = fromrebin Edges where (reb.FirstPoint == a &reb.SecondPoint == b) || (reb.SecondPoint == a &reb.FirstPoint == b) selectreb;
if (myr.Count() > 1 || myr.Count() == 0)
{
thrownewDekstraException("Ненайденоребромеждусоседями!");
}
else
{
returnmyr.First();
}
}
///<summary>
/// Получаем очередную неотмеченную вершину, "ближайшую" к заданной.
///</summary>
///<returns></returns>
privateVerticeGetAnotherUncheckedPoint()
{
IEnumerable<Vertice>pointsuncheck = from p in Vertices wherep.IsChecked == falseselect p;
if (pointsuncheck.Count() != 0)
{
floatminVal = pointsuncheck.First().ValueMetka;
VerticeminPoint = pointsuncheck.First();
foreach (Vertice p inpointsuncheck)
{
if (p.ValueMetka<minVal)
{
minVal = p.ValueMetka;
minPoint = p;
}
}
returnminPoint;
}
else
{
returnnull;
}
}
//извлекает из списка вершин минимальный путь до конкретной вершины
publicList<Vertice>MinPathToVertice (MarkerendMar)
{
Vertice end = (from v in Vertices where (v.SomeMarker == endMar) select v).First();
List<Vertice>listOfpoints = newList<Vertice>();
Verticetempp = newVertice();
tempp = end;
while (tempp != this.BeginPoint)
{
listOfpoints.Add(tempp);
tempp = tempp.predPoint;
}
listOfpoints.Add(tempp);
returnlistOfpoints;
}
//построение массива рёбер и вершин, запуск алгоритма, вывод пути
publicList<Marker>BuildingPath(MarkerstartMar, MarkerfinishMar, List<Marker> markers)
{
this.FillVertices(markers);
this.FillEdges(markers);
Vertice start = (from v in Vertices where (v.SomeMarker == startMar) select v).First();
Vertice finish = (from v in Vertices where (v.SomeMarker == finishMar) select v).First();
finish.ValueMetka = 0;
this.AlgoritmRun(finish);
string result = "";
if (finish != this.BeginPoint)
{
string s = string.Empty;
foreach (Vertice p1 inthis.MinPathToVertice(finishMar))
{
s += string.Format("{0} ", p1.Id);
}
result = string.Format("Point ={0}, MinPath from {1} = {2}", finish.Id, this.BeginPoint.Id, s);
}
List<Marker>resultM = newList<Marker>();
foreach (Vertice v inthis.MinPathToVertice(startMar))
{
resultM.Add(v.SomeMarker);
}
returnresultM;//выдаёт список маркеров в обратном порядке
}
classDekstraException :ApplicationException//генерация исключений
{
publicDekstraException(string message)
: base(message)
{
}
}
}
Код класса IndoorNavigationContext:
publicpartialclassIndoorNavigationContext :DbContext
{
staticIndoorNavigationContext()
{
Database.SetInitializer<IndoorNavigationContext>(null);
}
publicIndoorNavigationContext()
: base("Name=IndoorNavigationContext")
{
}
publicDbSet<Device> Devices { get; set; }
publicDbSet<LinksM>LinksMs { get; set; }
publicDbSet<LinksP>LinksPs { get; set; }
publicDbSet<Marker> Markers { get; set; }
publicDbSet<Point> Points { get; set; }
publicDbSet<Port> Ports { get; set; }
protectedoverridevoidOnModelCreating(DbModelBuildermodelBuilder)
{
modelBuilder.Configurations.Add(newDeviceMap());
modelBuilder.Configurations.Add(newLinksMMap());
modelBuilder.Configurations.Add(newMarkerMap());
modelBuilder.Configurations.Add(newLinksPMap());
modelBuilder.Configurations.Add(newPointMap());
modelBuilder.Configurations.Add(newPortMap());
}}
Приложение 2
Код модульных тестов
Код тестового метода GetMarkerNeighbours():
[TestMethod]
publicvoidGetMarkerNeighbours()
{
//arrange
EFRepository repo = newEFRepository();
Marker m1 = repo.Markers.Where(m =>m.Id == 1).First();
Marker m2 = repo.Markers.Where(m =>m.Id == 2).First();
Marker m6 = repo.Markers.Where(m =>m.Id == 6).First();
//act
m1.FillMarker();
m2.FillMarker();
m6.FillMarker();
//assert
Assert.AreEqual<string>("первый", m1.Description);
Assert.AreEqual<int>(3, m1.Neighbours.Count);
Assert.AreEqual<int>(1, repo.Markers.Where(m =>m.Id == 1).Count());
Assert.AreEqual<int>(7, m1.Neighbours[m2]);
Assert.AreEqual<string>("второй", m2.Description);
Assert.AreEqual<int>(3, m2.Neighbours.Count);
Assert.AreEqual<string>("шестой", m6.Description);
Assert.AreEqual<int>(3, m6.Neighbours.Count);
}
Код тестового метода GetPointNeghbours():
[TestMethod]
publicvoidGetPointNeghbours()
{
//arrange
EFRepository repo = newEFRepository();
Point p1 = repo.Points.First();
Point p2 = repo.Points.Where(p =>p.Id == 2).First();
Point p3 = repo.Points.Where(p =>p.Id == 3).First();
Point p4 = repo.Points.Where(p =>p.Id == 4).First();
//act
p1.FillNeighbours();
p2.FillNeighbours();
p3.FillNeighbours();
p4.FillNeighbours();
//assert
Assert.AreEqual<string>("внешнийуголнижний ", p1.Description);
Assert.AreEqual<int>(2, p1.Neighbours.Count());
Assert.AreEqual<string>("внешнийуголнижний 4", p2.Description);
Assert.AreEqual<int>(1, p2.Neighbours.Count());
Assert.AreEqual<string>("внешнийуголнижний 2", p3.Description);
Assert.AreEqual<int>(1, p3.Neighbours.Count());
Assert.AreEqual<string>("внешнийуголнижний 3", p4.Description);
Assert.AreEqual<int>(0, p4.Neighbours.Count());
}
Код тестового метода FillVerticesTestMethod():
[TestMethod]
publicvoidFillVerticesTestMethod()
{
//Arrange
ShortestPath s1 = newShortestPath();
List<Marker> markers = GetMarker();
//Act
s1.FillVertices(markers);
//Assert
Assert.AreEqual<int>(6, s1.Vertices.Count);
Assert.AreEqual<int>(s1.Vertices[0].SomeMarker.Id, first.Id);
Assert.AreEqual<int>(s1.Vertices[5].SomeMarker.Id, sixth.Id);
}
Код модульного теста FillEdgesTestMethod():
[TestMethod]
publicvoidFillEdgesTestMethod()
{
//Arrange
ShortestPath s1 = newShortestPath();
List<Marker> markers = newList<Marker>();
markers = GetMarker();
//Act
s1.FillVertices(markers);
s1.FillEdges(markers);
//Assert
Assert.AreEqual<int>(9, s1.Edges.Count);
}
Код модульного теста Search1Get():
[TestMethod]
publicvoid Search1Get()
{
// Arrange
Mock<IRepository> mock = newMock<IRepository>();
mock.Setup(m =>m.Markers).Returns(newMarker[] {
newMarker() {Id = 0,Description = "основной", Neighbours = null},
newMarker() {Id = 1,Description = "первый", Neighbours = null},
newMarker() {Id = 2,Description = "второй", Neighbours = null},
newMarker() {Id = 3, Description = "третий", Neighbours = null},
newMarker() {Id = 4, Description = "четвёртый", Neighbours = null}
}.AsQueryable());
HomeController c1 = newHomeController(mock.Object);
List<Marker> test = mock.Object.Markers.ToList<Marker>();
foreach (Marker m in test)
{
m.FillMarker();
}
// Act
ViewResult result = c1.Search1();
//Assert
Assert.AreEqual(test.First().Id, ((List<Marker>)result.Model).First().Id);
Assert.AreEqual(4, ((List<Marker>)result.Model)[4].Id);
}
Приложение 3
Код тестового представления Search1
Код тестового представления Search:
@usingIndoorNavigation.Domain.ModelClasses
@usingIndoorNavigation.Interface.Models
@modelSearch1Model
@{
Layout = null;
}
<!DOCTYPEhtml>
<html>
<head>
<metacharset="utf-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Поиск</title>
<linkhref="~/Content/bootstrap.css"rel="stylesheet"/>
<linkhref="~/Content/bootstrap-responsive.css"rel="stylesheet"/>
<scriptsrc="~/Scripts/bootstrap.js"></script>
<scriptsrc="http://code.jquery.com/jquery-latest.js"></script>
<scriptsrc="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<!-- Le styles -->
<styletype="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.container-narrow>hr
{
margin: 30px0;
}
.sidebar-nav {
padding: 9px0;
}
</style>
<scripttype="text/javascript">
//функции открытия/закрытия окон
$(document).ready(function () {
$("#open_button").click(function () {
$("#search1form").slideToggle(200);
$("#search2form").css("display", "none");
});
$("#placeForRoom").click(function () {
$("#search1form").css("display", "none");
$("#search2form").css("display", "none");
});
$("#search2").click(function () {
if ($("#search2").attr("onclick") != "") {
$("#search1form").css("display", "none");
$("#search2form").slideToggle(200);
}
});
$("#search1go").click(function () {
$("#search2").attr({ onclick: "Search2()" });
});
$("#open_button_2").click(function () {
$("#search2form").slideToggle(200);
$("#search1form").css("display", "none");
});
});
</script>
<script>
functionGenerateGetRoom() {
$("#generateGetRoom").click();
}
/* в эту функцию вставляй функции, которые визуализируют кратчайший путь. параметр data
выдаётся методом действия GetRoute, поэтому структуру параметра (его поля) смотри там*/
functionProcessDataPath(data) {
$("#finish").val(data[data.length - 1].Id);
$("#finishDouble").val(data[data.length - 1].Id);
$("#portBlock").empty();
var select = "<select id=\"port\" data-val=\"true\" name=\"port\">";
for (vari = 0; i< data[data.length - 1].Keys.length; i++) {
select = select + "<option>" + data[data.length - 1].Keys[i] + "</option>";
}
select = select + "</select>";
$("#portBlock").append(select);
//ниже - тестовый код. вместо него вставляй свои функции
var target = $("#placeForRoom");
target.empty();
$("#placeForRoom").css("font-size", 18);
for (vari = 0; i<data.length; i++) {
var marker = data[i];
target.append("<tr><td>" + marker.Id + "</td><td>"
+ marker.Description + "</td><td>" + marker.DeviceId + "</td></tr>");
}
}
/*в эту функцию вставляй функции, которые визуализируют помещение с маркерами. параметр data выдаётся методом действия GetRoomWithMarkers*/
functionProcessDataRoom(data) {
//это - тестовый код
if (data != null) {
var mar = data.markers;
$("#placeForRoom").append(mar[4].Description);
}
}
/*в эту функцию вставляй функции, которые визуализируют связь между конечным маркером и устройством, связанным через порт. параметр data выдаётся методом действия Search2Json*/
functionProcessDataPort(data) {
//это тестовый код
returnwindow.alert(data.linkedMar.Description);
}
</script>
</head>
<bodyonload="GenerateGetRoom()">
<divclass="navbarnavbar-inverse navbar-fixed-top">
<divclass="navbar-inner">
<divclass="container-fluid">
<buttontype="button"class="btnbtn-navbar"data-toggle="collapse"data-target=".nav-collapse">
<spanclass="icon-bar"></span>
<spanclass="icon-bar"></span>
<spanclass="icon-bar"></span>
</button>
@Html.ActionLink("Инженерная indoor-навигация", "Index", "Home", null, new { @class = "brand" })
<divclass="nav-collapse collapse">
<pclass="navbar-text pull-right">
Logged in as <ahref="#"class="navbar-link">Андрей</a>
</p>
<ulclass="nav">
<li>@Html.ActionLink("Главная", "Index", null, new { @class = "active" })</li>
<li>@Html.ActionLink("О программе", "About")</li>
<li>@Html.ActionLink("Контакты", "Contact")</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<divclass="container-fluid">
<divclass="row-fluid">
<divclass="span3">
<divclass="well sidebar-nav">
<ulclass="navnav-list">
<li>@Html.ActionLink("Опрограмме \u00BB", "About", null, new { @class = "btn-link" })</li>
<li>@Html.ActionLink("Омаркерах \u00BB", "GetAllMarkers", null, new { @class = "btn-link" })</li>
<li>@Html.ActionLink("Онас \u00BB", "Contact", null, new { @class = "btn-link" })</li>
<li><aclass="btn-link">Будущеепроекта»</a></li>
<li>@Html.ActionLink("Использование \u00BB", "Search1", null, new { @class = "btn-link" })</li>
</ul>
</div>
</div>
<divclass="span9 thumbnail"style="background-image:url(../Images/plan.jpg); height:550px; background-repeat: no-repeat; background-size:cover;">
<divstyle="position:fixed;">
<buttonid="open_button"style="background-color:white;"><imgsrc="~/Images/MAP.png"/></button>
</div>
<divid="search1form"class="form-actions"style="position:fixed; margin-top: 55px; display:none;">
<pid="open"style="font-weight: bold">Данныедляпоиска</p>
@using (Ajax.BeginForm("GetRoute", "Home", newAjaxOptions
{
OnSuccess = "ProcessDataPath",
Url = Url.Action("GetRoute", new { start = Model.Start, finish = Model.Finish }),
HttpMethod = "POST",
UpdateTargetId = "placeForRoom"
}))
{
<div>
@Html.Label("Start", "Введите начальный маркер пути:")
@Html.DropDownListFor(m =>m.Start, newSelectList(Model.Markers.Select(m =>m.Id)))
</div>
<div>
@Html.Label("Finish", "Введите конечный маркер пути:")
@Html.DropDownListFor(m =>m.Finish, newSelectList(Model.Markers.Where(m=>m.Device != null).Select(m =>m.Id)))
</div>
<inputid="search1go"type="submit"value="Начатьпоиск"class="btnbtn-info"/>
<aid="search2"class="btn"href="#"onclick=""><iclass="icon-forward"></i></a>
}
</div>
<divid="search2form"class="form-actions"style="position:fixed; margin-top: 55px; display:none;">
<pstyle="font-weight: bold">Второйэтаппоиска</p>
@using (Ajax.BeginForm("Search2Json", "Home", newAjaxOptions
{
OnSuccess = "ProcessDataPort",
Url = Url.Action("Search2Json", new { }),
HttpMethod = "POST",
UpdateTargetId = "placeForRoom"
}))
{
<div>
@Html.Label("FinishLabel", "Маркер:")
@Html.TextBox("finish", 1, new {style = "display:none"})
@Html.TextBox("finishDouble", 1, new {disabled="disabled"})
@Html.Label("PortLabel", "Введите номер выбранного порта:")
</div>
<divid="portBlock">
@{
@Html.DropDownList("port", newSelectList((Session["Finish"] asMarker).Device.Neighbours.Keys.ToString()), "1")
}
</div>
<inputtype="submit"value="Начатьпоиск"class="btnbtn-info"/>
}
</div>
<divid="placeForRoom"><!--Сюда вставляй canvas, где будет визуализация помещения--></div>
@Ajax.ActionLink("Вызвать данные о помещении с маркерами", "GetRoomWithMarkers", null,
newAjaxOptions()
{
OnSuccess = "ProcessDataRoom",
Url = Url.Action("GetRoomWithMarkers")
},
new { id = "generateGetRoom", style = "display:none" })
</div>
</div>
</div>
</body>
</html>
Размещено на Allbest.ru
...Подобные документы
Разработка алгоритма реализации на ЭВМ процесса поиска кратчайшего пути в графе методом Дейкстры. Программная реализация алгоритма поиска кратчайшего пути между двумя любыми вершинами графа. Проверка работоспособности программы на тестовых примерах.
реферат [929,8 K], добавлен 23.09.2013Разработка программного продукта для поиска максимально удалённых вершин в графе. Характеристика ориентированного, смешанного и изоморфного графов. Обзор способов представления графа в информатике. Алгоритм поиска пути. Графический интерфейс программы.
курсовая работа [384,0 K], добавлен 10.01.2015Функциональная схема объекта заданной структуры. Выбор алгоритма диагностирования. Построение принципиальной схемы дешифратора технического объекта. Выбор элементной базы и построение принципиальной схемы устройства автоматического поиска неисправностей.
контрольная работа [196,9 K], добавлен 28.01.2017Алгоритм сортировки Шейкер: математическое описание задачи и описание алгоритма. Алгоритм покрытия: построение одного кратчайшего покрытия. Описание схемы и работы алгоритма на графах: нахождение кратчайшего пути. Контрольные примеры работы алгоритмов.
курсовая работа [43,8 K], добавлен 19.10.2010Особенности проведения поиска по реквизитам документа, контексту, специализированным классификаторам (тематический), интеллектуальный. Средства и инструменты поиска в компьютерных справочно-правовых системах "гарант", "консультантплюс", "кодекс".
реферат [25,9 K], добавлен 19.03.2016Описание алгоритма сортировки с двоичным включением, выбор структур данных. Пример сортировки массива, отсортированного случайным образом. Алгоритм покрытия по методу "Построение одного кратчайшего покрытия". Волновой алгоритм поиска длиннейшего пути.
курсовая работа [78,2 K], добавлен 24.09.2010Методы реализации алгоритмов сортировки и алгоритмов поиска на языках программирования высокого уровня. Программирование алгоритмов сортировки и поиска в рамках создаваемого программного средства на языке Delphi. Создание руководства пользователя.
курсовая работа [1,7 M], добавлен 16.04.2012Состояние систем управления инженерными сетями. Выбор системы-прототипа и ее описание со всеми видами обеспечения. Разработка автоматизированной информационной системы мониторинга инженерных сетей, принцип работы и используемое программное обеспечение.
дипломная работа [1,9 M], добавлен 21.01.2015Встроенные средства устранения неполадок Windows. Диагностика неисправностей операционной системы. Запуск и проверка памяти. Правила работы в помещениях оснащенных персональными электронными вычислительными машинами и другим электронным оборудованием.
курсовая работа [38,6 K], добавлен 29.04.2014Разработка приложений баз данных Delphi. Построение концептуальной модели, атрибуты сущностей и связей. Проектирование приложения для ведения базы данных телефонных номеров с возможностью поиска по всем имеющимся полям. Тестирование программного средства.
курсовая работа [641,7 K], добавлен 17.08.2013Моделирование бизнес-процессов как средство поиска путей оптимизации деятельности компании. Методология SADT (структурный анализ и проектирование), семейство стандартов IDEF и алгоритмические языки в основе методологий моделирования бизнес-процессов.
реферат [21,7 K], добавлен 14.12.2011Фреймовые модели представления знаний. Разработка структуры фреймов для реализации экспертной системы. Разработка экспертной системы с фреймовой моделью представления знаний. Редактирование базы фактов кандидатов и описание режима консультации.
курсовая работа [1,3 M], добавлен 13.10.2012Блок-схема алгоритма Флойда. Разработка его псевдокода в программе Microsoft Visual Studio. Программа реализации алгоритмов Беллмана-Форда. Анализ трудоемкости роста функции. Протокол тестирования правильности работы программы по алгоритму Флойда.
курсовая работа [653,5 K], добавлен 18.02.2013Удовлетворение информационной потребности как цель поиска информации. Виды информационных ресурсов. Понятие документа в информационном поиске. Схема информационного поиска, этапы его представления. Характеристика качества поиска, его базовые положения.
презентация [1,2 M], добавлен 06.01.2014Анализ аналогов создаваемой АИС. Основные используемые методы разработки, описание модели жизненного цикла. Способы поддержки целостности базы данных и бизнес-процессов, описание интерфейса системы. Организация политики безопасности и доступа к БД.
курсовая работа [1,2 M], добавлен 29.11.2008Создание контекстной диаграммы информационной системы библиотеки. Основные компоненты и особенности ведения каталогов книг и читателей. Моделирование систем поиска и формирования заказов. Разработка диаграммы дерева узлов и логической модели базы данных.
курсовая работа [1,1 M], добавлен 24.06.2013Описание структуры бинарного дерева поиска на языке C# среды Visual Studio. Требования к интерфейсу пользователя, структуре данных и программным средствам. Компоненты программных средств, результаты тестирования, диаграммы вариантов использования классов.
курсовая работа [968,2 K], добавлен 26.01.2013Организационная структура цеха тепловых сетей, информационная связь с другими подразделениями предприятия. Автоматизация отслеживания водяных насосов и скважин с помощью информационных технологий. Разработка базы данных для паспортизации участков сетей.
отчет по практике [149,7 K], добавлен 28.09.2015Общие сведения о предприятии, его информационных системах и технологиях. Анализ информационной безопасности и условий труда. Разработка моделей AS-IS и TO-BE бизнес-процесса "Склад". Выявление недостатков модели "Обработать товар", пути их устранения.
отчет по практике [1,3 M], добавлен 01.10.2013Создание базы данных, выполнение поиска, изменение и удаление записей, обработка, проектирование и обмен данными. Определение формул для вычисляемой части базы данных. Заполнение таблицы с помощью Мастера форм. Формы представления и анализ информации.
учебное пособие [5,0 M], добавлен 12.08.2009