Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing bower_components and fixing typo #1529

Merged
merged 1 commit into from May 26, 2015

Conversation

Projects
None yet
6 participants
@sayedihashimi
Copy link
Contributor

commented May 19, 2015

No description provided.

@shiftkey

This comment has been minimized.

Copy link
Member

commented May 19, 2015

@sayedihashimi I've found this advice about it, but do you have a more official URL handy for us to point to?

@sayedihashimi

This comment has been minimized.

Copy link
Contributor Author

commented May 20, 2015

Adding @madskristensen and @DamianEdwards who were more involved in the discussion regarding this than I was.

@sayedihashimi

This comment has been minimized.

Copy link
Contributor Author

commented May 21, 2015

Accidently hit the close button.

@barrytang

This comment has been minimized.

Copy link

commented May 21, 2015

There are basically two workflows we want to support going forward:

  1.  People reference ./wwwroot/lib/bower_components directly (this is also how our default template is configured too)
    
  2.  People use build steps to copy files under bower_components to ./wwwroot 
    

We don’t want to special case bower_components for SCC since for workflow #1, people would want to check in ./wwwroot/lib/bower_components.

@balachir

This comment has been minimized.

Copy link

commented May 26, 2015

@shiftkey, does Barry's comment address your concerns?

@shiftkey

This comment has been minimized.

Copy link
Member

commented May 26, 2015

@balachir 👍

shiftkey added a commit that referenced this pull request May 26, 2015

Merge pull request #1529 from sayedihashimi/master
Removing bower_components and fixing typo

@shiftkey shiftkey merged commit 8559c8a into github:master May 26, 2015

@kspearrin

This comment has been minimized.

Copy link

commented on 7471960 Jun 11, 2015

What was the reason for removing bower_components?

This comment has been minimized.

Copy link
Member

replied Jun 11, 2015

@kspearrin see the discussion in #1529

@OsirisTerje OsirisTerje referenced this pull request Nov 19, 2015

Closed

Fixed gitignore #1

peterblazejewicz added a commit to peterblazejewicz/generator-aspnet that referenced this pull request Jan 6, 2016

Remove Bower rule. See github/gitignore#1529
This commit updates file state to upstream project.
Thanks!

@corysimmons corysimmons referenced this pull request Feb 4, 2016

Closed

Bower gitignore added #1724

nevasys referenced this pull request in nevasys/MGL805ACME Feb 3, 2017

Zaggg added a commit to Zaggg/job-fire-service that referenced this pull request May 9, 2017

.gitignore
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (github/gitignore#1529 (comment))
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

bqh-kaiserhl pushed a commit to kaiserhl/gitignore that referenced this pull request Jul 8, 2017

Merge pull request github#1529 from sayedihashimi/master
Removing bower_components and fixing typo

OzieDeviL added a commit to OzieDeviL/Calltime that referenced this pull request Aug 13, 2017

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (github/gitignore#1529 (comment))
bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Ignore Theme Files
/Calltime.Web/Theme/
/Calltime.Web/assets/
/Calltime.Web/assets

# Ignore runtime scripts
/Calltime.Web/Scripts
/Calltime.Web/Scripts/

OzieDeviL added a commit to OzieDeviL/Calltime that referenced this pull request Aug 13, 2017

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (github/gitignore#1529 (comment))
bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Ignore Theme Files
/Calltime.Web/Theme/
/Calltime.Web/assets/
/Calltime.Web/assets

# Ignore runtime scripts
/Calltime.Web/Scripts
/Calltime.Web/Scripts/
@hsn95

This comment has been minimized.

Copy link

commented Oct 24, 2017

..

Xarybdis pushed a commit to Xarybdis/FinalProjectForAipLec that referenced this pull request Apr 5, 2018

consithe1
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# Visual Studio 2017 auto generated files
Generated\ Files/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# Benchmark Results
BenchmarkDotNet.Artifacts/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json

# StyleCop
StyleCopReport.xml

# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# Visual Studio Trace Files
*.e2e

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Including strong name files can present a security risk
# (github/gitignore#2483 (comment))
#*.snk

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (github/gitignore#1529 (comment))
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Tabs Studio
*.tss

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
*.binlog

# NVidia Nsight GPU debugger configuration file
*.nvuser

Eryl2000 added a commit to Eryl2000/TicTacToeMachineLearning that referenced this pull request Jul 2, 2018

Imported into Microsoft Visual Studio
diff --git a/.gitignore b/.gitignore
index a48f643..9f32482 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,35 +1,362 @@
-# Prerequisites
-*.d
-
-# Compiled Object files
-*.slo
-*.lo
-*.o
-*.obj
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Compiled Dynamic libraries
-*.so
-*.dylib
-*.dll
-
-# Fortran module files
-*.mod
-*.smod
-
-# Compiled Static libraries
-*.lai
-*.la
-*.a
-*.lib
-
-# Executables
-*.exe
-*.out
-*.app
-
-# Log files for saved players
-*.log
\ No newline at end of file
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+
+# Precompiled Headers
+*.gch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
\ No newline at end of file
diff --git a/Genetic.cpp b/Genetic.cpp
index 4ebd56a..3d04407 100644
--- a/Genetic.cpp
+++ b/Genetic.cpp
@@ -1,6 +1,7 @@

 #include "Genetic.h"

+
 //mutationRate is in the range [0, 1], greedyPercent is in the range [0, 1]
 Genetic::Genetic(const float mutationRate, const float greedyPercent)
 		: m_mutationRate(clamp(mutationRate, 0.0f, 1.0f))
@@ -15,7 +16,7 @@ void Genetic::setPopulationSize(int populationSize){
 //Make new players based on how successful the current ones are
 void Genetic::breed(vector<playerContainer<NeuralPlayer> >& population){
 	vector<playerContainer<NeuralPlayer> > newPop;
-	newPop.resize(m_populationSize);
+	newPop.reserve(m_populationSize);

 	//Keep the best greedyPercent of last generation
 	int numToKeep = (int)(m_greedyPercent * (float)m_populationSize);
@@ -25,18 +26,18 @@ void Genetic::breed(vector<playerContainer<NeuralPlayer> >& population){

 	//Copy the players which are being kept from greedyPercent
 	for(int i = 0; i < numToKeep; ++i){
-		newPop[i] = population[m_populationSize - 1 - i];
+		newPop.push_back(population[m_populationSize - 1 - i]);
 	}

 	//Iterates over the remaining child elements
 	for(int i = numToKeep; i < m_populationSize; ++i){
 		playerContainer<NeuralPlayer> parent1 = pickParent(population);
 		playerContainer<NeuralPlayer> parent2 = pickParent(population);
-		vector<Matrix> newWeights = crossOver(parent1, parent2);
+		vector<MatrixXd> newWeights = crossOver(parent1, parent2);

 		playerContainer<NeuralPlayer> temp(population[m_populationSize-1 - i]);
 		temp.player.neural.setWeights(newWeights);
-		newPop[i] = temp;
+		newPop.push_back(temp);
 	}
 	population = newPop;
 }
@@ -50,17 +51,17 @@ void Genetic::mutate(vector<playerContainer<NeuralPlayer> >& population){
 	int numToKeep = (int)(m_greedyPercent * (float)m_populationSize);

 	for(int i = numToKeep; i < m_populationSize; ++i){
-	    vector<Matrix> weights = population[i].player.neural.getWeights();
+	    vector<MatrixXd> weights = population[i].player.neural.getWeights();
 		size_t layers = weights.size();

 		//For each layer
 		for(size_t lay = 0; lay < layers; ++lay){
-			int rows = weights[lay].numRows();
-			int cols = weights[lay].numCols();
+			int rows = weights[lay].rows();
+			int cols = weights[lay].cols();

 			//Randomly mutate each element
-			for(int row = 0; row < rows; ++row){
-				for(int col = 0; col < cols; ++col){
+			for(int col = 0; col < cols; ++col){
+				for(int row = 0; row < rows; ++row){
 					//Mutate with a certain chance
 					if( ((float)rand() / float(RAND_MAX)) < m_mutationRate){
 						weights[lay](row, col) += distribution(gen);
@@ -98,10 +99,10 @@ playerContainer<NeuralPlayer> Genetic::pickParent(
 	return population.back();
 }

-vector<Matrix> Genetic::crossOver(const playerContainer<NeuralPlayer> parent1,
-								  const playerContainer<NeuralPlayer> parent2){
-	vector<Matrix> weights1;
-	vector<Matrix> weights2;
+vector<MatrixXd> Genetic::crossOver(const playerContainer<NeuralPlayer>& parent1,
+								  const playerContainer<NeuralPlayer>& parent2){
+	vector<MatrixXd> weights1;
+	vector<MatrixXd> weights2;

 	//Parent 1
     weights1 = parent1.player.neural.getWeights();
@@ -111,12 +112,12 @@ vector<Matrix> Genetic::crossOver(const playerContainer<NeuralPlayer> parent1,

 	//For each layer
 	for(size_t i = 0; i < length; ++i){
-		int rows = weights1[i].numRows();
-		int cols = weights1[i].numCols();
+		int rows = weights1[i].rows();
+		int cols = weights1[i].cols();

 		//Cross breed matrix
-		for(int row = 0; row < rows; ++row){
-			for(int col = 0; col < cols; ++col){
+		for(int col = 0; col < cols; ++col){
+			for(int row = 0; row < rows; ++row){
 				//50% chance of being from parent1 or parent2
 				if(rand() % 2 == 0){
 					weights1[i](row, col) = weights2[i](row, col);
diff --git a/Genetic.h b/Genetic.h
index 3c1563a..9d3ed76 100644
--- a/Genetic.h
+++ b/Genetic.h
@@ -4,7 +4,9 @@
 #include <iostream>
 #include <random>

-#include "Matrix.h"
+#include <Eigen/Dense>
+using namespace Eigen;
+
 #include "NeuralNet.h"
 #include "Player.h"
 #include "main.h"
@@ -24,8 +26,8 @@ public:
     void mutate(vector<playerContainer<NeuralPlayer> >& population);

 private:
-    vector<Matrix> crossOver(const playerContainer<NeuralPlayer> parent1,
-                             const playerContainer<NeuralPlayer> parent2);
+    vector<MatrixXd> crossOver(const playerContainer<NeuralPlayer>& parent1,
+                             const playerContainer<NeuralPlayer>& parent2);

     playerContainer<NeuralPlayer> pickParent(
             const vector<playerContainer<NeuralPlayer> >& population) const;
diff --git a/Matrix.cpp b/Matrix.cpp
deleted file mode 100644
index e445b7d..0000000
--- a/Matrix.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-
-#include "Matrix.h"
-
-
-
-
-//Size Constructor
-Matrix::Matrix(const unsigned int rows, const unsigned int cols)
-        : m_rows(rows)
-        , m_cols(cols){
-    if (rows == 0 || cols == 0){
-        cerr << "Error: Matrix size constructor has 0 size" << endl;
-        exit(1);
-    }
-    m_data = new double[rows * cols];
-}
-
-//Copy constructor
-Matrix::Matrix(const Matrix& m)
-        : m_rows(m.m_rows)
-        , m_cols(m.m_cols){
-    if (m_rows <= 0 || m_cols <= 0){
-        cerr << "Error: Matrix copy constructor has 0 size" << endl;
-        exit(1);
-    }
-    m_data = new double[m_rows * m_cols];
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            m_data[m_cols * row + col] = m.m_data[m.m_cols * row + col];
-        }
-    }
-}
-
-//Sets all matrix elements to 'n'
-void Matrix::initialize(const int n){
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            m_data[m_cols * row + col] = n;
-        }
-    }
-}
-
-vector<double> Matrix::toVector() const{
-    vector<double> temp;
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            temp.push_back(m_data[m_cols * row + col]);
-        }
-    }
-    return temp;
-}
-
-unsigned int Matrix::numRows() const{
-    return m_rows;
-}
-
-unsigned int Matrix::numCols() const{
-    return m_cols;
-}
-
-//Prints the matrix as a grid to the console
-void Matrix::printData() const{
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            printf("%9.4lf", m_data[m_cols * row + col]);
-        }
-        cout << endl;
-    }
-}
-
-//Returns a copy of itself which is transposed
-Matrix Matrix::transpose() const{
-    Matrix temp(m_cols, m_rows);
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            temp(col, row) = m_data[m_cols * row + col];
-        }
-    }
-    return temp;
-}
-
-//Destructor
-Matrix::~Matrix(){
-    delete[] m_data;
-}
-
-//Override = operator to copy each element
-void Matrix::operator= (const Matrix& m){
-    if(m.numRows() != m_rows || m.numCols() != m_cols){
-        cerr << "Error: Matrix sizes are not equivalent. Cannot perform \
-        assignment." << endl;
-        exit(1);
-    }
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            m_data[m_cols * row + col] = m.m_data[m.m_cols * row + col];
-        }
-    }
-}
-
-//Override - (unary) operator to negate each element
-Matrix Matrix::operator- () const{
-    Matrix temp(m_rows, m_cols);
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            temp(row, col) = -1 * m_data[m_cols * row + col];
-        }
-    }
-    return temp;
-}
-
-//Override + operator to add elementwise
-Matrix Matrix::operator+ (const Matrix& a) const{
-    if(a.numRows() != m_rows || a.numCols() != m_cols){
-        cerr << "Error: Matrix sizes are not equivalent. Cannot perform \
-        addition." << endl;
-        exit(1);
-    }
-    Matrix temp(m_rows, m_cols);
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            temp(row, col) = a(row, col) + m_data[m_cols * row + col];
-        }
-    }
-    return temp;
-}
-
-//Override - operator to subtract elementwise
-Matrix Matrix::operator- (const Matrix& a) const{
-    if(a.numRows() != m_rows || a.numCols() != m_cols){
-        cerr << "Error: Matrix sizes are not equivalent. Cannot perform \
-        subtraction." << endl;
-        exit(1);
-    }
-    Matrix temp(m_rows, m_cols);
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            temp(row, col) = m_data[m_cols * row + col] - a(row, col);
-        }
-    }
-    return temp;
-}
-
-//Override * operator to multiply elementwise by a constant
-Matrix Matrix::operator* (const int a) const{
-    Matrix temp(m_rows, m_cols);
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            temp(row, col) = a * m_data[m_cols * row + col];
-        }
-    }
-    return temp;
-}
-
-//Override * operator to perform standard matrix multiplication
-Matrix Matrix::operator* (const Matrix& a) const{
-    if(m_cols != a.numRows()){
-        cerr << "Error: Matrix sizes are incompatible. Cannot perform \
-        matrix multiplication." << endl;
-        exit(1);
-    }
-    Matrix temp(m_rows, a.m_cols);
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < a.m_cols; ++col){
-            //perform cross product between current row and current column
-            temp(row, col) = 0;
-            for(unsigned int element = 0; element < m_cols; ++element){
-                temp(row, col) += m_data[m_cols * row + element]
-                                  * a(element, col);
-            }
-        }
-    }
-    return temp;
-}
-
-//Override () operator to allow access at a specific location
-double& Matrix::operator() (const unsigned int row, const unsigned int col){
-    if (row >= m_rows || col >= m_cols ){
-        cerr << "Error: Matrix subscript out of bounds (too large)." << endl;
-        exit(1);
-    }
-    return m_data[m_cols * row + col];
-}
-
-//Override () operator to allow access at a specific location
-double Matrix::operator() (const unsigned int row,
-                           const unsigned int col) const{
-    if (row >= m_rows || col >= m_cols){
-        cerr << "Error: Matrix subscript out of bounds (too large)." << endl;
-        exit(1);
-    }
-    return m_data[m_cols * row + col];
-}
-
-//Sets each element to a random double in the range [min, max] with specified
-//resolution
-void Matrix::initRand(const double min, const double max,
-                      const unsigned int resolution){
-    if(min > max){
-        cerr << "Error: initRand(): Min is larger than max." << endl;
-        exit(1);
-    }
-    if(resolution == 0){
-        cerr << "Error: initRand(): Resolution is equal to 0" << endl;
-        exit(1);
-    }
-    for(unsigned int row = 0; row < m_rows; ++row){
-        for(unsigned int col = 0; col < m_cols; ++col){
-            /* resolution represents how many pieces each (int) is broken into.
-             * bound is used because we can generate ints better than doubles.
-             * bound is the product of the total range * resolution.
-             * Afterward, we divide bound by resolution to get a double.
-             */
-            int bound = (int)( (double)resolution * (max - min) );
-            //The double value is created by dividing bound by resolution
-            double randDouble = min + (double)(rand() % bound) / resolution;
-            //Passed into the matrix
-            m_data[m_cols * row + col] = randDouble;
-        }
-    }
-}
-
-Matrix Matrix::addRowsCols(unsigned int extraRows, unsigned int extraCols,
-                           const double value){
-    unsigned int newRows = m_rows + extraRows;
-    unsigned int newCols = m_cols + extraCols;
-    Matrix temp(newRows, newCols);
-
-    for(unsigned int row = 0; row < newRows; ++row){
-        for(unsigned int col = 0; col < newCols; ++col){
-            if(row < m_rows && col < m_cols){
-                temp(row, col) = m_data[m_cols * row + col];
-            } else{
-                temp(row, col) = value;
-            }
-        }
-    }
-    return temp;
-}
-
-
-
-
-
diff --git a/Matrix.h b/Matrix.h
deleted file mode 100644
index 3e04666..0000000
--- a/Matrix.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef MATRIX_H
-#define MATRIX_H
-
-#include <stdexcept>
-#include <vector>
-#include <iostream>
-#include <time.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-using std::cout;
-using std::cin;
-using std::cerr;
-using std::endl;
-using std::vector;
-
-class Matrix {
-public:
-    Matrix(const unsigned int rows, const unsigned int cols);
-    Matrix(const Matrix& m);
-    ~Matrix();
-
-    double& operator() (const unsigned int row, const unsigned int col);
-    double  operator() (const unsigned int row, const unsigned int col) const;
-    void operator= (const Matrix& m);
-
-    std::vector<double> toVector() const;
-
-    unsigned int numRows() const;
-    unsigned int numCols() const;
-    void printData() const;
-
-    Matrix operator- () const;
-    Matrix operator+ (const Matrix& a) const;
-    Matrix operator- (const Matrix& a) const;
-    Matrix operator* (const int a) const;
-    Matrix operator* (const Matrix& a) const;
-
-    Matrix transpose() const;
-    void initialize(const int n);
-    void initRand(const double min, const double max,
-                  const unsigned int resolution=20);
-
-    Matrix addRowsCols(unsigned int extraRows, unsigned int extraCols,
-                       const double value);
-
-private:
-    unsigned int m_rows, m_cols;
-    double* m_data;
-};
-
-#endif
diff --git a/NeuralNet.cpp b/NeuralNet.cpp
index d86037e..e0865af 100644
--- a/NeuralNet.cpp
+++ b/NeuralNet.cpp
@@ -9,11 +9,12 @@ NeuralNet::NeuralNet(){
 //Constructor takes in the structure of the network as a matrix
 NeuralNet::NeuralNet(const vector<unsigned int>& layerSizes)
         : m_layerSizes(layerSizes){
+	unsigned int numLayers = layerSizes.size() - 1;
+	m_weights.reserve(numLayers);
+
     //Create vectors for weights. Each entry is a matrix for that layer
-    for(unsigned int i = 0; i < layerSizes.size() - 1; ++i){
-        Matrix tempWeight(layerSizes[i] + 1, layerSizes[i+1]);
-        tempWeight.initRand(-1, 1);
-        m_weights.push_back(tempWeight);
+    for(unsigned int i = 0; i < numLayers; ++i){
+        m_weights.push_back(MatrixXd::Random(layerSizes[i] + 1, layerSizes[i+1]));
     }
 }

@@ -32,7 +33,7 @@ void NeuralNet::printWeights() const{
     cout << "Current weights:" << endl;
     for(unsigned int i = 0; i < m_weights.size(); ++i){
         cout << "================================================" << endl;
-        m_weights[i].printData();
+        cout << m_weights[i] << endl;
     }
     cout << "================================================" << endl;
 }
@@ -54,13 +55,12 @@ bool NeuralNet::saveToFile(string fileName) const{
     outputFile << "\n";

     for(unsigned int lay = 0; lay < m_weights.size(); ++lay){
-        unsigned int numRows = m_weights[lay].numRows();
-        unsigned int numCols = m_weights[lay].numCols();
+        unsigned int rows = m_weights[lay].rows();
+        unsigned int cols = m_weights[lay].cols();

-        for(unsigned int i = 0; i < numRows; ++i){
-            for(unsigned int j = 0; j < numCols; ++j){
-                Matrix cur = m_weights[lay];
-                outputFile << cur(i, j) << " ";
+        for(unsigned int col = 0; col < cols; ++col){
+            for(unsigned int row = 0; row < rows; ++row){
+                outputFile << m_weights[lay](row, col) << " ";
             }
         }
     }
@@ -88,12 +88,14 @@ bool NeuralNet::loadFromFile(string fileName){
     }

     for(unsigned int lay = 0; lay < numLayers - 1; ++lay){
-        Matrix cur(m_layerSizes[lay] + 1, m_layerSizes[lay + 1]);
-        for(unsigned int i = 0; i < cur.numRows(); ++i){
-            for(unsigned int j = 0; j < cur.numCols(); ++j){
+        unsigned int rows = m_layerSizes[lay] + 1;
+        unsigned int cols = m_layerSizes[lay + 1];
+        MatrixXd cur(rows, cols);
+        for(unsigned int col = 0; col < cols; ++col){
+            for(unsigned int row = 0; row < rows; ++row){
                 double temp;
                 inputFile >> temp;
-                cur(i, j) = temp;
+                cur(row, col) = temp;
             }
         }
         m_weights.push_back(cur);
@@ -112,27 +114,31 @@ bool NeuralNet::loadFromFile(string fileName){
 }

 //Performs forward propagation using m_weights and 'input'
-Matrix NeuralNet::forward(const Matrix& input) const{
+RowVectorXd NeuralNet::forward(const RowVectorXd& input) const{
+	unsigned int numLayers = m_weights.size();
+
 	//Stores the previous layer's output
-    vector<Matrix> layers;
+    vector<RowVectorXd> layers;
+	layers.reserve(numLayers + 1);
     layers.push_back(input);

-    for(unsigned int lay = 0; lay < m_weights.size(); ++lay){
-        //Add extra col with 1.0 in it for bias
-        Matrix prev = (layers.back()).addRowsCols(0, 1, 1.0f);
+    for(unsigned int lay = 0; lay < numLayers; ++lay){
+        unsigned int numCols = layers[lay].size();
+        RowVectorXd prev(numCols + 1);
+        prev << layers[lay], 1.0;

     	//Cur = f(layers * weights + bias)...where f(x) is nonlinearity funtion
-        layers.push_back( applyNonlinearity(prev * m_weights[lay], sigmoid) );
+        layers.push_back(applyNonlinearity(prev * m_weights[lay], Activations::relu));
     }
-    return layers.back();
+    return layers[numLayers];
 }

-vector<Matrix> NeuralNet::getWeights() const{
+vector<MatrixXd> NeuralNet::getWeights() const{
     return m_weights;
 }

 //Sets the internal weights
-void NeuralNet::setWeights(const vector<Matrix>& weights){
+void NeuralNet::setWeights(const vector<MatrixXd>& weights){
     if (weights.size() == 0 || weights.size() != m_weights.size()){
     	cerr << "Error: setWeights(): Weights have different sizes." << endl;
         exit(1);
@@ -142,20 +148,14 @@ void NeuralNet::setWeights(const vector<Matrix>& weights){
     }
 }

-//Applies the nonlinearity function (sigmoid) elementwise
-Matrix NeuralNet::applyNonlinearity(const Matrix& input,
-                                    double(*callback)(double)) const{
-    Matrix temp(input);
-    for(unsigned int row = 0; row < input.numRows(); ++row){
-        for(unsigned int col = 0; col < input.numCols(); ++col){
-        	//Applies the callback to each element of input
-            temp(row, col) = callback(input(row, col));
-        }
-    }
-    return temp;
+RowVectorXd NeuralNet::applyNonlinearity(const RowVectorXd& input, Activations activation) const{
+	switch (activation){
+		case Activations::sigmoid: // 1 / (1 + e^-x)
+			return (((-1 * input.array()).exp() + 1).inverse()).matrix();
+		case Activations::relu: // max(0, x)
+			return ((input.array() > 0).cast<double>() * input.array()).matrix();
+		default:
+			return input;
+	}
 }

-//Sigmoid function. Returns a double between (0, 1)
-double NeuralNet::sigmoid(const double x){
-    return 1 / (1 + exp(-x));
-}
diff --git a/NeuralNet.h b/NeuralNet.h
index ff3f64a..362af2d 100644
--- a/NeuralNet.h
+++ b/NeuralNet.h
@@ -1,7 +1,9 @@
 #ifndef NN_H
 #define NN_H

-#include "Matrix.h"
+#include <Eigen/Dense>
+using namespace Eigen;
+
 #include <iostream>
 #include <fstream>
 #include <vector>
@@ -10,36 +12,43 @@

 using std::cout;
 using std::cin;
+using std::cerr;
 using std::endl;
 using std::vector;
 using std::ofstream;
 using std::ifstream;
 using std::string;

+enum Activations { sigmoid, relu };
+
 class NeuralNet {
+
+
 public:
     NeuralNet();
     NeuralNet(const vector<unsigned int>& layerSizes);
     NeuralNet(const NeuralNet& nn);

-    Matrix forward(const Matrix& input) const;
+    RowVectorXd forward(const RowVectorXd& input) const;

     void printWeights() const;

     void operator= (const NeuralNet& nn);

-    vector<Matrix> getWeights() const;
-    void setWeights(const vector<Matrix>& weights);
+    vector<MatrixXd> getWeights() const;
+    void setWeights(const vector<MatrixXd>& weights);

     bool saveToFile(string fileName) const;
     bool loadFromFile(string fileName);
 private:
     vector<unsigned int> m_layerSizes;
-    vector<Matrix> m_weights;
+    vector<MatrixXd> m_weights;

-    Matrix applyNonlinearity(const Matrix& input,
-                             double(*funct)(double)) const;
-    static double sigmoid(const double x);
+    /*RowVectorXd applyNonlinearity(const RowVectorXd& input,
+                             double(*funct)(double)) const;*/
+	RowVectorXd applyNonlinearity(const RowVectorXd& input, Activations activation) const;
+    //static double sigmoid(const double x);
+	//static double relu(const double x);
 };

 #endif
diff --git a/Player.cpp b/Player.cpp
index df231b7..27dfbad 100644
--- a/Player.cpp
+++ b/Player.cpp
@@ -24,8 +24,7 @@ void Player::operator= (const Player& right){
 }
 /*
 vector<double> Player::getMove() const{
-    Matrix temp(1, 9);
-    temp.initRand(-1, 1);
+    MatrixXd temp = MatrixXd::Random(1, 9);
     return temp.toVector();
 }*/

@@ -68,8 +67,8 @@ void NeuralPlayer::operator= (const NeuralPlayer& right){
     neural = right.neural;
 }

-vector<double> NeuralPlayer::getMove(const Matrix& input) const{
-    return neural.forward(input).toVector();
+RowVectorXd NeuralPlayer::getMove(const RowVectorXd& input) const{
+    return neural.forward(input);
 }

 //----------ManualPlayer--------------
@@ -98,7 +97,7 @@ void ManualPlayer::operator= (const ManualPlayer& right){
     Player::operator=(right);
 }

-vector<double> ManualPlayer::getMove(const Matrix& input) const{
+RowVectorXd ManualPlayer::getMove(const RowVectorXd& input) const{
     unsigned int row, col;
     char eater;
     m_os << "Your move, of the form \"row, col\": ";
@@ -106,10 +105,10 @@ vector<double> ManualPlayer::getMove(const Matrix& input) const{
     row --;
     col --;

-    Matrix temp(m_rows, m_cols);
-    temp.initialize(0);
-    temp(row, col) = 1;
-    return temp.toVector();
+    RowVectorXd temp(m_rows * m_cols);
+    temp << RowVectorXd::Constant(m_rows * m_cols, 0);
+    temp(row * m_cols + col) = 1.0;
+    return temp;
 }

 //----------PerfectPlayer--------------
diff --git a/Player.h b/Player.h
index f15f861..6449e6e 100644
--- a/Player.h
+++ b/Player.h
@@ -1,8 +1,10 @@
 #ifndef PLAYER_H
 #define PLAYER_H

+#include <Eigen/Dense>
+using namespace Eigen;
+
 #include <vector>
-#include "Matrix.h"
 #include "NeuralNet.h"

 using std::cout;
@@ -22,7 +24,7 @@ public:
     void operator= (const Player& right);
     bool operator< (const Player& right) const;

-    virtual vector<double> getMove(const Matrix& input) const = 0;
+    virtual RowVectorXd getMove(const RowVectorXd& input) const = 0;

     void addToFitness(const double a);
     double getFitness() const;
@@ -44,7 +46,7 @@ public:

     void operator= (const NeuralPlayer& right);

-    virtual vector<double> getMove(const Matrix& input) const override;
+    virtual RowVectorXd getMove(const RowVectorXd& input) const override;

     NeuralNet neural;
 private:
@@ -61,7 +63,7 @@ public:

     void operator= (const ManualPlayer& right);

-    virtual vector<double> getMove(const Matrix& input) const override;
+    virtual RowVectorXd getMove(const RowVectorXd& input) const override;

 private:
     istream& m_is;
@@ -79,7 +81,7 @@ public:

     void operator= (const PerfectPlayer& right);

-    virtual vector<double> getMove(const Matrix& input) const override;
+    virtual vector<double> getMove(const VectorXd& input) const override;

 private:
     double winningMove() const;
diff --git a/Population.h b/Population.h
index 0d7953c..2f006df 100644
--- a/Population.h
+++ b/Population.h
@@ -7,13 +7,16 @@
 #include <vector>
 #include <algorithm>
 #include <string>
+#include <ctime>
+
+#include <Eigen/Dense>
+using namespace Eigen;

-#include "Matrix.h"
 #include "NeuralNet.h"
 #include "Player.h"
 #include "TicTacToe.h"
 #include "Genetic.h"
-#include "UltimateTTT.h"
+//#include "UltimateTTT.h"

 using std::cout;
 using std::cin;
@@ -29,7 +32,7 @@ public:
     Population<Game>();

     void init(unsigned int seed = 1, istream& is = cin, ostream& os = cout);
-    void train(bool verbose);
+    time_t train(bool verbose);
     string saveBest(string path);
     void loadBest(string path, string name = "");

@@ -140,7 +143,8 @@ string Population<Game>::saveBest(string path){

 template <template <class, class> class Game>
-void Population<Game>::train(bool verbose){
+time_t Population<Game>::train(bool verbose){
+    time_t startTime = time(NULL);
     for(int generation = 0; generation < m_iterations; ++generation){
         //Play games with every permutaiton of players
         roundRobin();
@@ -149,7 +153,7 @@ void Population<Game>::train(bool verbose){
         sort(m_population.begin(), m_population.end(),
             comparePlayerContainer<NeuralPlayer>);

-        m_hallOfFame.push_back(m_population.back());
+        m_hallOfFame.push_back(m_population[m_populationSize - 1]);

         //Print board
         if(verbose){
@@ -179,6 +183,7 @@ void Population<Game>::train(bool verbose){
             m_population[i].player.resetFitness();
         }
     }
+    return time(NULL) - startTime;
 }

@@ -241,6 +246,7 @@ void Population<Game>::init(unsigned int seed, istream& is, ostream& os){
     }

     m_ga.setPopulationSize(m_populationSize);
+	m_hallOfFame.reserve(m_iterations);
 }

 template <template <class, class> class Game>
diff --git a/README.md b/README.md
index 1fbf255..f4e88d8 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# TicTacToeMachineLearning
-The goal of this project is to train the computer to play tic tac toe at a superhuman level. This is a rather trivial problem, but I'm simply using it as a chance to learn more about machine learning. My approach is overkill, but this is just a fun project.
-
-I'm using a neural network trained by a genetic algorithm to learn tic tac toe. I start with a random population of players. Each generation they play every other player once. Fitness points are awarded for their record: 0 points for each loss, 0.5 for each tie, and 1 point for each win. I then evolve the the players based on normal genetic algorithm techniques (mutation, breeding, crossover, etc.). The goal is to maximize the player's fitness.
+# TicTacToeMachineLearning
+The goal of this project is to train the computer to play tic tac toe at a superhuman level. This is a rather trivial problem, but I'm simply using it as a chance to learn more about machine learning. My approach is overkill, but this is just a fun project.
+
+I'm using a neural network trained by a genetic algorithm to learn tic tac toe. I start with a random population of players. Each generation they play every other player once. Fitness points are awarded for their record: 0 points for each loss, 0.5 for each tie, and 1 point for each win. I then evolve the the players based on normal genetic algorithm techniques (mutation, breeding, crossover, etc.). The goal is to maximize the player's fitness.
diff --git a/TicTacToe.h b/TicTacToe.h
index f7d97eb..530bb82 100644
--- a/TicTacToe.h
+++ b/TicTacToe.h
@@ -1,7 +1,9 @@
 #ifndef TTT_H
 #define TTT_H

-#include "Matrix.h"
+#include <Eigen/Dense>
+using namespace Eigen;
+
 #include "NeuralNet.h"
 #include "Player.h"

@@ -12,6 +14,7 @@

 using std::cout;
 using std::cin;
+using std::cerr;
 using std::endl;
 using std::vector;
 using std::pair;
@@ -35,13 +38,13 @@ private:
     bool isEmpty() const;
     bool isFull() const;

-    Matrix toMatrix() const;
-    Matrix toPlayerPerspective(const States state) const;
+    RowVectorXd toMatrix() const;
+    RowVectorXd toPlayerPerspective(const States state) const;

     States getBoardAtPosition(const int position) const;
     void setBoardAtPosition(const int position, const States state);

-    vector<unsigned int> bestMoves(const vector<double>& input) const;
+    RowVectorXi bestMoves(const RowVectorXd& input) const;
     void printBoard() const;
     bool hasWon() const;

@@ -104,28 +107,24 @@ bool TicTacToe<T1, T2>::isFull() const{

 //Returns a vector of the preferred moves starting with most preferred
 template <class T1, class T2>
-vector<unsigned int> TicTacToe<T1, T2>::bestMoves(
-        const vector<double>& input) const{
-    vector<unsigned int> temp;
+RowVectorXi TicTacToe<T1, T2>::bestMoves(const RowVectorXd& input) const{
+    Matrix<int, 1, 9> ret;
     vector< pair<double, unsigned int> > inputPair;
-
-    temp.resize(NUM_OUTPUTS, -1);
+	inputPair.reserve(9);

     //Populate inputPair
     for(unsigned int i = 0; i < NUM_OUTPUTS; ++i){
-        inputPair.push_back(make_pair(input[i], i));
+        inputPair.push_back(make_pair(input(i), i));
     }

     sort(inputPair.begin(), inputPair.end());

-    //Populate temp
+    //Populate ret
     for(unsigned int i = 0; i < NUM_OUTPUTS; ++i){
-        temp[i] = inputPair[i].second;
+        ret(8 - i) = inputPair[i].second;
     }

-    //Reverse temp
-    reverse(temp.begin(), temp.end());
-    return temp;
+    return ret;
 }

 //Prints the current board to the console
@@ -154,13 +153,11 @@ void TicTacToe<T1, T2>::printBoard() const{
  * representation so it can be passed into other methods.
  */
 template <class T1, class T2>
-Matrix TicTacToe<T1, T2>::toMatrix() const{
-    Matrix temp(1, NUM_OUTPUTS);
+RowVectorXd TicTacToe<T1, T2>::toMatrix() const{
+    RowVectorXd temp(NUM_OUTPUTS);

-    for(int i = 0; i < 3; ++i){
-        for(int j = 0; j < 3; ++j){
-            temp(0, 3 * i + j) = (float)getBoardAtPosition(3 * i + j);
-        }
+    for(int i = 0; i < 9; ++i){
+        temp(i) = (double)getBoardAtPosition(i);
     }
     return temp;
 }
@@ -172,19 +169,17 @@ Matrix TicTacToe<T1, T2>::toMatrix() const{
     - empty squares        =  0
  */
 template <class T1, class T2>
-Matrix TicTacToe<T1, T2>::toPlayerPerspective(const States state) const{
-    Matrix temp(toMatrix());
+RowVectorXd TicTacToe<T1, T2>::toPlayerPerspective(const States state) const{
+    RowVectorXd temp = toMatrix();

-    for(unsigned int i = 0; i < temp.numRows(); ++i){
-        for(unsigned int j = 0; j < temp.numCols(); ++j){
-            States cur = static_cast<States>(temp(i, j));
-            if(cur == States::empty){
-                temp(i, j) = 0.0;
-            } else if(cur == state){
-                temp(i, j) = 1.0;
-            } else{
-                temp(i, j) = -1.0;
-            }
+    for(unsigned int i = 0; i < 9; ++i){
+        States cur = static_cast<States>((int)temp(i));
+        if(cur == States::empty){
+            temp(i) = 0.0;
+        } else if(cur == state){
+            temp(i) = 1.0;
+        } else{
+            temp(i) = -1.0;
         }
     }
     return temp;
@@ -258,7 +253,7 @@ bool TicTacToe<T1, T2>::hasWon() const{
 template <class T1, class T2>
 bool TicTacToe<T1, T2>::takeTurn(const States state, const int turn){
     //holds the list of desired moves in order of preference
-    vector<unsigned int> moves;
+    RowVectorXi moves;

     //Diagnostics
     if(m_verbose){
@@ -266,7 +261,7 @@ bool TicTacToe<T1, T2>::takeTurn(const States state, const int turn){
     }

     //player 1 controls 'X' squares, player 2 controls 'O' squares
-    Matrix playerPerspective = toPlayerPerspective(state);
+    RowVectorXd playerPerspective = toPlayerPerspective(state);
     if(state == States::playerX){
         moves = bestMoves(m_player1.player.getMove(playerPerspective));
     } else{
@@ -275,8 +270,8 @@ bool TicTacToe<T1, T2>::takeTurn(const States state, const int turn){

     //Make the best move from available squares
     for(int i = 0; i < NUM_OUTPUTS; ++i){
-        if(getBoardAtPosition(moves[i]) == States::empty){
-            setBoardAtPosition(moves[i], state);
+        if(getBoardAtPosition(moves(i)) == States::empty){
+            setBoardAtPosition(moves(i), state);
             break;
         }
     }
diff --git a/TicTacToeMachineLearning.sln b/TicTacToeMachineLearning.sln
new file mode 100644
index 0000000..61f2553
--- /dev/null
+++ b/TicTacToeMachineLearning.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2035
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TicTacToeMachineLearning", "TicTacToeMachineLearning.vcxproj", "{AE943583-6E21-47EC-BFC2-F37CA248C5A9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Debug|x64.ActiveCfg = Debug|x64
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Debug|x64.Build.0 = Debug|x64
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Debug|x86.ActiveCfg = Debug|Win32
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Debug|x86.Build.0 = Debug|Win32
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Release|x64.ActiveCfg = Release|x64
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Release|x64.Build.0 = Release|x64
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Release|x86.ActiveCfg = Release|Win32
+		{AE943583-6E21-47EC-BFC2-F37CA248C5A9}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {7CBB95EE-B334-49D0-B4E3-EB36EAE13774}
+	EndGlobalSection
+EndGlobal
diff --git a/TicTacToeMachineLearning.vcxproj b/TicTacToeMachineLearning.vcxproj
new file mode 100644
index 0000000..5e818ca
--- /dev/null
+++ b/TicTacToeMachineLearning.vcxproj
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{AE943583-6E21-47EC-BFC2-F37CA248C5A9}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>D:/MinGW/include/eigen-eigen-5a0156e40feb/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>D:/MinGW/include/eigen-eigen-5a0156e40feb/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="Genetic.cpp" />
+    <ClCompile Include="main.cpp" />
+    <ClCompile Include="Matrix.cpp" />
+    <ClCompile Include="NeuralNet.cpp" />
+    <ClCompile Include="Player.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Genetic.h" />
+    <ClInclude Include="main.h" />
+    <ClInclude Include="Matrix.h" />
+    <ClInclude Include="NeuralNet.h" />
+    <ClInclude Include="Player.h" />
+    <ClInclude Include="Population.h" />
+    <ClInclude Include="TicTacToe.h" />
+    <ClInclude Include="UltimateTTT.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/TicTacToeMachineLearning.vcxproj.filters b/TicTacToeMachineLearning.vcxproj.filters
new file mode 100644
index 0000000..4feca21
--- /dev/null
+++ b/TicTacToeMachineLearning.vcxproj.filters
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Genetic.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Matrix.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="NeuralNet.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Player.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Genetic.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="main.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Matrix.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="NeuralNet.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Player.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Population.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="TicTacToe.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="UltimateTTT.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Todo.txt b/Todo.txt
index 3ec2b32..b39e9ec 100644
--- a/Todo.txt
+++ b/Todo.txt
@@ -1,7 +1,8 @@
 TODO List

 - Code formatting
-- Improve Matrix class functionality/cleanliness
+- XXXXXXXXXXXXX Improve Matrix class functionality/cleanliness XXXXXXXXXXXXX
+- Use Eigen matrix library
 - Ultimate Tic Tac Toe
 - Random Player (chooses moves randomly)
 - Timekeeping (execution time)
diff --git a/Training Times.xlsx b/Training Times.xlsx
new file mode 100644
index 0000000..fe8cf0b
Binary files /dev/null and b/Training Times.xlsx differ
diff --git a/UltimateTTT.h b/UltimateTTT.h
index 5f47f14..45cb8fa 100644
--- a/UltimateTTT.h
+++ b/UltimateTTT.h
@@ -133,10 +133,11 @@ bool UltimateTTT<T1, T2>::subBoardTied(const int subBoard) const{
 template <class T1, class T2>
 vector<unsigned int> UltimateTTT<T1, T2>::bestMoves(
         const vector<double>& input) const{
-    vector<unsigned int> temp;
-    temp.resize(NUM_OUTPUTS, -1);
-
-    vector< pair<double, unsigned int> > inputPair;
+
+    vector<unsigned int> ret;
+	vector< pair<double, unsigned int> > inputPair;
+    ret.reserve(NUM_OUTPUTS);
+    inputPair.reserve(NUM_OUTPUTS);

     //Populate inputPair
     for(unsigned int i = 0; i < NUM_OUTPUTS; ++i){
@@ -147,12 +148,12 @@ vector<unsigned int> UltimateTTT<T1, T2>::bestMoves(

     //Populate temp
     for(unsigned int i = 0; i < NUM_OUTPUTS; ++i){
-        temp[i] = inputPair[i].second;
+        ret.push_back(inputPair[i].second);
     }

     //Reverse temp
-    reverse(temp.begin(), temp.end());
-    return temp;
+    reverse(ret.begin(), ret.end());
+    return ret;
 }

 //Prints the current board to the console
diff --git a/main.cpp b/main.cpp
index 81926da..4b1da79 100644
--- a/main.cpp
+++ b/main.cpp
@@ -2,16 +2,17 @@

 #include "main.h"
 #include "Population.h"
+#include <Eigen/Dense>

 int main(){
-    srand(time(NULL));
-
+    srand((unsigned int)time(NULL));
+
     //Where your player log files are stored
     string path = "data/";
     Population<TicTacToe> pop;

-
+    /*
     ManualPlayer tempHuman1(cin, cout, 10, 9);
     playerContainer<ManualPlayer> human1(tempHuman1);

@@ -26,7 +27,7 @@ int main(){

     UltimateTTT<NeuralPlayer, NeuralPlayer> ttt(machine1, machine2, true);
     ttt.playGame();
-
+    */

     char loadPlayer;
     cout << "Do you want to load a trained player? (y/n): ";
@@ -36,8 +37,10 @@ int main(){
     if(loadPlayer == 'y' || loadPlayer == 'Y'){
         pop.loadBest(path);
     } else{
-        pop.init(time(NULL));
-        pop.train(false);
+        pop.init((unsigned int)time(NULL));
+        time_t trainingTime = pop.train(false);
+
+        cout << "Time to train: " << trainingTime << endl;

         char savePlayer;
         cout << "Do you want to save the best player to a file? (y/n): ";
diff --git a/makefile b/makefile
index 8167680..9100c15 100644
--- a/makefile
+++ b/makefile
@@ -5,21 +5,22 @@ Warnings = -Wall -Wextra -Wdouble-promotion -Wswitch-default -Wfloat-equal \
 Sanitize = -fsanitize=address -fsanitize=undefined
 TestingFlags = -Og -g
 ReleaseFlags = -O3
-Targets = main.cpp Matrix.cpp NeuralNet.cpp Player.cpp Genetic.cpp
+Targets = main.cpp NeuralNet.cpp Player.cpp Genetic.cpp
+Include = -isystem d:/MinGW/include/eigen-eigen-5a0156e40feb/

 all: $(Targets)
 	$(RM) a
-	g++ $(CompilerFlags) $(Warnings) $(TestingFlags) $(Targets)
+	g++ $(CompilerFlags) $(Warnings) $(TestingFlags) $(Targets) $(Include)

 run: $(Targets)
 	$(RM) a
-	g++ $(CompilerFlags) $(Warnings) $(TestingFlags) $(Targets)
+	g++ $(CompilerFlags) $(Warnings) $(TestingFlags) $(Targets) $(Include)
 	./a.exe

 fast: $(Targets)
 	$(RM) a
-	g++ $(CompilerFlags) $(Warnings) $(ReleaseFlags) $(Targets)
+	g++ $(CompilerFlags) $(Warnings) $(ReleaseFlags) $(Targets) $(Include)

 clean:
 	$(RM) a

AlainGIGNAC referenced this pull request in AlainGIGNAC/figure.visualstudio.com Jul 16, 2018

GeneralD added a commit to GeneralD/HanoiTower that referenced this pull request Aug 13, 2018

[from now] 2018/08/14 00:35:59
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e1a0dbd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,457 @@
+### https://raw.github.com/github/gitignore/300be202df4d2bc4824249407fb617df64750627/Global/macOS.gitignore
+
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+
+### https://raw.github.com/github/gitignore/300be202df4d2bc4824249407fb617df64750627/Global/Windows.gitignore
+
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+
+### https://raw.github.com/github/gitignore/300be202df4d2bc4824249407fb617df64750627/VisualStudio.gitignore
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (github/gitignore#2483 (comment))
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (github/gitignore#1529 (comment))
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+
+### https://raw.github.com/github/gitignore/300be202df4d2bc4824249407fb617df64750627/Global/JetBrains.gitignore
+
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+
diff --git a/HanoiTower.sln b/HanoiTower.sln
new file mode 100644
index 0000000..d7a8d52
--- /dev/null
+++ b/HanoiTower.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HanoiTower", "HanoiTower\HanoiTower.csproj", "{EF983A81-088F-4943-8ED2-539E8FD9F136}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{EF983A81-088F-4943-8ED2-539E8FD9F136}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EF983A81-088F-4943-8ED2-539E8FD9F136}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EF983A81-088F-4943-8ED2-539E8FD9F136}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EF983A81-088F-4943-8ED2-539E8FD9F136}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git a/HanoiTower/HanoiTower.csproj b/HanoiTower/HanoiTower.csproj
new file mode 100644
index 0000000..5bfde6c
--- /dev/null
+++ b/HanoiTower/HanoiTower.csproj
@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Remove="EmptyClass.cs" />
+    <Compile Remove="MomorisedRecursableFuncExtensions.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="csharp-monad" Version="1.0.1" />
+    <PackageReference Include="AsyncEnumerator" Version="2.2.1" />
+  </ItemGroup>
+</Project>
diff --git a/HanoiTower/PartialApplying.cs b/HanoiTower/PartialApplying.cs
new file mode 100644
index 0000000..527e264
--- /dev/null
+++ b/HanoiTower/PartialApplying.cs
@@ -0,0 +1,31 @@
+using System;
+namespace Functional {
+
+	public delegate TResult PartialApply<T, TResult>(T arg);
+
+	public static class PartialApplyFuncExtensions {
+		public static PartialApply<T_, TResult> _<T_, TResult>(this Func<T_, TResult> func) => new PartialApply<T_, TResult>(func);
+		public static PartialApply<T_, TResult> _<T_, TResult>(this Func<T_, PartialApply<T_, TResult>> func) => _ => func(_)(_);
+		public static Func<T1, PartialApply<T_, TResult>> _<T_, T1, TResult>(this Func<T_, Func<T1, TResult>> func) => v1 => _ => func(_)(v1);
+		public static Func<T1, PartialApply<T_, TResult>> _<T_, T1, TResult>(this Func<T_, Func<T1, PartialApply<T_, TResult>>> func) => v1 => _ => func(_)(v1)(_);
+		public static Func<T1, Func<T2, PartialApply<T_, TResult>>> _<T_, T1, T2, TResult>(this Func<T_, Func<T1, Func<T2, TResult>>> func) => v1 => v2 => _ => func(_)(v1)(v2);
+		public static Func<T1, Func<T2, PartialApply<T_, TResult>>> _<T_, T1, T2, TResult>(this Func<T_, Func<T1, Func<T2, PartialApply<T_, TResult>>>> func) => v1 => v2 => _ => func(_)(v1)(v2)(_);
+		public static Func<T1, Func<T2, Func<T3, PartialApply<T_, TResult>>>> _<T_, T1, T2, T3, TResult>(this Func<T_, Func<T1, Func<T2, Func<T3, TResult>>>> func) => v1 => v2 => v3 => _ => func(_)(v1)(v2)(v3);
+		public static Func<T, TResult> ToFunc<T, TResult>(PartialApply<T, TResult> func) => v => func(v);
+	}
+
+	public static class CurryFuncExtensions {
+		public static Func<T1, TResult> Curry<T1, TResult>(this Func<T1, TResult> func) => v1 => func(v1);
+		public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func) => v1 => v2 => func(v1, v2);
+		public static Func<T1, Func<T2, Func<T3, TResult>>> Curry<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func) => v1 => v2 => v3 => func(v1, v2, v3);
+		public static Func<T1, Func<T2, Func<T3, Func<T4, TResult>>>> Curry<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> func) => v1 => v2 => v3 => v4 => func(v1, v2, v3, v4);
+	}
+
+	public static class CurryActionExtensions {
+		public static Action<T1> Curry<T1>(this Action<T1> func) => v1 => func(v1);
+		public static Func<T1, Action<T2>> Curry<T1, T2>(this Action<T1, T2> func) => v1 => v2 => func(v1, v2);
+		public static Func<T1, Func<T2, Action<T3>>> Curry<T1, T2, T3>(this Action<T1, T2, T3> func) => v1 => v2 => v3 => func(v1, v2, v3);
+		public static Func<T1, Func<T2, Func<T3, Action<T4>>>> Curry<T1, T2, T3, T4>(this Action<T1, T2, T3, T4> func) => v1 => v2 => v3 => v4 => func(v1, v2, v3, v4);
+	}
+
+}
diff --git a/HanoiTower/Program.cs b/HanoiTower/Program.cs
new file mode 100644
index 0000000..8413db9
--- /dev/null
+++ b/HanoiTower/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Async;
+using System.Threading;
+using Functional;
+
+namespace HanoiTower {
+    class Program {
+        static void Main(string[] args) {
+            var hanoi = RecursableFuncExtensions.RecurseMemorised<int, int, int, int, AsyncEnumerable<string>>
+            ((next, src, bare, dst, height) => new AsyncEnumerable<string>(async yield => {
+                if (height > 1) foreach (var r in next(src, dst, bare, height - 1).ToEnumerable()) await yield.ReturnAsync(r);
+                await yield.ReturnAsync($"object: {height}, tower: {src}->{dst}");
+                if (height > 1) foreach (var r in next(bare, src, dst, height - 1).ToEnumerable()) await yield.ReturnAsync(r);
+            }).Curry()(1)(2)(3);
+
+            int h;
+            if (args.Length == 0 || !int.TryParse(args[0], out h)) h = 3;
+            hanoi(h).ForEachAsync(s => Console.WriteLine(s));
+        }
+    }
+}
\ No newline at end of file
diff --git a/HanoiTower/RecursableFuncExtensions.cs b/HanoiTower/RecursableFuncExtensions.cs
new file mode 100644
index 0000000..86fc04c
--- /dev/null
+++ b/HanoiTower/RecursableFuncExtensions.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+
+namespace Functional {
+
+	public static class RecursableFuncExtensions {
+
+		public static Func<T1, TResult> Recurse<T1, TResult>(this Func<Func<T1, TResult>, T1, TResult> f) {
+			Func<T1, TResult> next = null;
+			return next = p1 => f(next, p1);
+		}
+
+		public static Func<T1, T2, TResult> Recurse<T1, T2, TResult>(this Func<Func<T1, T2, TResult>, T1, T2, TResult> f) {
+			Func<T1, T2, TResult> next = null;
+			return next = (p1, p2) => f(next, p1, p2);
+		}
+
+		public static Func<T1, T2, T3, TResult> Recurse<T1, T2, T3, TResult>(this Func<Func<T1, T2, T3, TResult>, T1, T2, T3, TResult> f) {
+			Func<T1, T2, T3, TResult> next = null;
+			return next = (p1, p2, p3) => f(next, p1, p2, p3);
+		}
+
+		public static Func<T1, T2, T3, T4, TResult> Recurse<T1, T2, T3, T4, TResult>(this Func<Func<T1, T2, T3, T4, TResult>, T1, T2, T3, T4, TResult> f) {
+			Func<T1, T2, T3, T4, TResult> next = null;
+			return next = (p1, p2, p3, p4) => f(next, p1, p2, p3, p4);
+		}
+
+		public static Func<T1, T2, T3, T4, T5, TResult> Recurse<T1, T2, T3, T4, T5, TResult>(this Func<Func<T1, T2, T3, T4, T5, TResult>, T1, T2, T3, T4, T5, TResult> f) {
+			Func<T1, T2, T3, T4, T5, TResult> next = null;
+			return next = (p1, p2, p3, p4, p5) => f(next, p1, p2, p3, p4, p5);
+		}
+
+		public static Func<T1, T2, T3, T4, T5, T6, TResult> Recurse<T1, T2, T3, T4, T5, T6, TResult>(this Func<Func<T1, T2, T3, T4, T5, T6, TResult>, T1, T2, T3, T4, T5, T6, TResult> f) {
+			Func<T1, T2, T3, T4, T5, T6, TResult> next = null;
+			return next = (p1, p2, p3, p4, p5, p6) => f(next, p1, p2, p3, p4, p5, p6);
+		}
+
+		public static Func<T1, TResult> RecurseMemorised<T1, TResult>(this Func<Func<T1, TResult>, T1, TResult> f) {
+			Dictionary<T1, TResult> memory = new Dictionary<T1, TResult>();
+			Func<T1, TResult> next = null;
+			return next = p1 => memory.ContainsKey(p1) ? memory[p1] : memory[p1] = f(next, p1);
+		}
+
+		public static Func<T1, T2, TResult> RecurseMemorised<T1, T2, TResult>(this Func<Func<T1, T2, TResult>, T1, T2, TResult> f) {
+			Dictionary<object, TResult> memory = new Dictionary<object, TResult>();
+			Func<T1, T2, TResult> next = null;
+			return next = (p1, p2) => memory.ContainsKey(new { p1, p2 }) ? memory[new { p1, p2 }] : memory[new { p1, p2 }] = f(next, p1, p2);
+		}
+
+		public static Func<T1, T2, T3, TResult> RecurseMemorised<T1, T2, T3, TResult>(this Func<Func<T1, T2, T3, TResult>, T1, T2, T3, TResult> f) {
+			Dictionary<object, TResult> memory = new Dictionary<object, TResult>();
+			Func<T1, T2, T3, TResult> next = null;
+			return next = (p1, p2, p3) => memory.ContainsKey(new { p1, p2, p3 }) ? memory[new { p1, p2, p3 }] : memory[new { p1, p2, p3 }] = f(next, p1, p2, p3);
+		}
+
+		public static Func<T1, T2, T3, T4, TResult> RecurseMemorised<T1, T2, T3, T4, TResult>(this Func<Func<T1, T2, T3, T4, TResult>, T1, T2, T3, T4, TResult> f) {
+			Dictionary<object, TResult> memory = new Dictionary<object, TResult>();
+			Func<T1, T2, T3, T4, TResult> next = null;
+			return next = (p1, p2, p3, p4) => memory.ContainsKey(new { p1, p2, p3, p4 }) ? memory[new { p1, p2, p3, p4 }] : memory[new { p1, p2, p3, p4 }] = f(next, p1, p2, p3, p4);
+		}
+
+		public static Func<T1, T2, T3, T4, T5, TResult> RecurseMemorised<T1, T2, T3, T4, T5, TResult>(this Func<Func<T1, T2, T3, T4, T5, TResult>, T1, T2, T3, T4, T5, TResult> f) {
+			Dictionary<object, TResult> memory = new Dictionary<object, TResult>();
+			Func<T1, T2, T3, T4, T5, TResult> next = null;
+			return next = (p1, p2, p3, p4, p5) => memory.ContainsKey(new { p1, p2, p3, p4, p5 }) ? memory[new { p1, p2, p3, p4, p5 }] : memory[new { p1, p2, p3, p4, p5 }] = f(next, p1, p2, p3, p4, p5);
+		}
+
+		public static Func<T1, T2, T3, T4, T5, T6, TResult> RecurseMemorised<T1, T2, T3, T4, T5, T6, TResult>(this Func<Func<T1, T2, T3, T4, T5, T6, TResult>, T1, T2, T3, T4, T5, T6, TResult> f) {
+			Dictionary<object, TResult> memory = new Dictionary<object, TResult>();
+			Func<T1, T2, T3, T4, T5, T6, TResult> next = null;
+			return next = (p1, p2, p3, p4, p5, p6) => memory.ContainsKey(new { p1, p2, p3, p4, p5, p6 }) ? memory[new { p1, p2, p3, p4, p5, p6 }] : memory[new { p1, p2, p3, p4, p5, p6 }] = f(next, p1, p2, p3, p4, p5, p6);
+		}
+	}
+}

mxrider331 referenced this pull request in mxrider331/McKenna-McIntosh- Dec 23, 2018

Jlteka added a commit to Jlteka/Constellation that referenced this pull request Mar 22, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git "a/\320\241onstellation.sln" "b/\320\241onstellation.sln"
new file mode 100644
index 0000000..626e658
--- /dev/null
+++ "b/\320\241onstellation.sln"
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Сonstellation", "Сonstellation\Сonstellation.csproj", "{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git "a/\320\241onstellation/Controllers/HomeController.cs" "b/\320\241onstellation/Controllers/HomeController.cs"
new file mode 100644
index 0000000..c196899
--- /dev/null
+++ "b/\320\241onstellation/Controllers/HomeController.cs"
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Constellation.Models;
+
+namespace Constellation.Controllers
+{
+    public class HomeController : Controller
+    {
+        public IActionResult Index()
+        {
+            return View();
+        }
+
+        public IActionResult Privacy()
+        {
+            return View();
+        }
+
+        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+        public IActionResult Error()
+        {
+            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
+        }
+    }
+}
diff --git "a/\320\241onstellation/Controllers/TourController.cs" "b/\320\241onstellation/Controllers/TourController.cs"
new file mode 100644
index 0000000..3d8f463
--- /dev/null
+++ "b/\320\241onstellation/Controllers/TourController.cs"
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.AspNetCore.Mvc;
+using Constellation.Services;
+using Constellation.Models;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace Constellation.Controllers
+{
+    public class TourController : ControllerBase
+    {
+        private readonly ITourRepository _tourRepo;
+
+        public TourController(ITourRepository tourRepo)
+        {
+            _tourRepo = tourRepo;
+        }
+
+        [HttpGet]
+        [Route("tourid/{id}")]
+        public async Task<ActionResult<Tour>> GetById(int id)
+        {
+            return await _tourRepo.GetById(id);
+        }
+
+        [HttpGet]
+        [Route("tourlist")]
+        public async Task<ActionResult<List<Tour>>> GetTourList()
+        {
+            return await _tourRepo.GetTourList();
+        }
+    }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Models/ErrorViewModel.cs" "b/\320\241onstellation/Models/ErrorViewModel.cs"
new file mode 100644
index 0000000..6204c00
--- /dev/null
+++ "b/\320\241onstellation/Models/ErrorViewModel.cs"
@@ -0,0 +1,11 @@
+using System;
+
+namespace Constellation.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Models/PhotoCard.cs" "b/\320\241onstellation/Models/PhotoCard.cs"
new file mode 100644
index 0000000..042b991
--- /dev/null
+++ "b/\320\241onstellation/Models/PhotoCard.cs"
@@ -0,0 +1,9 @@
+using System;
+namespace Constellation.Models
+{
+    public class PhotoCard
+    {
+        public string Photo { get; set; }
+        public string Thumbnail { get; set; }
+    }
+}
diff --git "a/\320\241onstellation/Models/Tour.cs" "b/\320\241onstellation/Models/Tour.cs"
new file mode 100644
index 0000000..0c07f44
--- /dev/null
+++ "b/\320\241onstellation/Models/Tour.cs"
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace Constellation.Models
+{
+    public class Tour
+    {
+        public int Id { get; set; }
+        public string Title { get; set; }
+        public string Header { get; set; }
+        public string Description { get; set; }
+        public string Route { get; set; }
+        public DateTimeOffset PeriodStart { get; set; }
+        public DateTimeOffset PeriodEnd { get; set; }
+        public float MinPrice { get; set; }
+        public PhotoCard PhotoCard { get; set; }
+        public List<PhotoCard> PhotoAlbum { get; set; }
+
+    }
+}
diff --git "a/\320\241onstellation/Models/TourDTO.cs" "b/\320\241onstellation/Models/TourDTO.cs"
new file mode 100644
index 0000000..f632d8b
--- /dev/null
+++ "b/\320\241onstellation/Models/TourDTO.cs"
@@ -0,0 +1,17 @@
+using System;
+namespace Constellation.Models
+{
+    public class TourDTO
+    {
+        public int Id { get; set; }
+        public string Title { get; set; }
+        public string Header { get; set; }
+        public string Description { get; set; }
+        public string Route { get; set; }
+        public DateTimeOffset PeriodStart { get; set; }
+        public DateTimeOffset PeriodEnd { get; set; }
+        public float MinPrice { get; set; }
+        public string Photo { get; set; }
+        public string Thumbnail { get; set; }
+    }
+}
diff --git "a/\320\241onstellation/Program.cs" "b/\320\241onstellation/Program.cs"
new file mode 100644
index 0000000..850dceb
--- /dev/null
+++ "b/\320\241onstellation/Program.cs"
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace Constellation
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateWebHostBuilder(args).Build().Run();
+        }
+
+        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
+                .UseStartup<Startup>();
+    }
+}
diff --git "a/\320\241onstellation/Properties/launchSettings.json" "b/\320\241onstellation/Properties/launchSettings.json"
new file mode 100644
index 0000000..570c805
--- /dev/null
+++ "b/\320\241onstellation/Properties/launchSettings.json"
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:19708",
+      "sslPort": 44328
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "Constellation": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Services/ITourRepository.cs" "b/\320\241onstellation/Services/ITourRepository.cs"
new file mode 100644
index 0000000..a8421ff
--- /dev/null
+++ "b/\320\241onstellation/Services/ITourRepository.cs"
@@ -0,0 +1,13 @@
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using Constellation.Models;
+
+namespace Constellation.Services
+{
+    public interface ITourRepository
+    {
+        Task<Tour> GetById(int id);
+        Task<List<Tour>> GetTourList();
+    }
+}
diff --git "a/\320\241onstellation/Services/TourRepository.cs" "b/\320\241onstellation/Services/TourRepository.cs"
new file mode 100644
index 0000000..9cefdce
--- /dev/null
+++ "b/\320\241onstellation/Services/TourRepository.cs"
@@ -0,0 +1,123 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using System.Collections.Generic;
+using Constellation.Models;
+using Microsoft.Extensions.Configuration;
+using Dapper;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+
+namespace Constellation.Services
+{
+    public class TourRepository : ITourRepository
+    {
+        private readonly IConfiguration _config;
+
+        public TourRepository(IConfiguration config)
+        {
+            _config = config;
+        }
+
+        public IDbConnection Connection => new SqlConnection(_config.GetConnectionString("MyConnectionString"));
+
+        public async Task<Tour> GetById(int id)
+        {
+            using (IDbConnection conn = Connection)
+            {
+                var sbTourDTO = new StringBuilder();
+                sbTourDTO.AppendLine("SELECT");
+                sbTourDTO.AppendLine("id");
+                sbTourDTO.AppendLine(", title");
+                sbTourDTO.AppendLine(", header");
+                sbTourDTO.AppendLine(", [description]");
+                sbTourDTO.AppendLine(", [route]");
+                sbTourDTO.AppendLine(", periodStart");
+                sbTourDTO.AppendLine(", periodEnd");
+                sbTourDTO.AppendLine(", minPrice");
+                sbTourDTO.AppendLine(", Photo");
+                sbTourDTO.AppendLine(", Thumbnail");
+                sbTourDTO.AppendLine("FROM tour");
+                sbTourDTO.AppendLine("WHERE id = @ID");
+
+                conn.Open();
+                var tourDTO = await conn.QueryFirstOrDefaultAsync<TourDTO>(sbTourDTO.ToString(), new { ID = id });
+                var photoCards = await conn.QueryAsync<PhotoCard>("SELECT photo, thumbnail FROM[photoCard] WHERE tourId = @ID", new { ID = id });
+
+                return new Tour
+                {
+                    Id = tourDTO.Id,
+                    Title = tourDTO.Title,
+                    Header = tourDTO.Header,
+                    Description = tourDTO.Description,
+                    Route = tourDTO.Route,
+                    PeriodStart = tourDTO.PeriodStart,
+                    PeriodEnd = tourDTO.PeriodEnd,
+                    MinPrice = tourDTO.MinPrice,
+
+                    PhotoCard = new PhotoCard()
+                    {
+                        Photo = tourDTO.Photo,
+                        Thumbnail = tourDTO.Thumbnail
+                    },
+
+                    PhotoAlbum = photoCards.ToList()
+                };
+            }
+        }
+
+
+        public async Task<List<Tour>> GetTourList()
+        {
+            using (IDbConnection conn = Connection)
+            {
+                var sbTourDTO = new StringBuilder();
+                sbTourDTO.AppendLine("SELECT");
+                sbTourDTO.AppendLine("id");
+                sbTourDTO.AppendLine(", title");
+                sbTourDTO.AppendLine(", header");
+                sbTourDTO.AppendLine(", [description]");
+                sbTourDTO.AppendLine(", [route]");
+                sbTourDTO.AppendLine(", periodStart");
+                sbTourDTO.AppendLine(", periodEnd");
+                sbTourDTO.AppendLine(", minPrice");
+                sbTourDTO.AppendLine(", Photo");
+                sbTourDTO.AppendLine(", Thumbnail");
+                sbTourDTO.AppendLine("FROM tour");
+
+                conn.Open();
+                var tourDTOList = await conn.QueryAsync<TourDTO>(sbTourDTO.ToString());
+
+                var tourList = new List<Tour>();
+
+                tourDTOList.ToList().ForEach(delegate(TourDTO tourDTO)
+                {
+                    var tour = new Tour
+                    {
+                        Id = tourDTO.Id,
+                        Title = tourDTO.Title,
+                        Header = tourDTO.Header,
+                        Description = tourDTO.Description,
+                        Route = tourDTO.Route,
+                        PeriodStart = tourDTO.PeriodStart,
+                        PeriodEnd = tourDTO.PeriodEnd,
+                        MinPrice = tourDTO.MinPrice,
+
+                        PhotoCard = new PhotoCard
+                        {
+                            Photo = tourDTO.Photo,
+                            Thumbnail = tourDTO.Thumbnail
+                        }
+                    };
+                    tourList.Add(tour);
+                });
+
+                return tourList;
+
+            }
+
+        }
+    }
+}
diff --git "a/\320\241onstellation/Startup.cs" "b/\320\241onstellation/Startup.cs"
new file mode 100644
index 0000000..4d177a6
--- /dev/null
+++ "b/\320\241onstellation/Startup.cs"
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.HttpsPolicy;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Constellation.Services;
+
+namespace Constellation
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddTransient<ITourRepository, TourRepository>();
+            services.Configure<CookiePolicyOptions>(options =>
+            {
+                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
+                options.CheckConsentNeeded = context => true;
+                options.MinimumSameSitePolicy = SameSiteMode.None;
+            });
+
+
+            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+            }
+            else
+            {
+                app.UseExceptionHandler("/Home/Error");
+                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+                app.UseHsts();
+            }
+
+            app.UseHttpsRedirection();
+            app.UseStaticFiles();
+            app.UseCookiePolicy();
+
+            app.UseMvc(routes =>
+            {
+                routes.MapRoute(
+                    name: "default",
+                    template: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}
diff --git "a/\320\241onstellation/Views/Home/Index.cshtml" "b/\320\241onstellation/Views/Home/Index.cshtml"
new file mode 100644
index 0000000..08a5a5c
--- /dev/null
+++ "b/\320\241onstellation/Views/Home/Index.cshtml"
@@ -0,0 +1,8 @@
+@{
+    ViewData["Title"] = "Home Page";
+}
+
+<div class="text-center">
+    <h1 class="display-4">Welcome</h1>
+    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
+</div>
diff --git "a/\320\241onstellation/Views/Home/Privacy.cshtml" "b/\320\241onstellation/Views/Home/Privacy.cshtml"
new file mode 100644
index 0000000..2479fb7
--- /dev/null
+++ "b/\320\241onstellation/Views/Home/Privacy.cshtml"
@@ -0,0 +1,6 @@
+@{
+    ViewData["Title"] = "Privacy Policy";
+}
+<h1>@ViewData["Title"]</h1>
+
+<p>Use this page to detail your site's privacy policy.</p>
diff --git "a/\320\241onstellation/Views/Shared/Error.cshtml" "b/\320\241onstellation/Views/Shared/Error.cshtml"
new file mode 100644
index 0000000..7e4df6f
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/Error.cshtml"
@@ -0,0 +1,25 @@
+@model ErrorViewModel
+@{
+    ViewData["Title"] = "Error";
+}
+
+<h1 class="text-danger">Error.</h1>
+<h2 class="text-danger">An error occurred while processing your request.</h2>
+
+@if (Model.ShowRequestId)
+{
+<p>
+    <strong>Request ID:</strong> <code>@Model.RequestId</code>
+</p>
+}
+
+<h3>Development Mode</h3>
+<p>
+    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
+</p>
+<p>
+    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
+    It can result in displaying sensitive information from exceptions to end users.
+    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
+    and restarting the app.
+</p>
diff --git "a/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml" "b/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml"
new file mode 100644
index 0000000..c1f60b4
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml"
@@ -0,0 +1,26 @@
+@using Microsoft.AspNetCore.Http.Features
+
+@{
+    var consentFeature = Context.Features.Get<ITrackingConsentFeature>
+    ();
+    var showBanner = !consentFeature?.CanTrack ?? false;
+    var cookieString = consentFeature?.CreateConsentCookie();
+    }
+
+    @if (showBanner)
+    {
+    <div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
+        Use this space to summarize your privacy and cookie use policy. <a asp-area="" asp-controller="Home" asp-action="Privacy">Learn More</a>.
+        <button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
+            <span aria-hidden="true">Accept</span>
+        </button>
+    </div>
+    <script>
+        (function () {
+            var button = document.querySelector("#cookieConsent button[data-cookie-string]");
+            button.addEventListener("click", function (event) {
+                document.cookie = button.dataset.cookieString;
+            }, false);
+        })();
+    </script>
+    }
diff --git "a/\320\241onstellation/Views/Shared/_Layout.cshtml" "b/\320\241onstellation/Views/Shared/_Layout.cshtml"
new file mode 100644
index 0000000..9867985
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_Layout.cshtml"
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8" />
+        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+        <title>@ViewData["Title"] - Constellation</title>
+
+        <environment include="Development">
+            <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
+        </environment>
+        <environment exclude="Development">
+            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
+                  asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
+                  asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
+                  crossorigin="anonymous"
+                  integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" />
+        </environment>
+        <link rel="stylesheet" href="~/css/site.css" />
+    </head>
+    <body>
+        <header>
+            <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
+                <div class="container">
+                    <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Constellation</a>
+                    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
+                            aria-expanded="false" aria-label="Toggle navigation">
+                        <span class="navbar-toggler-icon"></span>
+                    </button>
+                    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
+                        <ul class="navbar-nav flex-grow-1">
+                            <li class="nav-item">
+                                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </nav>
+        </header>
+        <div class="container">
+            <partial name="_CookieConsentPartial" />
+            <main role="main" class="pb-3">
+                @RenderBody()
+            </main>
+        </div>
+
+        <footer class="border-top footer text-muted">
+            <div class="container">
+                &copy; 2019 - Constellation - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+            </div>
+        </footer>
+
+        <environment include="Development">
+            <script src="~/lib/jquery/dist/jquery.js"></script>
+            <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
+        </environment>
+        <environment exclude="Development">
+            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
+                    asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
+                    asp-fallback-test="window.jQuery"
+                    crossorigin="anonymous"
+                    integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
+            </script>
+            <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
+                    asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
+                    asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
+                    crossorigin="anonymous"
+                    integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
+            </script>
+        </environment>
+        <script src="~/js/site.js" asp-append-version="true"></script>
+
+        @RenderSection("Scripts", required: false)
+    </body>
+</html>
diff --git "a/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml" "b/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml"
new file mode 100644
index 0000000..cb4d75c
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml"
@@ -0,0 +1,18 @@
+<environment include="Development">
+    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
+    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
+</environment>
+<environment exclude="Development">
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
+            asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
+            asp-fallback-test="window.jQuery && window.jQuery.validator"
+            crossorigin="anonymous"
+            integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
+    </script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
+            asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
+            asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
+            crossorigin="anonymous"
+            integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
+    </script>
+</environment>
diff --git "a/\320\241onstellation/Views/_ViewImports.cshtml" "b/\320\241onstellation/Views/_ViewImports.cshtml"
new file mode 100644
index 0000000..689a1da
--- /dev/null
+++ "b/\320\241onstellation/Views/_ViewImports.cshtml"
@@ -0,0 +1,3 @@
+@using Constellation
+@using Constellation.Models
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git "a/\320\241onstellation/Views/_ViewStart.cshtml" "b/\320\241onstellation/Views/_ViewStart.cshtml"
new file mode 100644
index 0000000..6e88aa3
--- /dev/null
+++ "b/\320\241onstellation/Views/_ViewStart.cshtml"
@@ -0,0 +1,3 @@
+@{
+    Layout = "_Layout";
+}
diff --git "a/\320\241onstellation/appsettings.Development.json" "b/\320\241onstellation/appsettings.Development.json"
new file mode 100644
index 0000000..a2880cb
--- /dev/null
+++ "b/\320\241onstellation/appsettings.Development.json"
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git "a/\320\241onstellation/appsettings.json" "b/\320\241onstellation/appsettings.json"
new file mode 100644
index 0000000..aee0e66
--- /dev/null
+++ "b/\320\241onstellation/appsettings.json"
@@ -0,0 +1,11 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Warning"
+    }
+  },
+  "ConnectionStrings": {
+    "MyConnectionString": "Server=localhost;Database=Сonstellation_Test;User Id=sa; Password=123"
+  },
+  "AllowedHosts": "*"
+}
diff --git "a/\320\241onstellation/wwwroot/css/site.css" "b/\320\241onstellation/wwwroot/css/site.css"
new file mode 100644
index 0000000..607e2e5
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/css/site.css"
@@ -0,0 +1,59 @@
+/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+for details on configuring this project to bundle and minify static web assets. */
+
+a.navbar-brand {
+    white-space: normal;
+    text-align: center;
+    word-break: break-all;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    font-size: 14px;
+}
+
+@media (min-width: 768px) {
+    html {
+        font-size: 16px;
+    }
+}
+
+.border-top {
+    border-top: 1px solid #e5e5e5;
+}
+
+.border-bottom {
+    border-bottom: 1px solid #e5e5e5;
+}
+
+.box-shadow {
+    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
+}
+
+button.accept-policy {
+    font-size: 1rem;
+    line-height: inherit;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    position: relative;
+    min-height: 100%;
+}
+
+body {
+    /* Margin bottom by footer height */
+    margin-bottom: 60px;
+}
+
+.footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    white-space: nowrap;
+    /* Set the fixed height of the footer here */
+    height: 60px;
+    line-height: 60px; /* Vertically center the text there */
+}
diff --git "a/\320\241onstellation/wwwroot/favicon.ico" "b/\320\241onstellation/wwwroot/favicon.ico"
new file mode 100644
index 0000000..a3a7999
Binary files /dev/null and "b/\320\241onstellation/wwwroot/favicon.ico" differ
diff --git "a/\320\241onstellation/wwwroot/js/site.js" "b/\320\241onstellation/wwwroot/js/site.js"
new file mode 100644
index 0000000..ac49c18
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/js/site.js"
@@ -0,0 +1,4 @@
+// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+// for details on configuring this project to bundle and minify static web assets.
+
+// Write your JavaScript code.
diff --git "a/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE" "b/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE"
new file mode 100644
index 0000000..86f4b8c
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE"
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2011-2018 Twitter, Inc.
+Copyright (c) 2011-2018 The Bootstrap Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git "a/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css" "b/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css"
new file mode 100644
index 0000000..b26671f
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css"
@@ -0,0 +1,2244 @@
+/*!
+ * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)
+ * Copyright 2011-2018 The Bootstrap Authors
+ * Copyright 2011-2018 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+@-ms-viewport {
+    width: device-width;
+}
+
+html {
+    box-sizing: border-box;
+    -ms-overflow-style: scrollbar;
+}
+
+*,
+*::before,
+*::after {
+    box-sizing: inherit;
+}
+
+.container {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+
+@media (min-width: 576px) {
+    .container {
+        max-width: 540px;
+    }
+}
+
+@media (min-width: 768px) {
+    .container {
+        max-width: 720px;
+    }
+}
+
+@media (min-width: 992px) {
+    .container {
+        max-width: 960px;
+    }
+}
+
+@media (min-width: 1200px) {
+    .container {
+        max-width: 1140px;
+    }
+}
+
+.container-fluid {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+
+.row {
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex-wrap: wrap;
+    flex-wrap: wrap;
+    margin-right: -15px;
+    margin-left: -15px;
+}
+
+.no-gutters {
+    margin-right: 0;
+    margin-left: 0;
+}
+
+    .no-gutters > .col,
+    .no-gutters > [class*="col-"] {
+        padding-right: 0;
+        padding-left: 0;
+    }
+
+.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,
+.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,
+.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,
+.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,
+.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,
+.col-xl-auto {
+    position: relative;
+    width: 100%;
+    min-height: 1px;
+    padding-right: 15px;
+    padding-left: 15px;
+}
+
+.col {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+}
+
+.col-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+}
+
+.col-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+}
+
+.col-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+}
+
+.col-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+}
+
+.col-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+}
+
+.col-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+}
+
+.col-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+}
+
+.col-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+}
+
+.col-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+}
+
+.col-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+}
+
+.col-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+}
+
+.col-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+}
+
+.col-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+}
+
+.order-first {
+    -ms-flex-order: -1;
+    order: -1;
+}
+
+.order-last {
+    -ms-flex-order: 13;
+    order: 13;
+}
+
+.order-0 {
+    -ms-flex-order: 0;
+    order: 0;
+}
+
+.order-1 {
+    -ms-flex-order: 1;
+    order: 1;
+}
+
+.order-2 {
+    -ms-flex-order: 2;
+    order: 2;
+}
+
+.order-3 {
+    -ms-flex-order: 3;
+    order: 3;
+}
+
+.order-4 {
+    -ms-flex-order: 4;
+    order: 4;
+}
+
+.order-5 {
+    -ms-flex-order: 5;
+    order: 5;
+}
+
+.order-6 {
+    -ms-flex-order: 6;
+    order: 6;
+}
+
+.order-7 {
+    -ms-flex-order: 7;
+    order: 7;
+}
+
+.order-8 {
+    -ms-flex-order: 8;
+    order: 8;
+}
+
+.order-9 {
+    -ms-flex-order: 9;
+    order: 9;
+}
+
+.order-10 {
+    -ms-flex-order: 10;
+    order: 10;
+}
+
+.order-11 {
+    -ms-flex-order: 11;
+    order: 11;
+}
+
+.order-12 {
+    -ms-flex-order: 12;
+    order: 12;
+}
+
+.offset-1 {
+    margin-left: 8.333333%;
+}
+
+.offset-2 {
+    margin-left: 16.666667%;
+}
+
+.offset-3 {
+    margin-left: 25%;
+}
+
+.offset-4 {
+    margin-left: 33.333333%;
+}
+
+.offset-5 {
+    margin-left: 41.666667%;
+}
+
+.offset-6 {
+    margin-left: 50%;
+}
+
+.offset-7 {
+    margin-left: 58.333333%;
+}
+
+.offset-8 {
+    margin-left: 66.666667%;
+}
+
+.offset-9 {
+    margin-left: 75%;
+}
+
+.offset-10 {
+    margin-left: 83.333333%;
+}
+
+.offset-11 {
+    margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+    .col-sm {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-sm-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-sm-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-sm-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-sm-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-sm-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-sm-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-sm-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-sm-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-sm-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-sm-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-sm-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-sm-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-sm-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-sm-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-sm-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-sm-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-sm-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-sm-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-sm-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-sm-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-sm-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-sm-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-sm-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-sm-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-sm-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-sm-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-sm-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-sm-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-sm-0 {
+        margin-left: 0;
+    }
+
+    .offset-sm-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-sm-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-sm-3 {
+        margin-left: 25%;
+    }
+
+    .offset-sm-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-sm-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-sm-6 {
+        margin-left: 50%;
+    }
+
+    .offset-sm-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-sm-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-sm-9 {
+        margin-left: 75%;
+    }
+
+    .offset-sm-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-sm-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 768px) {
+    .col-md {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-md-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-md-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-md-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-md-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-md-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-md-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-md-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-md-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-md-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-md-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-md-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-md-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-md-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-md-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-md-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-md-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-md-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-md-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-md-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-md-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-md-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-md-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-md-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-md-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-md-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-md-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-md-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-md-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-md-0 {
+        margin-left: 0;
+    }
+
+    .offset-md-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-md-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-md-3 {
+        margin-left: 25%;
+    }
+
+    .offset-md-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-md-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-md-6 {
+        margin-left: 50%;
+    }
+
+    .offset-md-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-md-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-md-9 {
+        margin-left: 75%;
+    }
+
+    .offset-md-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-md-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 992px) {
+    .col-lg {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-lg-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-lg-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-lg-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-lg-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-lg-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-lg-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-lg-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-lg-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-lg-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-lg-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-lg-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-lg-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-lg-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-lg-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-lg-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-lg-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-lg-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-lg-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-lg-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-lg-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-lg-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-lg-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-lg-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-lg-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-lg-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-lg-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-lg-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-lg-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-lg-0 {
+        margin-left: 0;
+    }
+
+    .offset-lg-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-lg-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-lg-3 {
+        margin-left: 25%;
+    }
+
+    .offset-lg-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-lg-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-lg-6 {
+        margin-left: 50%;
+    }
+
+    .offset-lg-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-lg-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-lg-9 {
+        margin-left: 75%;
+    }
+
+    .offset-lg-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-lg-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 1200px) {
+    .col-xl {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-xl-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-xl-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-xl-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-xl-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-xl-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-xl-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-xl-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-xl-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-xl-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-xl-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-xl-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-xl-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-xl-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-xl-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-xl-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-xl-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-xl-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-xl-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-xl-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-xl-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-xl-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-xl-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-xl-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-xl-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-xl-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-xl-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-xl-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-xl-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-xl-0 {
+        margin-left: 0;
+    }
+
+    .offset-xl-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-xl-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-xl-3 {
+        margin-left: 25%;
+    }
+
+    .offset-xl-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-xl-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-xl-6 {
+        margin-left: 50%;
+    }
+
+    .offset-xl-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-xl-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-xl-9 {
+        margin-left: 75%;
+    }
+
+    .offset-xl-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-xl-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+.d-none {
+    display: none !important;
+}
+
+.d-inline {
+    display: inline !important;
+}
+
+.d-inline-block {
+    display: inline-block !important;
+}
+
+.d-block {
+    display: block !important;
+}
+
+.d-table {
+    display: table !important;
+}
+
+.d-table-row {
+    display: table-row !important;
+}
+
+.d-table-cell {
+    display: table-cell !important;
+}
+
+.d-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+}
+
+.d-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+}
+
+@media (min-width: 576px) {
+    .d-sm-none {
+        display: none !important;
+    }
+
+    .d-sm-inline {
+        display: inline !important;
+    }
+
+    .d-sm-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-sm-block {
+        display: block !important;
+    }
+
+    .d-sm-table {
+        display: table !important;
+    }
+
+    .d-sm-table-row {
+        display: table-row !important;
+    }
+
+    .d-sm-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-sm-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-sm-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 768px) {
+    .d-md-none {
+        display: none !important;
+    }
+
+    .d-md-inline {
+        display: inline !important;
+    }
+
+    .d-md-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-md-block {
+        display: block !important;
+    }
+
+    .d-md-table {
+        display: table !important;
+    }
+
+    .d-md-table-row {
+        display: table-row !important;
+    }
+
+    .d-md-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-md-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-md-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 992px) {
+    .d-lg-none {
+        display: none !important;
+    }
+
+    .d-lg-inline {
+        display: inline !important;
+    }
+
+    .d-lg-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-lg-block {
+        display: block !important;
+    }
+
+    .d-lg-table {
+        display: table !important;
+    }
+
+    .d-lg-table-row {
+        display: table-row !important;
+    }
+
+    .d-lg-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-lg-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-lg-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 1200px) {
+    .d-xl-none {
+        display: none !important;
+    }
+
+    .d-xl-inline {
+        display: inline !important;
+    }
+
+    .d-xl-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-xl-block {
+        display: block !important;
+    }
+
+    .d-xl-table {
+        display: table !important;
+    }
+
+    .d-xl-table-row {
+        display: table-row !important;
+    }
+
+    .d-xl-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-xl-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-xl-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media print {
+    .d-print-none {
+        display: none !important;
+    }
+
+    .d-print-inline {
+        display: inline !important;
+    }
+
+    .d-print-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-print-block {
+        display: block !important;
+    }
+
+    .d-print-table {
+        display: table !important;
+    }
+
+    .d-print-table-row {
+        display: table-row !important;
+    }
+
+    .d-print-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-print-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-print-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+.flex-row {
+    -ms-flex-direction: row !important;
+    flex-direction: row !important;
+}
+
+.flex-column {
+    -ms-flex-direction: column !important;
+    flex-direction: column !important;
+}
+
+.flex-row-reverse {
+    -ms-flex-direction: row-reverse !important;
+    flex-direction: row-reverse !important;
+}
+
+.flex-column-reverse {
+    -ms-flex-direction: column-reverse !important;
+    flex-direction: column-reverse !important;
+}
+
+.flex-wrap {
+    -ms-flex-wrap: wrap !important;
+    flex-wrap: wrap !important;
+}
+
+.flex-nowrap {
+    -ms-flex-wrap: nowrap !important;
+    flex-wrap: nowrap !important;
+}
+
+.flex-wrap-reverse {
+    -ms-flex-wrap: wrap-reverse !important;
+    flex-wrap: wrap-reverse !important;
+}
+
+.flex-fill {
+    -ms-flex: 1 1 auto !important;
+    flex: 1 1 auto !important;
+}
+
+.flex-grow-0 {
+    -ms-flex-positive: 0 !important;
+    flex-grow: 0 !important;
+}
+
+.flex-grow-1 {
+    -ms-flex-positive: 1 !important;
+    flex-grow: 1 !important;
+}
+
+.flex-shrink-0 {
+    -ms-flex-negative: 0 !important;
+    flex-shrink: 0 !important;
+}
+
+.flex-shrink-1 {
+    -ms-flex-negative: 1 !important;
+    flex-shrink: 1 !important;
+}
+
+.justify-content-start {
+    -ms-flex-pack: start !important;
+    justify-content: flex-start !important;
+}
+
+.justify-content-end {
+    -ms-flex-pack: end !important;
+    justify-content: flex-end !important;
+}
+
+.justify-content-center {
+    -ms-flex-pack: center !important;
+    justify-content: center !important;
+}
+
+.justify-content-between {
+    -ms-flex-pack: justify !important;
+    justify-content: space-between !important;
+}
+
+.justify-content-around {
+    -ms-flex-pack: distribute !important;
+    justify-content: space-around !important;
+}
+
+.align-items-start {
+    -ms-flex-align: start !important;
+    align-items: flex-start !important;
+}
+
+.align-items-end {
+    -ms-flex-align: end !important;
+    align-items: flex-end !important;
+}
+
+.align-items-center {
+    -ms-flex-align: center !important;
+    align-items: center !important;
+}
+
+.align-items-baseline {
+    -ms-flex-align: baseline !important;
+    align-items: baseline !important;
+}
+
+.align-items-stretch {
+    -ms-flex-align: stretch !important;
+    align-items: stretch !important;
+}
+
+.align-content-start {
+    -ms-flex-line-pack: start !important;
+    align-content: flex-start !important;
+}
+
+.align-content-end {
+    -ms-flex-line-pack: end !important;
+    align-content: flex-end !important;
+}
+
+.align-content-center {
+    -ms-flex-line-pack: center !important;
+    align-content: center !important;
+}
+
+.align-content-between {
+    -ms-flex-line-pack: justify !important;
+    align-content: space-between !important;
+}
+
+.align-content-around {
+    -ms-flex-line-pack: distribute !important;
+    align-content: space-around !important;
+}
+
+.align-content-stretch {
+    -ms-flex-line-pack: stretch !important;
+    align-content: stretch !important;
+}
+
+.align-self-auto {
+    -ms-flex-item-align: auto !important;
+    align-self: auto !important;
+}
+
+.align-self-start {
+    -ms-flex-item-align: start !important;
+    align-self: flex-start !important;
+}
+
+.align-self-end {
+    -ms-flex-item-align: end !important;
+    align-self: flex-end !important;
+}
+
+.align-self-center {
+    -ms-flex-item-align: center !important;
+    align-self: center !important;
+}
+
+.align-self-baseline {
+    -ms-flex-item-align: baseline !important;
+    align-self: baseline !important;
+}
+
+.align-self-stretch {
+    -ms-flex-item-align: stretch !important;
+    align-self: stretch !important;
+}
+
+@media (min-width: 576px) {
+    .flex-sm-row {
+        -ms-flex-direction: row !important;
+        flex-direction: row !important;
+    }
+
+    .flex-sm-column {
+        -ms-flex-direction: column !important;
+        flex-direction: column !important;
+    }
+
+    .flex-sm-row-reverse {
+        -ms-flex-direction: row-reverse !important;
+        flex-direction: row-reverse !important;
+    }
+
+    .flex-sm-column-reverse {
+        -ms-flex-direction: column-reverse !important;
+        flex-direction: column-reverse !important;
+    }
+
+    .flex-sm-wrap {
+        -ms-flex-wrap: wrap !important;
+        flex-wrap: wrap !important;
+    }
+
+    .flex-sm-nowrap {
+        -ms-flex-wrap: nowrap !important;
+        flex-wrap: nowrap !important;
+    }
+
+    .flex-sm-wrap-reverse {
+        -ms-flex-wrap: wrap-reverse !important;
+        flex-wrap: wrap-reverse !important;
+    }
+
+    .flex-sm-fill {
+        -ms-flex: 1 1 auto !important;
+        flex: 1 1 auto !important;
+    }
+
+    .flex-sm-grow-0 {
+        -ms-flex-positive: 0 !important;
+        flex-grow: 0 !important;
+    }
+
+    .flex-sm-grow-1 {
+        -ms-flex-positive: 1 !important;
+        flex-grow: 1 !important;
+…

Jlteka added a commit to Jlteka/Constellation that referenced this pull request Mar 22, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git "a/\320\241onstellation.sln" "b/\320\241onstellation.sln"
new file mode 100644
index 0000000..626e658
--- /dev/null
+++ "b/\320\241onstellation.sln"
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Сonstellation", "Сonstellation\Сonstellation.csproj", "{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git "a/\320\241onstellation/Controllers/HomeController.cs" "b/\320\241onstellation/Controllers/HomeController.cs"
new file mode 100644
index 0000000..c196899
--- /dev/null
+++ "b/\320\241onstellation/Controllers/HomeController.cs"
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Constellation.Models;
+
+namespace Constellation.Controllers
+{
+    public class HomeController : Controller
+    {
+        public IActionResult Index()
+        {
+            return View();
+        }
+
+        public IActionResult Privacy()
+        {
+            return View();
+        }
+
+        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+        public IActionResult Error()
+        {
+            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
+        }
+    }
+}
diff --git "a/\320\241onstellation/Controllers/TourController.cs" "b/\320\241onstellation/Controllers/TourController.cs"
new file mode 100644
index 0000000..3d8f463
--- /dev/null
+++ "b/\320\241onstellation/Controllers/TourController.cs"
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.AspNetCore.Mvc;
+using Constellation.Services;
+using Constellation.Models;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace Constellation.Controllers
+{
+    public class TourController : ControllerBase
+    {
+        private readonly ITourRepository _tourRepo;
+
+        public TourController(ITourRepository tourRepo)
+        {
+            _tourRepo = tourRepo;
+        }
+
+        [HttpGet]
+        [Route("tourid/{id}")]
+        public async Task<ActionResult<Tour>> GetById(int id)
+        {
+            return await _tourRepo.GetById(id);
+        }
+
+        [HttpGet]
+        [Route("tourlist")]
+        public async Task<ActionResult<List<Tour>>> GetTourList()
+        {
+            return await _tourRepo.GetTourList();
+        }
+    }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Models/ErrorViewModel.cs" "b/\320\241onstellation/Models/ErrorViewModel.cs"
new file mode 100644
index 0000000..6204c00
--- /dev/null
+++ "b/\320\241onstellation/Models/ErrorViewModel.cs"
@@ -0,0 +1,11 @@
+using System;
+
+namespace Constellation.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Models/PhotoCard.cs" "b/\320\241onstellation/Models/PhotoCard.cs"
new file mode 100644
index 0000000..042b991
--- /dev/null
+++ "b/\320\241onstellation/Models/PhotoCard.cs"
@@ -0,0 +1,9 @@
+using System;
+namespace Constellation.Models
+{
+    public class PhotoCard
+    {
+        public string Photo { get; set; }
+        public string Thumbnail { get; set; }
+    }
+}
diff --git "a/\320\241onstellation/Models/Tour.cs" "b/\320\241onstellation/Models/Tour.cs"
new file mode 100644
index 0000000..0c07f44
--- /dev/null
+++ "b/\320\241onstellation/Models/Tour.cs"
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace Constellation.Models
+{
+    public class Tour
+    {
+        public int Id { get; set; }
+        public string Title { get; set; }
+        public string Header { get; set; }
+        public string Description { get; set; }
+        public string Route { get; set; }
+        public DateTimeOffset PeriodStart { get; set; }
+        public DateTimeOffset PeriodEnd { get; set; }
+        public float MinPrice { get; set; }
+        public PhotoCard PhotoCard { get; set; }
+        public List<PhotoCard> PhotoAlbum { get; set; }
+
+    }
+}
diff --git "a/\320\241onstellation/Models/TourDTO.cs" "b/\320\241onstellation/Models/TourDTO.cs"
new file mode 100644
index 0000000..f632d8b
--- /dev/null
+++ "b/\320\241onstellation/Models/TourDTO.cs"
@@ -0,0 +1,17 @@
+using System;
+namespace Constellation.Models
+{
+    public class TourDTO
+    {
+        public int Id { get; set; }
+        public string Title { get; set; }
+        public string Header { get; set; }
+        public string Description { get; set; }
+        public string Route { get; set; }
+        public DateTimeOffset PeriodStart { get; set; }
+        public DateTimeOffset PeriodEnd { get; set; }
+        public float MinPrice { get; set; }
+        public string Photo { get; set; }
+        public string Thumbnail { get; set; }
+    }
+}
diff --git "a/\320\241onstellation/Program.cs" "b/\320\241onstellation/Program.cs"
new file mode 100644
index 0000000..850dceb
--- /dev/null
+++ "b/\320\241onstellation/Program.cs"
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace Constellation
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateWebHostBuilder(args).Build().Run();
+        }
+
+        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
+                .UseStartup<Startup>();
+    }
+}
diff --git "a/\320\241onstellation/Properties/launchSettings.json" "b/\320\241onstellation/Properties/launchSettings.json"
new file mode 100644
index 0000000..570c805
--- /dev/null
+++ "b/\320\241onstellation/Properties/launchSettings.json"
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:19708",
+      "sslPort": 44328
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "Constellation": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Services/ITourRepository.cs" "b/\320\241onstellation/Services/ITourRepository.cs"
new file mode 100644
index 0000000..a8421ff
--- /dev/null
+++ "b/\320\241onstellation/Services/ITourRepository.cs"
@@ -0,0 +1,13 @@
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using Constellation.Models;
+
+namespace Constellation.Services
+{
+    public interface ITourRepository
+    {
+        Task<Tour> GetById(int id);
+        Task<List<Tour>> GetTourList();
+    }
+}
diff --git "a/\320\241onstellation/Services/TourRepository.cs" "b/\320\241onstellation/Services/TourRepository.cs"
new file mode 100644
index 0000000..9cefdce
--- /dev/null
+++ "b/\320\241onstellation/Services/TourRepository.cs"
@@ -0,0 +1,123 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using System.Collections.Generic;
+using Constellation.Models;
+using Microsoft.Extensions.Configuration;
+using Dapper;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+
+namespace Constellation.Services
+{
+    public class TourRepository : ITourRepository
+    {
+        private readonly IConfiguration _config;
+
+        public TourRepository(IConfiguration config)
+        {
+            _config = config;
+        }
+
+        public IDbConnection Connection => new SqlConnection(_config.GetConnectionString("MyConnectionString"));
+
+        public async Task<Tour> GetById(int id)
+        {
+            using (IDbConnection conn = Connection)
+            {
+                var sbTourDTO = new StringBuilder();
+                sbTourDTO.AppendLine("SELECT");
+                sbTourDTO.AppendLine("id");
+                sbTourDTO.AppendLine(", title");
+                sbTourDTO.AppendLine(", header");
+                sbTourDTO.AppendLine(", [description]");
+                sbTourDTO.AppendLine(", [route]");
+                sbTourDTO.AppendLine(", periodStart");
+                sbTourDTO.AppendLine(", periodEnd");
+                sbTourDTO.AppendLine(", minPrice");
+                sbTourDTO.AppendLine(", Photo");
+                sbTourDTO.AppendLine(", Thumbnail");
+                sbTourDTO.AppendLine("FROM tour");
+                sbTourDTO.AppendLine("WHERE id = @ID");
+
+                conn.Open();
+                var tourDTO = await conn.QueryFirstOrDefaultAsync<TourDTO>(sbTourDTO.ToString(), new { ID = id });
+                var photoCards = await conn.QueryAsync<PhotoCard>("SELECT photo, thumbnail FROM[photoCard] WHERE tourId = @ID", new { ID = id });
+
+                return new Tour
+                {
+                    Id = tourDTO.Id,
+                    Title = tourDTO.Title,
+                    Header = tourDTO.Header,
+                    Description = tourDTO.Description,
+                    Route = tourDTO.Route,
+                    PeriodStart = tourDTO.PeriodStart,
+                    PeriodEnd = tourDTO.PeriodEnd,
+                    MinPrice = tourDTO.MinPrice,
+
+                    PhotoCard = new PhotoCard()
+                    {
+                        Photo = tourDTO.Photo,
+                        Thumbnail = tourDTO.Thumbnail
+                    },
+
+                    PhotoAlbum = photoCards.ToList()
+                };
+            }
+        }
+
+
+        public async Task<List<Tour>> GetTourList()
+        {
+            using (IDbConnection conn = Connection)
+            {
+                var sbTourDTO = new StringBuilder();
+                sbTourDTO.AppendLine("SELECT");
+                sbTourDTO.AppendLine("id");
+                sbTourDTO.AppendLine(", title");
+                sbTourDTO.AppendLine(", header");
+                sbTourDTO.AppendLine(", [description]");
+                sbTourDTO.AppendLine(", [route]");
+                sbTourDTO.AppendLine(", periodStart");
+                sbTourDTO.AppendLine(", periodEnd");
+                sbTourDTO.AppendLine(", minPrice");
+                sbTourDTO.AppendLine(", Photo");
+                sbTourDTO.AppendLine(", Thumbnail");
+                sbTourDTO.AppendLine("FROM tour");
+
+                conn.Open();
+                var tourDTOList = await conn.QueryAsync<TourDTO>(sbTourDTO.ToString());
+
+                var tourList = new List<Tour>();
+
+                tourDTOList.ToList().ForEach(delegate(TourDTO tourDTO)
+                {
+                    var tour = new Tour
+                    {
+                        Id = tourDTO.Id,
+                        Title = tourDTO.Title,
+                        Header = tourDTO.Header,
+                        Description = tourDTO.Description,
+                        Route = tourDTO.Route,
+                        PeriodStart = tourDTO.PeriodStart,
+                        PeriodEnd = tourDTO.PeriodEnd,
+                        MinPrice = tourDTO.MinPrice,
+
+                        PhotoCard = new PhotoCard
+                        {
+                            Photo = tourDTO.Photo,
+                            Thumbnail = tourDTO.Thumbnail
+                        }
+                    };
+                    tourList.Add(tour);
+                });
+
+                return tourList;
+
+            }
+
+        }
+    }
+}
diff --git "a/\320\241onstellation/Startup.cs" "b/\320\241onstellation/Startup.cs"
new file mode 100644
index 0000000..4d177a6
--- /dev/null
+++ "b/\320\241onstellation/Startup.cs"
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.HttpsPolicy;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Constellation.Services;
+
+namespace Constellation
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddTransient<ITourRepository, TourRepository>();
+            services.Configure<CookiePolicyOptions>(options =>
+            {
+                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
+                options.CheckConsentNeeded = context => true;
+                options.MinimumSameSitePolicy = SameSiteMode.None;
+            });
+
+
+            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+            }
+            else
+            {
+                app.UseExceptionHandler("/Home/Error");
+                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+                app.UseHsts();
+            }
+
+            app.UseHttpsRedirection();
+            app.UseStaticFiles();
+            app.UseCookiePolicy();
+
+            app.UseMvc(routes =>
+            {
+                routes.MapRoute(
+                    name: "default",
+                    template: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}
diff --git "a/\320\241onstellation/Views/Home/Index.cshtml" "b/\320\241onstellation/Views/Home/Index.cshtml"
new file mode 100644
index 0000000..08a5a5c
--- /dev/null
+++ "b/\320\241onstellation/Views/Home/Index.cshtml"
@@ -0,0 +1,8 @@
+@{
+    ViewData["Title"] = "Home Page";
+}
+
+<div class="text-center">
+    <h1 class="display-4">Welcome</h1>
+    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
+</div>
diff --git "a/\320\241onstellation/Views/Home/Privacy.cshtml" "b/\320\241onstellation/Views/Home/Privacy.cshtml"
new file mode 100644
index 0000000..2479fb7
--- /dev/null
+++ "b/\320\241onstellation/Views/Home/Privacy.cshtml"
@@ -0,0 +1,6 @@
+@{
+    ViewData["Title"] = "Privacy Policy";
+}
+<h1>@ViewData["Title"]</h1>
+
+<p>Use this page to detail your site's privacy policy.</p>
diff --git "a/\320\241onstellation/Views/Shared/Error.cshtml" "b/\320\241onstellation/Views/Shared/Error.cshtml"
new file mode 100644
index 0000000..7e4df6f
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/Error.cshtml"
@@ -0,0 +1,25 @@
+@model ErrorViewModel
+@{
+    ViewData["Title"] = "Error";
+}
+
+<h1 class="text-danger">Error.</h1>
+<h2 class="text-danger">An error occurred while processing your request.</h2>
+
+@if (Model.ShowRequestId)
+{
+<p>
+    <strong>Request ID:</strong> <code>@Model.RequestId</code>
+</p>
+}
+
+<h3>Development Mode</h3>
+<p>
+    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
+</p>
+<p>
+    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
+    It can result in displaying sensitive information from exceptions to end users.
+    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
+    and restarting the app.
+</p>
diff --git "a/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml" "b/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml"
new file mode 100644
index 0000000..c1f60b4
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml"
@@ -0,0 +1,26 @@
+@using Microsoft.AspNetCore.Http.Features
+
+@{
+    var consentFeature = Context.Features.Get<ITrackingConsentFeature>
+    ();
+    var showBanner = !consentFeature?.CanTrack ?? false;
+    var cookieString = consentFeature?.CreateConsentCookie();
+    }
+
+    @if (showBanner)
+    {
+    <div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
+        Use this space to summarize your privacy and cookie use policy. <a asp-area="" asp-controller="Home" asp-action="Privacy">Learn More</a>.
+        <button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
+            <span aria-hidden="true">Accept</span>
+        </button>
+    </div>
+    <script>
+        (function () {
+            var button = document.querySelector("#cookieConsent button[data-cookie-string]");
+            button.addEventListener("click", function (event) {
+                document.cookie = button.dataset.cookieString;
+            }, false);
+        })();
+    </script>
+    }
diff --git "a/\320\241onstellation/Views/Shared/_Layout.cshtml" "b/\320\241onstellation/Views/Shared/_Layout.cshtml"
new file mode 100644
index 0000000..9867985
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_Layout.cshtml"
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8" />
+        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+        <title>@ViewData["Title"] - Constellation</title>
+
+        <environment include="Development">
+            <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
+        </environment>
+        <environment exclude="Development">
+            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
+                  asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
+                  asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
+                  crossorigin="anonymous"
+                  integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" />
+        </environment>
+        <link rel="stylesheet" href="~/css/site.css" />
+    </head>
+    <body>
+        <header>
+            <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
+                <div class="container">
+                    <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Constellation</a>
+                    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
+                            aria-expanded="false" aria-label="Toggle navigation">
+                        <span class="navbar-toggler-icon"></span>
+                    </button>
+                    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
+                        <ul class="navbar-nav flex-grow-1">
+                            <li class="nav-item">
+                                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </nav>
+        </header>
+        <div class="container">
+            <partial name="_CookieConsentPartial" />
+            <main role="main" class="pb-3">
+                @RenderBody()
+            </main>
+        </div>
+
+        <footer class="border-top footer text-muted">
+            <div class="container">
+                &copy; 2019 - Constellation - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+            </div>
+        </footer>
+
+        <environment include="Development">
+            <script src="~/lib/jquery/dist/jquery.js"></script>
+            <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
+        </environment>
+        <environment exclude="Development">
+            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
+                    asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
+                    asp-fallback-test="window.jQuery"
+                    crossorigin="anonymous"
+                    integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
+            </script>
+            <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
+                    asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
+                    asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
+                    crossorigin="anonymous"
+                    integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
+            </script>
+        </environment>
+        <script src="~/js/site.js" asp-append-version="true"></script>
+
+        @RenderSection("Scripts", required: false)
+    </body>
+</html>
diff --git "a/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml" "b/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml"
new file mode 100644
index 0000000..cb4d75c
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml"
@@ -0,0 +1,18 @@
+<environment include="Development">
+    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
+    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
+</environment>
+<environment exclude="Development">
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
+            asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
+            asp-fallback-test="window.jQuery && window.jQuery.validator"
+            crossorigin="anonymous"
+            integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
+    </script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
+            asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
+            asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
+            crossorigin="anonymous"
+            integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
+    </script>
+</environment>
diff --git "a/\320\241onstellation/Views/_ViewImports.cshtml" "b/\320\241onstellation/Views/_ViewImports.cshtml"
new file mode 100644
index 0000000..689a1da
--- /dev/null
+++ "b/\320\241onstellation/Views/_ViewImports.cshtml"
@@ -0,0 +1,3 @@
+@using Constellation
+@using Constellation.Models
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git "a/\320\241onstellation/Views/_ViewStart.cshtml" "b/\320\241onstellation/Views/_ViewStart.cshtml"
new file mode 100644
index 0000000..6e88aa3
--- /dev/null
+++ "b/\320\241onstellation/Views/_ViewStart.cshtml"
@@ -0,0 +1,3 @@
+@{
+    Layout = "_Layout";
+}
diff --git "a/\320\241onstellation/appsettings.Development.json" "b/\320\241onstellation/appsettings.Development.json"
new file mode 100644
index 0000000..a2880cb
--- /dev/null
+++ "b/\320\241onstellation/appsettings.Development.json"
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git "a/\320\241onstellation/appsettings.json" "b/\320\241onstellation/appsettings.json"
new file mode 100644
index 0000000..aee0e66
--- /dev/null
+++ "b/\320\241onstellation/appsettings.json"
@@ -0,0 +1,11 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Warning"
+    }
+  },
+  "ConnectionStrings": {
+    "MyConnectionString": "Server=localhost;Database=Сonstellation_Test;User Id=sa; Password=123"
+  },
+  "AllowedHosts": "*"
+}
diff --git "a/\320\241onstellation/wwwroot/css/site.css" "b/\320\241onstellation/wwwroot/css/site.css"
new file mode 100644
index 0000000..607e2e5
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/css/site.css"
@@ -0,0 +1,59 @@
+/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+for details on configuring this project to bundle and minify static web assets. */
+
+a.navbar-brand {
+    white-space: normal;
+    text-align: center;
+    word-break: break-all;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    font-size: 14px;
+}
+
+@media (min-width: 768px) {
+    html {
+        font-size: 16px;
+    }
+}
+
+.border-top {
+    border-top: 1px solid #e5e5e5;
+}
+
+.border-bottom {
+    border-bottom: 1px solid #e5e5e5;
+}
+
+.box-shadow {
+    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
+}
+
+button.accept-policy {
+    font-size: 1rem;
+    line-height: inherit;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    position: relative;
+    min-height: 100%;
+}
+
+body {
+    /* Margin bottom by footer height */
+    margin-bottom: 60px;
+}
+
+.footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    white-space: nowrap;
+    /* Set the fixed height of the footer here */
+    height: 60px;
+    line-height: 60px; /* Vertically center the text there */
+}
diff --git "a/\320\241onstellation/wwwroot/favicon.ico" "b/\320\241onstellation/wwwroot/favicon.ico"
new file mode 100644
index 0000000..a3a7999
Binary files /dev/null and "b/\320\241onstellation/wwwroot/favicon.ico" differ
diff --git "a/\320\241onstellation/wwwroot/js/site.js" "b/\320\241onstellation/wwwroot/js/site.js"
new file mode 100644
index 0000000..ac49c18
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/js/site.js"
@@ -0,0 +1,4 @@
+// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+// for details on configuring this project to bundle and minify static web assets.
+
+// Write your JavaScript code.
diff --git "a/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE" "b/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE"
new file mode 100644
index 0000000..86f4b8c
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE"
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2011-2018 Twitter, Inc.
+Copyright (c) 2011-2018 The Bootstrap Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git "a/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css" "b/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css"
new file mode 100644
index 0000000..b26671f
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css"
@@ -0,0 +1,2244 @@
+/*!
+ * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)
+ * Copyright 2011-2018 The Bootstrap Authors
+ * Copyright 2011-2018 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+@-ms-viewport {
+    width: device-width;
+}
+
+html {
+    box-sizing: border-box;
+    -ms-overflow-style: scrollbar;
+}
+
+*,
+*::before,
+*::after {
+    box-sizing: inherit;
+}
+
+.container {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+
+@media (min-width: 576px) {
+    .container {
+        max-width: 540px;
+    }
+}
+
+@media (min-width: 768px) {
+    .container {
+        max-width: 720px;
+    }
+}
+
+@media (min-width: 992px) {
+    .container {
+        max-width: 960px;
+    }
+}
+
+@media (min-width: 1200px) {
+    .container {
+        max-width: 1140px;
+    }
+}
+
+.container-fluid {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+
+.row {
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex-wrap: wrap;
+    flex-wrap: wrap;
+    margin-right: -15px;
+    margin-left: -15px;
+}
+
+.no-gutters {
+    margin-right: 0;
+    margin-left: 0;
+}
+
+    .no-gutters > .col,
+    .no-gutters > [class*="col-"] {
+        padding-right: 0;
+        padding-left: 0;
+    }
+
+.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,
+.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,
+.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,
+.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,
+.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,
+.col-xl-auto {
+    position: relative;
+    width: 100%;
+    min-height: 1px;
+    padding-right: 15px;
+    padding-left: 15px;
+}
+
+.col {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+}
+
+.col-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+}
+
+.col-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+}
+
+.col-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+}
+
+.col-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+}
+
+.col-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+}
+
+.col-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+}
+
+.col-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+}
+
+.col-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+}
+
+.col-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+}
+
+.col-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+}
+
+.col-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+}
+
+.col-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+}
+
+.col-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+}
+
+.order-first {
+    -ms-flex-order: -1;
+    order: -1;
+}
+
+.order-last {
+    -ms-flex-order: 13;
+    order: 13;
+}
+
+.order-0 {
+    -ms-flex-order: 0;
+    order: 0;
+}
+
+.order-1 {
+    -ms-flex-order: 1;
+    order: 1;
+}
+
+.order-2 {
+    -ms-flex-order: 2;
+    order: 2;
+}
+
+.order-3 {
+    -ms-flex-order: 3;
+    order: 3;
+}
+
+.order-4 {
+    -ms-flex-order: 4;
+    order: 4;
+}
+
+.order-5 {
+    -ms-flex-order: 5;
+    order: 5;
+}
+
+.order-6 {
+    -ms-flex-order: 6;
+    order: 6;
+}
+
+.order-7 {
+    -ms-flex-order: 7;
+    order: 7;
+}
+
+.order-8 {
+    -ms-flex-order: 8;
+    order: 8;
+}
+
+.order-9 {
+    -ms-flex-order: 9;
+    order: 9;
+}
+
+.order-10 {
+    -ms-flex-order: 10;
+    order: 10;
+}
+
+.order-11 {
+    -ms-flex-order: 11;
+    order: 11;
+}
+
+.order-12 {
+    -ms-flex-order: 12;
+    order: 12;
+}
+
+.offset-1 {
+    margin-left: 8.333333%;
+}
+
+.offset-2 {
+    margin-left: 16.666667%;
+}
+
+.offset-3 {
+    margin-left: 25%;
+}
+
+.offset-4 {
+    margin-left: 33.333333%;
+}
+
+.offset-5 {
+    margin-left: 41.666667%;
+}
+
+.offset-6 {
+    margin-left: 50%;
+}
+
+.offset-7 {
+    margin-left: 58.333333%;
+}
+
+.offset-8 {
+    margin-left: 66.666667%;
+}
+
+.offset-9 {
+    margin-left: 75%;
+}
+
+.offset-10 {
+    margin-left: 83.333333%;
+}
+
+.offset-11 {
+    margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+    .col-sm {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-sm-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-sm-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-sm-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-sm-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-sm-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-sm-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-sm-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-sm-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-sm-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-sm-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-sm-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-sm-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-sm-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-sm-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-sm-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-sm-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-sm-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-sm-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-sm-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-sm-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-sm-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-sm-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-sm-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-sm-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-sm-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-sm-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-sm-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-sm-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-sm-0 {
+        margin-left: 0;
+    }
+
+    .offset-sm-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-sm-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-sm-3 {
+        margin-left: 25%;
+    }
+
+    .offset-sm-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-sm-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-sm-6 {
+        margin-left: 50%;
+    }
+
+    .offset-sm-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-sm-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-sm-9 {
+        margin-left: 75%;
+    }
+
+    .offset-sm-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-sm-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 768px) {
+    .col-md {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-md-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-md-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-md-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-md-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-md-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-md-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-md-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-md-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-md-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-md-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-md-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-md-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-md-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-md-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-md-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-md-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-md-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-md-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-md-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-md-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-md-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-md-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-md-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-md-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-md-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-md-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-md-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-md-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-md-0 {
+        margin-left: 0;
+    }
+
+    .offset-md-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-md-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-md-3 {
+        margin-left: 25%;
+    }
+
+    .offset-md-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-md-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-md-6 {
+        margin-left: 50%;
+    }
+
+    .offset-md-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-md-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-md-9 {
+        margin-left: 75%;
+    }
+
+    .offset-md-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-md-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 992px) {
+    .col-lg {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-lg-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-lg-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-lg-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-lg-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-lg-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-lg-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-lg-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-lg-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-lg-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-lg-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-lg-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-lg-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-lg-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-lg-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-lg-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-lg-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-lg-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-lg-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-lg-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-lg-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-lg-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-lg-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-lg-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-lg-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-lg-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-lg-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-lg-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-lg-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-lg-0 {
+        margin-left: 0;
+    }
+
+    .offset-lg-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-lg-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-lg-3 {
+        margin-left: 25%;
+    }
+
+    .offset-lg-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-lg-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-lg-6 {
+        margin-left: 50%;
+    }
+
+    .offset-lg-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-lg-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-lg-9 {
+        margin-left: 75%;
+    }
+
+    .offset-lg-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-lg-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 1200px) {
+    .col-xl {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-xl-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-xl-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-xl-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-xl-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-xl-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-xl-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-xl-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-xl-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-xl-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-xl-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-xl-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-xl-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-xl-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-xl-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-xl-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-xl-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-xl-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-xl-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-xl-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-xl-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-xl-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-xl-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-xl-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-xl-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-xl-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-xl-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-xl-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-xl-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-xl-0 {
+        margin-left: 0;
+    }
+
+    .offset-xl-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-xl-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-xl-3 {
+        margin-left: 25%;
+    }
+
+    .offset-xl-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-xl-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-xl-6 {
+        margin-left: 50%;
+    }
+
+    .offset-xl-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-xl-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-xl-9 {
+        margin-left: 75%;
+    }
+
+    .offset-xl-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-xl-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+.d-none {
+    display: none !important;
+}
+
+.d-inline {
+    display: inline !important;
+}
+
+.d-inline-block {
+    display: inline-block !important;
+}
+
+.d-block {
+    display: block !important;
+}
+
+.d-table {
+    display: table !important;
+}
+
+.d-table-row {
+    display: table-row !important;
+}
+
+.d-table-cell {
+    display: table-cell !important;
+}
+
+.d-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+}
+
+.d-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+}
+
+@media (min-width: 576px) {
+    .d-sm-none {
+        display: none !important;
+    }
+
+    .d-sm-inline {
+        display: inline !important;
+    }
+
+    .d-sm-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-sm-block {
+        display: block !important;
+    }
+
+    .d-sm-table {
+        display: table !important;
+    }
+
+    .d-sm-table-row {
+        display: table-row !important;
+    }
+
+    .d-sm-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-sm-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-sm-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 768px) {
+    .d-md-none {
+        display: none !important;
+    }
+
+    .d-md-inline {
+        display: inline !important;
+    }
+
+    .d-md-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-md-block {
+        display: block !important;
+    }
+
+    .d-md-table {
+        display: table !important;
+    }
+
+    .d-md-table-row {
+        display: table-row !important;
+    }
+
+    .d-md-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-md-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-md-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 992px) {
+    .d-lg-none {
+        display: none !important;
+    }
+
+    .d-lg-inline {
+        display: inline !important;
+    }
+
+    .d-lg-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-lg-block {
+        display: block !important;
+    }
+
+    .d-lg-table {
+        display: table !important;
+    }
+
+    .d-lg-table-row {
+        display: table-row !important;
+    }
+
+    .d-lg-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-lg-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-lg-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 1200px) {
+    .d-xl-none {
+        display: none !important;
+    }
+
+    .d-xl-inline {
+        display: inline !important;
+    }
+
+    .d-xl-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-xl-block {
+        display: block !important;
+    }
+
+    .d-xl-table {
+        display: table !important;
+    }
+
+    .d-xl-table-row {
+        display: table-row !important;
+    }
+
+    .d-xl-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-xl-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-xl-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media print {
+    .d-print-none {
+        display: none !important;
+    }
+
+    .d-print-inline {
+        display: inline !important;
+    }
+
+    .d-print-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-print-block {
+        display: block !important;
+    }
+
+    .d-print-table {
+        display: table !important;
+    }
+
+    .d-print-table-row {
+        display: table-row !important;
+    }
+
+    .d-print-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-print-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-print-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+.flex-row {
+    -ms-flex-direction: row !important;
+    flex-direction: row !important;
+}
+
+.flex-column {
+    -ms-flex-direction: column !important;
+    flex-direction: column !important;
+}
+
+.flex-row-reverse {
+    -ms-flex-direction: row-reverse !important;
+    flex-direction: row-reverse !important;
+}
+
+.flex-column-reverse {
+    -ms-flex-direction: column-reverse !important;
+    flex-direction: column-reverse !important;
+}
+
+.flex-wrap {
+    -ms-flex-wrap: wrap !important;
+    flex-wrap: wrap !important;
+}
+
+.flex-nowrap {
+    -ms-flex-wrap: nowrap !important;
+    flex-wrap: nowrap !important;
+}
+
+.flex-wrap-reverse {
+    -ms-flex-wrap: wrap-reverse !important;
+    flex-wrap: wrap-reverse !important;
+}
+
+.flex-fill {
+    -ms-flex: 1 1 auto !important;
+    flex: 1 1 auto !important;
+}
+
+.flex-grow-0 {
+    -ms-flex-positive: 0 !important;
+    flex-grow: 0 !important;
+}
+
+.flex-grow-1 {
+    -ms-flex-positive: 1 !important;
+    flex-grow: 1 !important;
+}
+
+.flex-shrink-0 {
+    -ms-flex-negative: 0 !important;
+    flex-shrink: 0 !important;
+}
+
+.flex-shrink-1 {
+    -ms-flex-negative: 1 !important;
+    flex-shrink: 1 !important;
+}
+
+.justify-content-start {
+    -ms-flex-pack: start !important;
+    justify-content: flex-start !important;
+}
+
+.justify-content-end {
+    -ms-flex-pack: end !important;
+    justify-content: flex-end !important;
+}
+
+.justify-content-center {
+    -ms-flex-pack: center !important;
+    justify-content: center !important;
+}
+
+.justify-content-between {
+    -ms-flex-pack: justify !important;
+    justify-content: space-between !important;
+}
+
+.justify-content-around {
+    -ms-flex-pack: distribute !important;
+    justify-content: space-around !important;
+}
+
+.align-items-start {
+    -ms-flex-align: start !important;
+    align-items: flex-start !important;
+}
+
+.align-items-end {
+    -ms-flex-align: end !important;
+    align-items: flex-end !important;
+}
+
+.align-items-center {
+    -ms-flex-align: center !important;
+    align-items: center !important;
+}
+
+.align-items-baseline {
+    -ms-flex-align: baseline !important;
+    align-items: baseline !important;
+}
+
+.align-items-stretch {
+    -ms-flex-align: stretch !important;
+    align-items: stretch !important;
+}
+
+.align-content-start {
+    -ms-flex-line-pack: start !important;
+    align-content: flex-start !important;
+}
+
+.align-content-end {
+    -ms-flex-line-pack: end !important;
+    align-content: flex-end !important;
+}
+
+.align-content-center {
+    -ms-flex-line-pack: center !important;
+    align-content: center !important;
+}
+
+.align-content-between {
+    -ms-flex-line-pack: justify !important;
+    align-content: space-between !important;
+}
+
+.align-content-around {
+    -ms-flex-line-pack: distribute !important;
+    align-content: space-around !important;
+}
+
+.align-content-stretch {
+    -ms-flex-line-pack: stretch !important;
+    align-content: stretch !important;
+}
+
+.align-self-auto {
+    -ms-flex-item-align: auto !important;
+    align-self: auto !important;
+}
+
+.align-self-start {
+    -ms-flex-item-align: start !important;
+    align-self: flex-start !important;
+}
+
+.align-self-end {
+    -ms-flex-item-align: end !important;
+    align-self: flex-end !important;
+}
+
+.align-self-center {
+    -ms-flex-item-align: center !important;
+    align-self: center !important;
+}
+
+.align-self-baseline {
+    -ms-flex-item-align: baseline !important;
+    align-self: baseline !important;
+}
+
+.align-self-stretch {
+    -ms-flex-item-align: stretch !important;
+    align-self: stretch !important;
+}
+
+@media (min-width: 576px) {
+    .flex-sm-row {
+        -ms-flex-direction: row !important;
+        flex-direction: row !important;
+    }
+
+    .flex-sm-column {
+        -ms-flex-direction: column !important;
+        flex-direction: column !important;
+    }
+
+    .flex-sm-row-reverse {
+        -ms-flex-direction: row-reverse !important;
+        flex-direction: row-reverse !important;
+    }
+
+    .flex-sm-column-reverse {
+        -ms-flex-direction: column-reverse !important;
+        flex-direction: column-reverse !important;
+    }
+
+    .flex-sm-wrap {
+        -ms-flex-wrap: wrap !important;
+        flex-wrap: wrap !important;
+    }
+
+    .flex-sm-nowrap {
+        -ms-flex-wrap: nowrap !important;
+        flex-wrap: nowrap !important;
+    }
+
+    .flex-sm-wrap-reverse {
+        -ms-flex-wrap: wrap-reverse !important;
+        flex-wrap: wrap-reverse !important;
+    }
+
+    .flex-sm-fill {
+        -ms-flex: 1 1 auto !important;
+        flex: 1 1 auto !important;
+    }
+
+    .flex-sm-grow-0 {
+        -ms-flex-positive: 0 !important;
+        flex-grow: 0 !important;
+    }
+
+    .flex-sm-grow-1 {
+        -ms-flex-positive: 1 !important;
+        flex-grow: 1 !important;
+…

Jlteka added a commit to Jlteka/Constellation that referenced this pull request Mar 25, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git "a/\320\241onstellation.sln" "b/\320\241onstellation.sln"
new file mode 100644
index 0000000..626e658
--- /dev/null
+++ "b/\320\241onstellation.sln"
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Сonstellation", "Сonstellation\Сonstellation.csproj", "{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A0DE6F19-801F-4EAC-B90D-9B79C8C9FB89}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git "a/\320\241onstellation/Controllers/HomeController.cs" "b/\320\241onstellation/Controllers/HomeController.cs"
new file mode 100644
index 0000000..c196899
--- /dev/null
+++ "b/\320\241onstellation/Controllers/HomeController.cs"
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Constellation.Models;
+
+namespace Constellation.Controllers
+{
+    public class HomeController : Controller
+    {
+        public IActionResult Index()
+        {
+            return View();
+        }
+
+        public IActionResult Privacy()
+        {
+            return View();
+        }
+
+        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+        public IActionResult Error()
+        {
+            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
+        }
+    }
+}
diff --git "a/\320\241onstellation/Controllers/TourController.cs" "b/\320\241onstellation/Controllers/TourController.cs"
new file mode 100644
index 0000000..3d8f463
--- /dev/null
+++ "b/\320\241onstellation/Controllers/TourController.cs"
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.AspNetCore.Mvc;
+using Constellation.Services;
+using Constellation.Models;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace Constellation.Controllers
+{
+    public class TourController : ControllerBase
+    {
+        private readonly ITourRepository _tourRepo;
+
+        public TourController(ITourRepository tourRepo)
+        {
+            _tourRepo = tourRepo;
+        }
+
+        [HttpGet]
+        [Route("tourid/{id}")]
+        public async Task<ActionResult<Tour>> GetById(int id)
+        {
+            return await _tourRepo.GetById(id);
+        }
+
+        [HttpGet]
+        [Route("tourlist")]
+        public async Task<ActionResult<List<Tour>>> GetTourList()
+        {
+            return await _tourRepo.GetTourList();
+        }
+    }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Models/ErrorViewModel.cs" "b/\320\241onstellation/Models/ErrorViewModel.cs"
new file mode 100644
index 0000000..6204c00
--- /dev/null
+++ "b/\320\241onstellation/Models/ErrorViewModel.cs"
@@ -0,0 +1,11 @@
+using System;
+
+namespace Constellation.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Models/PhotoCard.cs" "b/\320\241onstellation/Models/PhotoCard.cs"
new file mode 100644
index 0000000..042b991
--- /dev/null
+++ "b/\320\241onstellation/Models/PhotoCard.cs"
@@ -0,0 +1,9 @@
+using System;
+namespace Constellation.Models
+{
+    public class PhotoCard
+    {
+        public string Photo { get; set; }
+        public string Thumbnail { get; set; }
+    }
+}
diff --git "a/\320\241onstellation/Models/Tour.cs" "b/\320\241onstellation/Models/Tour.cs"
new file mode 100644
index 0000000..0c07f44
--- /dev/null
+++ "b/\320\241onstellation/Models/Tour.cs"
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace Constellation.Models
+{
+    public class Tour
+    {
+        public int Id { get; set; }
+        public string Title { get; set; }
+        public string Header { get; set; }
+        public string Description { get; set; }
+        public string Route { get; set; }
+        public DateTimeOffset PeriodStart { get; set; }
+        public DateTimeOffset PeriodEnd { get; set; }
+        public float MinPrice { get; set; }
+        public PhotoCard PhotoCard { get; set; }
+        public List<PhotoCard> PhotoAlbum { get; set; }
+
+    }
+}
diff --git "a/\320\241onstellation/Models/TourDTO.cs" "b/\320\241onstellation/Models/TourDTO.cs"
new file mode 100644
index 0000000..f632d8b
--- /dev/null
+++ "b/\320\241onstellation/Models/TourDTO.cs"
@@ -0,0 +1,17 @@
+using System;
+namespace Constellation.Models
+{
+    public class TourDTO
+    {
+        public int Id { get; set; }
+        public string Title { get; set; }
+        public string Header { get; set; }
+        public string Description { get; set; }
+        public string Route { get; set; }
+        public DateTimeOffset PeriodStart { get; set; }
+        public DateTimeOffset PeriodEnd { get; set; }
+        public float MinPrice { get; set; }
+        public string Photo { get; set; }
+        public string Thumbnail { get; set; }
+    }
+}
diff --git "a/\320\241onstellation/Program.cs" "b/\320\241onstellation/Program.cs"
new file mode 100644
index 0000000..850dceb
--- /dev/null
+++ "b/\320\241onstellation/Program.cs"
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace Constellation
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateWebHostBuilder(args).Build().Run();
+        }
+
+        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
+                .UseStartup<Startup>();
+    }
+}
diff --git "a/\320\241onstellation/Properties/launchSettings.json" "b/\320\241onstellation/Properties/launchSettings.json"
new file mode 100644
index 0000000..570c805
--- /dev/null
+++ "b/\320\241onstellation/Properties/launchSettings.json"
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:19708",
+      "sslPort": 44328
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "Constellation": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git "a/\320\241onstellation/Services/ITourRepository.cs" "b/\320\241onstellation/Services/ITourRepository.cs"
new file mode 100644
index 0000000..a8421ff
--- /dev/null
+++ "b/\320\241onstellation/Services/ITourRepository.cs"
@@ -0,0 +1,13 @@
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using Constellation.Models;
+
+namespace Constellation.Services
+{
+    public interface ITourRepository
+    {
+        Task<Tour> GetById(int id);
+        Task<List<Tour>> GetTourList();
+    }
+}
diff --git "a/\320\241onstellation/Services/TourRepository.cs" "b/\320\241onstellation/Services/TourRepository.cs"
new file mode 100644
index 0000000..9cefdce
--- /dev/null
+++ "b/\320\241onstellation/Services/TourRepository.cs"
@@ -0,0 +1,123 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using System.Collections.Generic;
+using Constellation.Models;
+using Microsoft.Extensions.Configuration;
+using Dapper;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+
+namespace Constellation.Services
+{
+    public class TourRepository : ITourRepository
+    {
+        private readonly IConfiguration _config;
+
+        public TourRepository(IConfiguration config)
+        {
+            _config = config;
+        }
+
+        public IDbConnection Connection => new SqlConnection(_config.GetConnectionString("MyConnectionString"));
+
+        public async Task<Tour> GetById(int id)
+        {
+            using (IDbConnection conn = Connection)
+            {
+                var sbTourDTO = new StringBuilder();
+                sbTourDTO.AppendLine("SELECT");
+                sbTourDTO.AppendLine("id");
+                sbTourDTO.AppendLine(", title");
+                sbTourDTO.AppendLine(", header");
+                sbTourDTO.AppendLine(", [description]");
+                sbTourDTO.AppendLine(", [route]");
+                sbTourDTO.AppendLine(", periodStart");
+                sbTourDTO.AppendLine(", periodEnd");
+                sbTourDTO.AppendLine(", minPrice");
+                sbTourDTO.AppendLine(", Photo");
+                sbTourDTO.AppendLine(", Thumbnail");
+                sbTourDTO.AppendLine("FROM tour");
+                sbTourDTO.AppendLine("WHERE id = @ID");
+
+                conn.Open();
+                var tourDTO = await conn.QueryFirstOrDefaultAsync<TourDTO>(sbTourDTO.ToString(), new { ID = id });
+                var photoCards = await conn.QueryAsync<PhotoCard>("SELECT photo, thumbnail FROM[photoCard] WHERE tourId = @ID", new { ID = id });
+
+                return new Tour
+                {
+                    Id = tourDTO.Id,
+                    Title = tourDTO.Title,
+                    Header = tourDTO.Header,
+                    Description = tourDTO.Description,
+                    Route = tourDTO.Route,
+                    PeriodStart = tourDTO.PeriodStart,
+                    PeriodEnd = tourDTO.PeriodEnd,
+                    MinPrice = tourDTO.MinPrice,
+
+                    PhotoCard = new PhotoCard()
+                    {
+                        Photo = tourDTO.Photo,
+                        Thumbnail = tourDTO.Thumbnail
+                    },
+
+                    PhotoAlbum = photoCards.ToList()
+                };
+            }
+        }
+
+
+        public async Task<List<Tour>> GetTourList()
+        {
+            using (IDbConnection conn = Connection)
+            {
+                var sbTourDTO = new StringBuilder();
+                sbTourDTO.AppendLine("SELECT");
+                sbTourDTO.AppendLine("id");
+                sbTourDTO.AppendLine(", title");
+                sbTourDTO.AppendLine(", header");
+                sbTourDTO.AppendLine(", [description]");
+                sbTourDTO.AppendLine(", [route]");
+                sbTourDTO.AppendLine(", periodStart");
+                sbTourDTO.AppendLine(", periodEnd");
+                sbTourDTO.AppendLine(", minPrice");
+                sbTourDTO.AppendLine(", Photo");
+                sbTourDTO.AppendLine(", Thumbnail");
+                sbTourDTO.AppendLine("FROM tour");
+
+                conn.Open();
+                var tourDTOList = await conn.QueryAsync<TourDTO>(sbTourDTO.ToString());
+
+                var tourList = new List<Tour>();
+
+                tourDTOList.ToList().ForEach(delegate(TourDTO tourDTO)
+                {
+                    var tour = new Tour
+                    {
+                        Id = tourDTO.Id,
+                        Title = tourDTO.Title,
+                        Header = tourDTO.Header,
+                        Description = tourDTO.Description,
+                        Route = tourDTO.Route,
+                        PeriodStart = tourDTO.PeriodStart,
+                        PeriodEnd = tourDTO.PeriodEnd,
+                        MinPrice = tourDTO.MinPrice,
+
+                        PhotoCard = new PhotoCard
+                        {
+                            Photo = tourDTO.Photo,
+                            Thumbnail = tourDTO.Thumbnail
+                        }
+                    };
+                    tourList.Add(tour);
+                });
+
+                return tourList;
+
+            }
+
+        }
+    }
+}
diff --git "a/\320\241onstellation/Startup.cs" "b/\320\241onstellation/Startup.cs"
new file mode 100644
index 0000000..4d177a6
--- /dev/null
+++ "b/\320\241onstellation/Startup.cs"
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.HttpsPolicy;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Constellation.Services;
+
+namespace Constellation
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddTransient<ITourRepository, TourRepository>();
+            services.Configure<CookiePolicyOptions>(options =>
+            {
+                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
+                options.CheckConsentNeeded = context => true;
+                options.MinimumSameSitePolicy = SameSiteMode.None;
+            });
+
+
+            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+            }
+            else
+            {
+                app.UseExceptionHandler("/Home/Error");
+                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+                app.UseHsts();
+            }
+
+            app.UseHttpsRedirection();
+            app.UseStaticFiles();
+            app.UseCookiePolicy();
+
+            app.UseMvc(routes =>
+            {
+                routes.MapRoute(
+                    name: "default",
+                    template: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}
diff --git "a/\320\241onstellation/Views/Home/Index.cshtml" "b/\320\241onstellation/Views/Home/Index.cshtml"
new file mode 100644
index 0000000..08a5a5c
--- /dev/null
+++ "b/\320\241onstellation/Views/Home/Index.cshtml"
@@ -0,0 +1,8 @@
+@{
+    ViewData["Title"] = "Home Page";
+}
+
+<div class="text-center">
+    <h1 class="display-4">Welcome</h1>
+    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
+</div>
diff --git "a/\320\241onstellation/Views/Home/Privacy.cshtml" "b/\320\241onstellation/Views/Home/Privacy.cshtml"
new file mode 100644
index 0000000..2479fb7
--- /dev/null
+++ "b/\320\241onstellation/Views/Home/Privacy.cshtml"
@@ -0,0 +1,6 @@
+@{
+    ViewData["Title"] = "Privacy Policy";
+}
+<h1>@ViewData["Title"]</h1>
+
+<p>Use this page to detail your site's privacy policy.</p>
diff --git "a/\320\241onstellation/Views/Shared/Error.cshtml" "b/\320\241onstellation/Views/Shared/Error.cshtml"
new file mode 100644
index 0000000..7e4df6f
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/Error.cshtml"
@@ -0,0 +1,25 @@
+@model ErrorViewModel
+@{
+    ViewData["Title"] = "Error";
+}
+
+<h1 class="text-danger">Error.</h1>
+<h2 class="text-danger">An error occurred while processing your request.</h2>
+
+@if (Model.ShowRequestId)
+{
+<p>
+    <strong>Request ID:</strong> <code>@Model.RequestId</code>
+</p>
+}
+
+<h3>Development Mode</h3>
+<p>
+    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
+</p>
+<p>
+    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
+    It can result in displaying sensitive information from exceptions to end users.
+    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
+    and restarting the app.
+</p>
diff --git "a/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml" "b/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml"
new file mode 100644
index 0000000..c1f60b4
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_CookieConsentPartial.cshtml"
@@ -0,0 +1,26 @@
+@using Microsoft.AspNetCore.Http.Features
+
+@{
+    var consentFeature = Context.Features.Get<ITrackingConsentFeature>
+    ();
+    var showBanner = !consentFeature?.CanTrack ?? false;
+    var cookieString = consentFeature?.CreateConsentCookie();
+    }
+
+    @if (showBanner)
+    {
+    <div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
+        Use this space to summarize your privacy and cookie use policy. <a asp-area="" asp-controller="Home" asp-action="Privacy">Learn More</a>.
+        <button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
+            <span aria-hidden="true">Accept</span>
+        </button>
+    </div>
+    <script>
+        (function () {
+            var button = document.querySelector("#cookieConsent button[data-cookie-string]");
+            button.addEventListener("click", function (event) {
+                document.cookie = button.dataset.cookieString;
+            }, false);
+        })();
+    </script>
+    }
diff --git "a/\320\241onstellation/Views/Shared/_Layout.cshtml" "b/\320\241onstellation/Views/Shared/_Layout.cshtml"
new file mode 100644
index 0000000..9867985
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_Layout.cshtml"
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8" />
+        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+        <title>@ViewData["Title"] - Constellation</title>
+
+        <environment include="Development">
+            <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
+        </environment>
+        <environment exclude="Development">
+            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
+                  asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
+                  asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
+                  crossorigin="anonymous"
+                  integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" />
+        </environment>
+        <link rel="stylesheet" href="~/css/site.css" />
+    </head>
+    <body>
+        <header>
+            <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
+                <div class="container">
+                    <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Constellation</a>
+                    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
+                            aria-expanded="false" aria-label="Toggle navigation">
+                        <span class="navbar-toggler-icon"></span>
+                    </button>
+                    <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
+                        <ul class="navbar-nav flex-grow-1">
+                            <li class="nav-item">
+                                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </nav>
+        </header>
+        <div class="container">
+            <partial name="_CookieConsentPartial" />
+            <main role="main" class="pb-3">
+                @RenderBody()
+            </main>
+        </div>
+
+        <footer class="border-top footer text-muted">
+            <div class="container">
+                &copy; 2019 - Constellation - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
+            </div>
+        </footer>
+
+        <environment include="Development">
+            <script src="~/lib/jquery/dist/jquery.js"></script>
+            <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
+        </environment>
+        <environment exclude="Development">
+            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
+                    asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
+                    asp-fallback-test="window.jQuery"
+                    crossorigin="anonymous"
+                    integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
+            </script>
+            <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
+                    asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
+                    asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
+                    crossorigin="anonymous"
+                    integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
+            </script>
+        </environment>
+        <script src="~/js/site.js" asp-append-version="true"></script>
+
+        @RenderSection("Scripts", required: false)
+    </body>
+</html>
diff --git "a/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml" "b/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml"
new file mode 100644
index 0000000..cb4d75c
--- /dev/null
+++ "b/\320\241onstellation/Views/Shared/_ValidationScriptsPartial.cshtml"
@@ -0,0 +1,18 @@
+<environment include="Development">
+    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
+    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
+</environment>
+<environment exclude="Development">
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
+            asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
+            asp-fallback-test="window.jQuery && window.jQuery.validator"
+            crossorigin="anonymous"
+            integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
+    </script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
+            asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
+            asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
+            crossorigin="anonymous"
+            integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
+    </script>
+</environment>
diff --git "a/\320\241onstellation/Views/_ViewImports.cshtml" "b/\320\241onstellation/Views/_ViewImports.cshtml"
new file mode 100644
index 0000000..689a1da
--- /dev/null
+++ "b/\320\241onstellation/Views/_ViewImports.cshtml"
@@ -0,0 +1,3 @@
+@using Constellation
+@using Constellation.Models
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git "a/\320\241onstellation/Views/_ViewStart.cshtml" "b/\320\241onstellation/Views/_ViewStart.cshtml"
new file mode 100644
index 0000000..6e88aa3
--- /dev/null
+++ "b/\320\241onstellation/Views/_ViewStart.cshtml"
@@ -0,0 +1,3 @@
+@{
+    Layout = "_Layout";
+}
diff --git "a/\320\241onstellation/appsettings.Development.json" "b/\320\241onstellation/appsettings.Development.json"
new file mode 100644
index 0000000..a2880cb
--- /dev/null
+++ "b/\320\241onstellation/appsettings.Development.json"
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git "a/\320\241onstellation/appsettings.json" "b/\320\241onstellation/appsettings.json"
new file mode 100644
index 0000000..aee0e66
--- /dev/null
+++ "b/\320\241onstellation/appsettings.json"
@@ -0,0 +1,11 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Warning"
+    }
+  },
+  "ConnectionStrings": {
+    "MyConnectionString": "Server=localhost;Database=Сonstellation_Test;User Id=sa; Password=123"
+  },
+  "AllowedHosts": "*"
+}
diff --git "a/\320\241onstellation/wwwroot/css/site.css" "b/\320\241onstellation/wwwroot/css/site.css"
new file mode 100644
index 0000000..607e2e5
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/css/site.css"
@@ -0,0 +1,59 @@
+/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+for details on configuring this project to bundle and minify static web assets. */
+
+a.navbar-brand {
+    white-space: normal;
+    text-align: center;
+    word-break: break-all;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    font-size: 14px;
+}
+
+@media (min-width: 768px) {
+    html {
+        font-size: 16px;
+    }
+}
+
+.border-top {
+    border-top: 1px solid #e5e5e5;
+}
+
+.border-bottom {
+    border-bottom: 1px solid #e5e5e5;
+}
+
+.box-shadow {
+    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
+}
+
+button.accept-policy {
+    font-size: 1rem;
+    line-height: inherit;
+}
+
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    position: relative;
+    min-height: 100%;
+}
+
+body {
+    /* Margin bottom by footer height */
+    margin-bottom: 60px;
+}
+
+.footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    white-space: nowrap;
+    /* Set the fixed height of the footer here */
+    height: 60px;
+    line-height: 60px; /* Vertically center the text there */
+}
diff --git "a/\320\241onstellation/wwwroot/favicon.ico" "b/\320\241onstellation/wwwroot/favicon.ico"
new file mode 100644
index 0000000..a3a7999
Binary files /dev/null and "b/\320\241onstellation/wwwroot/favicon.ico" differ
diff --git "a/\320\241onstellation/wwwroot/js/site.js" "b/\320\241onstellation/wwwroot/js/site.js"
new file mode 100644
index 0000000..ac49c18
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/js/site.js"
@@ -0,0 +1,4 @@
+// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
+// for details on configuring this project to bundle and minify static web assets.
+
+// Write your JavaScript code.
diff --git "a/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE" "b/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE"
new file mode 100644
index 0000000..86f4b8c
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/lib/bootstrap/LICENSE"
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2011-2018 Twitter, Inc.
+Copyright (c) 2011-2018 The Bootstrap Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git "a/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css" "b/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css"
new file mode 100644
index 0000000..b26671f
--- /dev/null
+++ "b/\320\241onstellation/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css"
@@ -0,0 +1,2244 @@
+/*!
+ * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)
+ * Copyright 2011-2018 The Bootstrap Authors
+ * Copyright 2011-2018 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+@-ms-viewport {
+    width: device-width;
+}
+
+html {
+    box-sizing: border-box;
+    -ms-overflow-style: scrollbar;
+}
+
+*,
+*::before,
+*::after {
+    box-sizing: inherit;
+}
+
+.container {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+
+@media (min-width: 576px) {
+    .container {
+        max-width: 540px;
+    }
+}
+
+@media (min-width: 768px) {
+    .container {
+        max-width: 720px;
+    }
+}
+
+@media (min-width: 992px) {
+    .container {
+        max-width: 960px;
+    }
+}
+
+@media (min-width: 1200px) {
+    .container {
+        max-width: 1140px;
+    }
+}
+
+.container-fluid {
+    width: 100%;
+    padding-right: 15px;
+    padding-left: 15px;
+    margin-right: auto;
+    margin-left: auto;
+}
+
+.row {
+    display: -ms-flexbox;
+    display: flex;
+    -ms-flex-wrap: wrap;
+    flex-wrap: wrap;
+    margin-right: -15px;
+    margin-left: -15px;
+}
+
+.no-gutters {
+    margin-right: 0;
+    margin-left: 0;
+}
+
+    .no-gutters > .col,
+    .no-gutters > [class*="col-"] {
+        padding-right: 0;
+        padding-left: 0;
+    }
+
+.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,
+.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,
+.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,
+.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,
+.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,
+.col-xl-auto {
+    position: relative;
+    width: 100%;
+    min-height: 1px;
+    padding-right: 15px;
+    padding-left: 15px;
+}
+
+.col {
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+    -ms-flex-positive: 1;
+    flex-grow: 1;
+    max-width: 100%;
+}
+
+.col-auto {
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    width: auto;
+    max-width: none;
+}
+
+.col-1 {
+    -ms-flex: 0 0 8.333333%;
+    flex: 0 0 8.333333%;
+    max-width: 8.333333%;
+}
+
+.col-2 {
+    -ms-flex: 0 0 16.666667%;
+    flex: 0 0 16.666667%;
+    max-width: 16.666667%;
+}
+
+.col-3 {
+    -ms-flex: 0 0 25%;
+    flex: 0 0 25%;
+    max-width: 25%;
+}
+
+.col-4 {
+    -ms-flex: 0 0 33.333333%;
+    flex: 0 0 33.333333%;
+    max-width: 33.333333%;
+}
+
+.col-5 {
+    -ms-flex: 0 0 41.666667%;
+    flex: 0 0 41.666667%;
+    max-width: 41.666667%;
+}
+
+.col-6 {
+    -ms-flex: 0 0 50%;
+    flex: 0 0 50%;
+    max-width: 50%;
+}
+
+.col-7 {
+    -ms-flex: 0 0 58.333333%;
+    flex: 0 0 58.333333%;
+    max-width: 58.333333%;
+}
+
+.col-8 {
+    -ms-flex: 0 0 66.666667%;
+    flex: 0 0 66.666667%;
+    max-width: 66.666667%;
+}
+
+.col-9 {
+    -ms-flex: 0 0 75%;
+    flex: 0 0 75%;
+    max-width: 75%;
+}
+
+.col-10 {
+    -ms-flex: 0 0 83.333333%;
+    flex: 0 0 83.333333%;
+    max-width: 83.333333%;
+}
+
+.col-11 {
+    -ms-flex: 0 0 91.666667%;
+    flex: 0 0 91.666667%;
+    max-width: 91.666667%;
+}
+
+.col-12 {
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+    max-width: 100%;
+}
+
+.order-first {
+    -ms-flex-order: -1;
+    order: -1;
+}
+
+.order-last {
+    -ms-flex-order: 13;
+    order: 13;
+}
+
+.order-0 {
+    -ms-flex-order: 0;
+    order: 0;
+}
+
+.order-1 {
+    -ms-flex-order: 1;
+    order: 1;
+}
+
+.order-2 {
+    -ms-flex-order: 2;
+    order: 2;
+}
+
+.order-3 {
+    -ms-flex-order: 3;
+    order: 3;
+}
+
+.order-4 {
+    -ms-flex-order: 4;
+    order: 4;
+}
+
+.order-5 {
+    -ms-flex-order: 5;
+    order: 5;
+}
+
+.order-6 {
+    -ms-flex-order: 6;
+    order: 6;
+}
+
+.order-7 {
+    -ms-flex-order: 7;
+    order: 7;
+}
+
+.order-8 {
+    -ms-flex-order: 8;
+    order: 8;
+}
+
+.order-9 {
+    -ms-flex-order: 9;
+    order: 9;
+}
+
+.order-10 {
+    -ms-flex-order: 10;
+    order: 10;
+}
+
+.order-11 {
+    -ms-flex-order: 11;
+    order: 11;
+}
+
+.order-12 {
+    -ms-flex-order: 12;
+    order: 12;
+}
+
+.offset-1 {
+    margin-left: 8.333333%;
+}
+
+.offset-2 {
+    margin-left: 16.666667%;
+}
+
+.offset-3 {
+    margin-left: 25%;
+}
+
+.offset-4 {
+    margin-left: 33.333333%;
+}
+
+.offset-5 {
+    margin-left: 41.666667%;
+}
+
+.offset-6 {
+    margin-left: 50%;
+}
+
+.offset-7 {
+    margin-left: 58.333333%;
+}
+
+.offset-8 {
+    margin-left: 66.666667%;
+}
+
+.offset-9 {
+    margin-left: 75%;
+}
+
+.offset-10 {
+    margin-left: 83.333333%;
+}
+
+.offset-11 {
+    margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+    .col-sm {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-sm-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-sm-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-sm-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-sm-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-sm-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-sm-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-sm-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-sm-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-sm-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-sm-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-sm-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-sm-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-sm-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-sm-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-sm-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-sm-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-sm-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-sm-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-sm-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-sm-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-sm-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-sm-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-sm-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-sm-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-sm-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-sm-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-sm-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-sm-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-sm-0 {
+        margin-left: 0;
+    }
+
+    .offset-sm-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-sm-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-sm-3 {
+        margin-left: 25%;
+    }
+
+    .offset-sm-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-sm-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-sm-6 {
+        margin-left: 50%;
+    }
+
+    .offset-sm-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-sm-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-sm-9 {
+        margin-left: 75%;
+    }
+
+    .offset-sm-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-sm-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 768px) {
+    .col-md {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-md-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-md-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-md-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-md-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-md-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-md-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-md-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-md-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-md-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-md-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-md-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-md-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-md-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-md-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-md-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-md-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-md-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-md-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-md-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-md-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-md-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-md-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-md-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-md-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-md-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-md-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-md-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-md-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-md-0 {
+        margin-left: 0;
+    }
+
+    .offset-md-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-md-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-md-3 {
+        margin-left: 25%;
+    }
+
+    .offset-md-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-md-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-md-6 {
+        margin-left: 50%;
+    }
+
+    .offset-md-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-md-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-md-9 {
+        margin-left: 75%;
+    }
+
+    .offset-md-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-md-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 992px) {
+    .col-lg {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-lg-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-lg-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-lg-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-lg-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-lg-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-lg-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-lg-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-lg-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-lg-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-lg-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-lg-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-lg-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-lg-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-lg-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-lg-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-lg-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-lg-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-lg-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-lg-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-lg-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-lg-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-lg-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-lg-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-lg-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-lg-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-lg-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-lg-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-lg-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-lg-0 {
+        margin-left: 0;
+    }
+
+    .offset-lg-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-lg-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-lg-3 {
+        margin-left: 25%;
+    }
+
+    .offset-lg-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-lg-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-lg-6 {
+        margin-left: 50%;
+    }
+
+    .offset-lg-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-lg-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-lg-9 {
+        margin-left: 75%;
+    }
+
+    .offset-lg-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-lg-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+@media (min-width: 1200px) {
+    .col-xl {
+        -ms-flex-preferred-size: 0;
+        flex-basis: 0;
+        -ms-flex-positive: 1;
+        flex-grow: 1;
+        max-width: 100%;
+    }
+
+    .col-xl-auto {
+        -ms-flex: 0 0 auto;
+        flex: 0 0 auto;
+        width: auto;
+        max-width: none;
+    }
+
+    .col-xl-1 {
+        -ms-flex: 0 0 8.333333%;
+        flex: 0 0 8.333333%;
+        max-width: 8.333333%;
+    }
+
+    .col-xl-2 {
+        -ms-flex: 0 0 16.666667%;
+        flex: 0 0 16.666667%;
+        max-width: 16.666667%;
+    }
+
+    .col-xl-3 {
+        -ms-flex: 0 0 25%;
+        flex: 0 0 25%;
+        max-width: 25%;
+    }
+
+    .col-xl-4 {
+        -ms-flex: 0 0 33.333333%;
+        flex: 0 0 33.333333%;
+        max-width: 33.333333%;
+    }
+
+    .col-xl-5 {
+        -ms-flex: 0 0 41.666667%;
+        flex: 0 0 41.666667%;
+        max-width: 41.666667%;
+    }
+
+    .col-xl-6 {
+        -ms-flex: 0 0 50%;
+        flex: 0 0 50%;
+        max-width: 50%;
+    }
+
+    .col-xl-7 {
+        -ms-flex: 0 0 58.333333%;
+        flex: 0 0 58.333333%;
+        max-width: 58.333333%;
+    }
+
+    .col-xl-8 {
+        -ms-flex: 0 0 66.666667%;
+        flex: 0 0 66.666667%;
+        max-width: 66.666667%;
+    }
+
+    .col-xl-9 {
+        -ms-flex: 0 0 75%;
+        flex: 0 0 75%;
+        max-width: 75%;
+    }
+
+    .col-xl-10 {
+        -ms-flex: 0 0 83.333333%;
+        flex: 0 0 83.333333%;
+        max-width: 83.333333%;
+    }
+
+    .col-xl-11 {
+        -ms-flex: 0 0 91.666667%;
+        flex: 0 0 91.666667%;
+        max-width: 91.666667%;
+    }
+
+    .col-xl-12 {
+        -ms-flex: 0 0 100%;
+        flex: 0 0 100%;
+        max-width: 100%;
+    }
+
+    .order-xl-first {
+        -ms-flex-order: -1;
+        order: -1;
+    }
+
+    .order-xl-last {
+        -ms-flex-order: 13;
+        order: 13;
+    }
+
+    .order-xl-0 {
+        -ms-flex-order: 0;
+        order: 0;
+    }
+
+    .order-xl-1 {
+        -ms-flex-order: 1;
+        order: 1;
+    }
+
+    .order-xl-2 {
+        -ms-flex-order: 2;
+        order: 2;
+    }
+
+    .order-xl-3 {
+        -ms-flex-order: 3;
+        order: 3;
+    }
+
+    .order-xl-4 {
+        -ms-flex-order: 4;
+        order: 4;
+    }
+
+    .order-xl-5 {
+        -ms-flex-order: 5;
+        order: 5;
+    }
+
+    .order-xl-6 {
+        -ms-flex-order: 6;
+        order: 6;
+    }
+
+    .order-xl-7 {
+        -ms-flex-order: 7;
+        order: 7;
+    }
+
+    .order-xl-8 {
+        -ms-flex-order: 8;
+        order: 8;
+    }
+
+    .order-xl-9 {
+        -ms-flex-order: 9;
+        order: 9;
+    }
+
+    .order-xl-10 {
+        -ms-flex-order: 10;
+        order: 10;
+    }
+
+    .order-xl-11 {
+        -ms-flex-order: 11;
+        order: 11;
+    }
+
+    .order-xl-12 {
+        -ms-flex-order: 12;
+        order: 12;
+    }
+
+    .offset-xl-0 {
+        margin-left: 0;
+    }
+
+    .offset-xl-1 {
+        margin-left: 8.333333%;
+    }
+
+    .offset-xl-2 {
+        margin-left: 16.666667%;
+    }
+
+    .offset-xl-3 {
+        margin-left: 25%;
+    }
+
+    .offset-xl-4 {
+        margin-left: 33.333333%;
+    }
+
+    .offset-xl-5 {
+        margin-left: 41.666667%;
+    }
+
+    .offset-xl-6 {
+        margin-left: 50%;
+    }
+
+    .offset-xl-7 {
+        margin-left: 58.333333%;
+    }
+
+    .offset-xl-8 {
+        margin-left: 66.666667%;
+    }
+
+    .offset-xl-9 {
+        margin-left: 75%;
+    }
+
+    .offset-xl-10 {
+        margin-left: 83.333333%;
+    }
+
+    .offset-xl-11 {
+        margin-left: 91.666667%;
+    }
+}
+
+.d-none {
+    display: none !important;
+}
+
+.d-inline {
+    display: inline !important;
+}
+
+.d-inline-block {
+    display: inline-block !important;
+}
+
+.d-block {
+    display: block !important;
+}
+
+.d-table {
+    display: table !important;
+}
+
+.d-table-row {
+    display: table-row !important;
+}
+
+.d-table-cell {
+    display: table-cell !important;
+}
+
+.d-flex {
+    display: -ms-flexbox !important;
+    display: flex !important;
+}
+
+.d-inline-flex {
+    display: -ms-inline-flexbox !important;
+    display: inline-flex !important;
+}
+
+@media (min-width: 576px) {
+    .d-sm-none {
+        display: none !important;
+    }
+
+    .d-sm-inline {
+        display: inline !important;
+    }
+
+    .d-sm-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-sm-block {
+        display: block !important;
+    }
+
+    .d-sm-table {
+        display: table !important;
+    }
+
+    .d-sm-table-row {
+        display: table-row !important;
+    }
+
+    .d-sm-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-sm-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-sm-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 768px) {
+    .d-md-none {
+        display: none !important;
+    }
+
+    .d-md-inline {
+        display: inline !important;
+    }
+
+    .d-md-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-md-block {
+        display: block !important;
+    }
+
+    .d-md-table {
+        display: table !important;
+    }
+
+    .d-md-table-row {
+        display: table-row !important;
+    }
+
+    .d-md-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-md-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-md-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 992px) {
+    .d-lg-none {
+        display: none !important;
+    }
+
+    .d-lg-inline {
+        display: inline !important;
+    }
+
+    .d-lg-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-lg-block {
+        display: block !important;
+    }
+
+    .d-lg-table {
+        display: table !important;
+    }
+
+    .d-lg-table-row {
+        display: table-row !important;
+    }
+
+    .d-lg-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-lg-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-lg-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media (min-width: 1200px) {
+    .d-xl-none {
+        display: none !important;
+    }
+
+    .d-xl-inline {
+        display: inline !important;
+    }
+
+    .d-xl-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-xl-block {
+        display: block !important;
+    }
+
+    .d-xl-table {
+        display: table !important;
+    }
+
+    .d-xl-table-row {
+        display: table-row !important;
+    }
+
+    .d-xl-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-xl-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-xl-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+@media print {
+    .d-print-none {
+        display: none !important;
+    }
+
+    .d-print-inline {
+        display: inline !important;
+    }
+
+    .d-print-inline-block {
+        display: inline-block !important;
+    }
+
+    .d-print-block {
+        display: block !important;
+    }
+
+    .d-print-table {
+        display: table !important;
+    }
+
+    .d-print-table-row {
+        display: table-row !important;
+    }
+
+    .d-print-table-cell {
+        display: table-cell !important;
+    }
+
+    .d-print-flex {
+        display: -ms-flexbox !important;
+        display: flex !important;
+    }
+
+    .d-print-inline-flex {
+        display: -ms-inline-flexbox !important;
+        display: inline-flex !important;
+    }
+}
+
+.flex-row {
+    -ms-flex-direction: row !important;
+    flex-direction: row !important;
+}
+
+.flex-column {
+    -ms-flex-direction: column !important;
+    flex-direction: column !important;
+}
+
+.flex-row-reverse {
+    -ms-flex-direction: row-reverse !important;
+    flex-direction: row-reverse !important;
+}
+
+.flex-column-reverse {
+    -ms-flex-direction: column-reverse !important;
+    flex-direction: column-reverse !important;
+}
+
+.flex-wrap {
+    -ms-flex-wrap: wrap !important;
+    flex-wrap: wrap !important;
+}
+
+.flex-nowrap {
+    -ms-flex-wrap: nowrap !important;
+    flex-wrap: nowrap !important;
+}
+
+.flex-wrap-reverse {
+    -ms-flex-wrap: wrap-reverse !important;
+    flex-wrap: wrap-reverse !important;
+}
+
+.flex-fill {
+    -ms-flex: 1 1 auto !important;
+    flex: 1 1 auto !important;
+}
+
+.flex-grow-0 {
+    -ms-flex-positive: 0 !important;
+    flex-grow: 0 !important;
+}
+
+.flex-grow-1 {
+    -ms-flex-positive: 1 !important;
+    flex-grow: 1 !important;
+}
+
+.flex-shrink-0 {
+    -ms-flex-negative: 0 !important;
+    flex-shrink: 0 !important;
+}
+
+.flex-shrink-1 {
+    -ms-flex-negative: 1 !important;
+    flex-shrink: 1 !important;
+}
+
+.justify-content-start {
+    -ms-flex-pack: start !important;
+    justify-content: flex-start !important;
+}
+
+.justify-content-end {
+    -ms-flex-pack: end !important;
+    justify-content: flex-end !important;
+}
+
+.justify-content-center {
+    -ms-flex-pack: center !important;
+    justify-content: center !important;
+}
+
+.justify-content-between {
+    -ms-flex-pack: justify !important;
+    justify-content: space-between !important;
+}
+
+.justify-content-around {
+    -ms-flex-pack: distribute !important;
+    justify-content: space-around !important;
+}
+
+.align-items-start {
+    -ms-flex-align: start !important;
+    align-items: flex-start !important;
+}
+
+.align-items-end {
+    -ms-flex-align: end !important;
+    align-items: flex-end !important;
+}
+
+.align-items-center {
+    -ms-flex-align: center !important;
+    align-items: center !important;
+}
+
+.align-items-baseline {
+    -ms-flex-align: baseline !important;
+    align-items: baseline !important;
+}
+
+.align-items-stretch {
+    -ms-flex-align: stretch !important;
+    align-items: stretch !important;
+}
+
+.align-content-start {
+    -ms-flex-line-pack: start !important;
+    align-content: flex-start !important;
+}
+
+.align-content-end {
+    -ms-flex-line-pack: end !important;
+    align-content: flex-end !important;
+}
+
+.align-content-center {
+    -ms-flex-line-pack: center !important;
+    align-content: center !important;
+}
+
+.align-content-between {
+    -ms-flex-line-pack: justify !important;
+    align-content: space-between !important;
+}
+
+.align-content-around {
+    -ms-flex-line-pack: distribute !important;
+    align-content: space-around !important;
+}
+
+.align-content-stretch {
+    -ms-flex-line-pack: stretch !important;
+    align-content: stretch !important;
+}
+
+.align-self-auto {
+    -ms-flex-item-align: auto !important;
+    align-self: auto !important;
+}
+
+.align-self-start {
+    -ms-flex-item-align: start !important;
+    align-self: flex-start !important;
+}
+
+.align-self-end {
+    -ms-flex-item-align: end !important;
+    align-self: flex-end !important;
+}
+
+.align-self-center {
+    -ms-flex-item-align: center !important;
+    align-self: center !important;
+}
+
+.align-self-baseline {
+    -ms-flex-item-align: baseline !important;
+    align-self: baseline !important;
+}
+
+.align-self-stretch {
+    -ms-flex-item-align: stretch !important;
+    align-self: stretch !important;
+}
+
+@media (min-width: 576px) {
+    .flex-sm-row {
+        -ms-flex-direction: row !important;
+        flex-direction: row !important;
+    }
+
+    .flex-sm-column {
+        -ms-flex-direction: column !important;
+        flex-direction: column !important;
+    }
+
+    .flex-sm-row-reverse {
+        -ms-flex-direction: row-reverse !important;
+        flex-direction: row-reverse !important;
+    }
+
+    .flex-sm-column-reverse {
+        -ms-flex-direction: column-reverse !important;
+        flex-direction: column-reverse !important;
+    }
+
+    .flex-sm-wrap {
+        -ms-flex-wrap: wrap !important;
+        flex-wrap: wrap !important;
+    }
+
+    .flex-sm-nowrap {
+        -ms-flex-wrap: nowrap !important;
+        flex-wrap: nowrap !important;
+    }
+
+    .flex-sm-wrap-reverse {
+        -ms-flex-wrap: wrap-reverse !important;
+        flex-wrap: wrap-reverse !important;
+    }
+
+    .flex-sm-fill {
+        -ms-flex: 1 1 auto !important;
+        flex: 1 1 auto !important;
+    }
+
+    .flex-sm-grow-0 {
+        -ms-flex-positive: 0 !important;
+        flex-grow: 0 !important;
+    }
+
+    .flex-sm-grow-1 {
+        -ms-flex-positive: 1 !important;
+        flex-grow: 1 !important;
+…

Jlteka added a commit to Jlteka/DoubleGisIntegration that referenced this pull request Apr 4, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (github/gitignore#2483 (comment))
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (github/gitignore#1529 (comment))
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git a/DoubleGisIntegration.sln b/DoubleGisIntegration.sln
new file mode 100644
index 0000000..c348434
--- /dev/null
+++ b/DoubleGisIntegration.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubleGisIntegration", "DoubleGisIntegration\DoubleGisIntegration.csproj", "{582F4B1A-7852-43D8-9A20-BBA865B01C72}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git a/DoubleGisIntegration/Controllers/HomeController.cs b/DoubleGisIntegration/Controllers/HomeController.cs
new file mode 100644
index 0000000..bfabcfb
--- /dev/null
+++ b/DoubleGisIntegration/Controllers/HomeController.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using DoubleGisIntegration.Models;
+using DoubleGisIntegration.Models.DTO;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using CarRouting.Models;
+
+
+namespace DoubleGisIntegration.Controllers
+{
+    public class HomeController : Controller
+    {
+        private const string URL = "http://catalog.api.2gis.ru/carrouting/4.0.0/{0}/?key={1}";
+        private const string City = "spb";
+        private const string ApiKey = "rupxwv7450";
+
+        private Uri BuildUri(string city, string key) => new Uri(string.Format(URL, city, key));
+
+        private readonly HttpClient _httpClient;
+
+        private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings()
+        {
+            ContractResolver = new CamelCasePropertyNamesContractResolver(),
+            NullValueHandling = NullValueHandling.Include
+        };
+
+        public HomeController(IHttpClientFactory factory)
+        {
+            _httpClient = factory.CreateClient();
+        }
+
+        [HttpGet]
+        public IActionResult Index()
+        {
+            var data = new ApiResponse(8, "Пустое тело запроса", null);
+            return Json(data, _serializerSettings);
+        }
+
+        [HttpPost]
+        public async Task<IActionResult> Index([FromBody] CarRoutingRequest request)
+        {
+            CarResponseInfo nearestCar = null;
+            var statusCode = 0;
+            var statusDescription = "Everything is OK";
+            try
+            {
+                var cars = await GetCarsInfo(request);
+                nearestCar = cars
+                    .Where(thisCar => thisCar.DistanceInMeters <= 2000)
+                    .OrderBy(thisCar => thisCar.TimeInSeconds)
+                    .FirstOrDefault();
+                if (nearestCar == null)
+                {
+                    throw new CarRoutingException(5, "Нет подходящих машин");
+                }
+            }
+
+            catch (CarRoutingException exception)
+            {
+                statusCode = exception.ErrorCode;
+                statusDescription = exception.ToString();
+            }
+
+            catch (Exception)
+            {
+                statusCode = -1;
+                statusDescription = "Неизвестная ошибка";
+            }
+
+            var data = new ApiResponse(statusCode, statusDescription, nearestCar);
+            return Json(data, _serializerSettings);
+
+        }
+
+        private async Task<List<CarResponseInfo>> GetCarsInfo(CarRoutingRequest request)
+        {
+            var cars = new List<CarResponseInfo>();
+            foreach (var car in request.Cars)
+            {
+                cars.Add(await MapToCarResponseInfo(request, car));
+            }
+            return cars;
+        }
+
+        private async Task<CarResponseInfo> MapToCarResponseInfo(CarRoutingRequest request, Car car)
+        {
+            var url = BuildUri(City, ApiKey);
+            var query = new CarRoutingQuery(car.Position, request.Destination);
+            var json = JsonConvert.SerializeObject(query, _serializerSettings);
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+            var response = await _httpClient.PostAsync(url, content);
+            if (response.IsSuccessStatusCode)
+            {
+                if (response.StatusCode == HttpStatusCode.OK)
+                {
+                    var responseText = await response.Content.ReadAsStringAsync();
+                    try
+                    {
+                        var responseObject = JsonConvert.DeserializeObject<CarRoutingQueryResult>(responseText);
+                        var result = responseObject.Result.First();
+                        return new CarResponseInfo(car.Id, result.Total_distance, result.Total_duration);
+                    }
+                    catch (Exception)
+                    {
+                        throw new CarRoutingException(1, "Не смогли представить в виде объекта.");//200 но дерьмо
+                    }
+                }
+                else if (response.StatusCode == HttpStatusCode.NoContent)
+                {
+                    throw new CarRoutingException(2, "В спб нет такого адреса.");//204
+                }
+                else
+                {
+                    throw new CarRoutingException(3, "Все ок, но вернули какую-то ебань.");// !200 !204
+                }
+            }
+            else
+            {
+                throw new CarRoutingException(4, "Гис сломался");//4xx 5xx
+            }
+        }
+
+    }
+}
diff --git a/DoubleGisIntegration/DoubleGisIntegration.csproj b/DoubleGisIntegration/DoubleGisIntegration.csproj
new file mode 100644
index 0000000..e63edfd
--- /dev/null
+++ b/DoubleGisIntegration/DoubleGisIntegration.csproj
@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.2</TargetFramework>
+    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
+  </PropertyGroup>
+
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.App" />
+    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Models\" />
+    <Folder Include="Models\DTO\" />
+  </ItemGroup>
+</Project>
diff --git a/DoubleGisIntegration/Models/ApiResponse.cs b/DoubleGisIntegration/Models/ApiResponse.cs
new file mode 100644
index 0000000..025aa0d
--- /dev/null
+++ b/DoubleGisIntegration/Models/ApiResponse.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class ApiResponse
+    {
+        public int StatusCode { get; }
+        public string StatusDescription { get; }
+        public CarResponseInfo Data { get; }
+
+        public ApiResponse(int statusCode, string statusDescription, CarResponseInfo data)
+        {
+            StatusCode = statusCode;
+            StatusDescription = statusDescription;
+            Data = data;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/Car.cs b/DoubleGisIntegration/Models/Car.cs
new file mode 100644
index 0000000..7f9d1c8
--- /dev/null
+++ b/DoubleGisIntegration/Models/Car.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class Car
+    {
+        public int Id { get; set; }
+        public GeoCoordinates Position { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarResponseInfo.cs b/DoubleGisIntegration/Models/CarResponseInfo.cs
new file mode 100644
index 0000000..aa6c63a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarResponseInfo.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class CarResponseInfo
+    {
+        public int ClosestCar { get; set; }
+        public int DistanceInMeters { get; set; }
+        public int TimeInSeconds { get; set; }
+
+        public CarResponseInfo (int closestCar, int distanceInMeters, int timeInSeconds)
+        {
+            ClosestCar = closestCar;
+            DistanceInMeters = distanceInMeters;
+            TimeInSeconds = timeInSeconds;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarRoutingException.cs b/DoubleGisIntegration/Models/CarRoutingException.cs
new file mode 100644
index 0000000..02dce60
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingException.cs
@@ -0,0 +1,14 @@
+namespace CarRouting.Models {
+    public class CarRoutingException : System.Exception {
+        public CarRoutingException(int errorCode, string message) {
+            Message = message;
+            ErrorCode = errorCode;
+        }
+        public int ErrorCode { get; set; }
+        public override string Message { get; }
+
+        public override string ToString() {
+            return $"Ошибка {ErrorCode}: {Message}";
+        }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/CarRoutingRequest.cs b/DoubleGisIntegration/Models/CarRoutingRequest.cs
new file mode 100644
index 0000000..a6bd22a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingRequest.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models
+{
+    public class CarRoutingRequest
+    {
+        public GeoCoordinates Destination { get; set; }
+        public IEnumerable<Car> Cars { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
new file mode 100644
index 0000000..97e7efd
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQuery
+    {
+        public string Locale { get; set; }
+        public string Point_a_name { get; set; }
+        public string Point_b_name { get; set; }
+        public List<GisCoordinate> Points { get; set; }
+        public string Type { get; set; }
+
+        public CarRoutingQuery(GeoCoordinates destination, GeoCoordinates carCoordinates)
+        {
+            Locale = "ru";
+            Point_a_name = null;
+            Point_b_name = null;
+            Type = "jam";
+
+            Points = new List<GisCoordinate>
+            {
+                new GisCoordinate(carCoordinates),
+                new GisCoordinate(destination)
+            };
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
new file mode 100644
index 0000000..12ea9f0
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQueryResult
+    {
+        public IEnumerable<QueryResultInner> Result { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/GisCoordinate.cs b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
new file mode 100644
index 0000000..adbb413
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class GisCoordinate
+    {
+        public string Type { get; set; }
+        public double X { get; set; }
+        public double Y { get; set; }
+
+        public GisCoordinate(GeoCoordinates coords)
+        {
+            Type = "pedo";
+            X = coords.Lng;
+            Y = coords.Lat;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/QueryResultInner.cs b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
new file mode 100644
index 0000000..cc92021
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
@@ -0,0 +1,9 @@
+using System;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class QueryResultInner
+    {
+        public int Total_distance { get; set; }
+        public int Total_duration { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/ErrorViewModel.cs b/DoubleGisIntegration/Models/ErrorViewModel.cs
new file mode 100644
index 0000000..33776b9
--- /dev/null
+++ b/DoubleGisIntegration/Models/ErrorViewModel.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace DoubleGisIntegration.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/GeoCoordinates.cs b/DoubleGisIntegration/Models/GeoCoordinates.cs
new file mode 100644
index 0000000..fde222f
--- /dev/null
+++ b/DoubleGisIntegration/Models/GeoCoordinates.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class GeoCoordinates
+    {
+        public double Lat { get; set; }
+        public double Lng { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Program.cs b/DoubleGisIntegration/Program.cs
new file mode 100644
index 0000000..7a790bc
--- /dev/null
+++ b/DoubleGisIntegration/Program.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace DoubleGisIntegration
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateWebHostBuilder(args).Build().Run();
+        }
+
+        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
+                .UseStartup<Startup>();
+    }
+}
diff --git a/DoubleGisIntegration/Properties/launchSettings.json b/DoubleGisIntegration/Properties/launchSettings.json
new file mode 100644
index 0000000..a330472
--- /dev/null
+++ b/DoubleGisIntegration/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:55659",
+      "sslPort": 44383
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "DoubleGisIntegration": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Startup.cs b/DoubleGisIntegration/Startup.cs
new file mode 100644
index 0000000..67861a7
--- /dev/null
+++ b/DoubleGisIntegration/Startup.cs
@@ -0,0 +1,36 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DoubleGisIntegration
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+            services.AddHttpClient();
+        }
+
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            app.UseDeveloperExceptionPage();
+
+            app.UseMvc(routes =>
+            {
+                routes.MapRoute(
+                    name: "default",
+                    template: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}
diff --git a/DoubleGisIntegration/appsettings.Development.json b/DoubleGisIntegration/appsettings.Development.json
new file mode 100644
index 0000000..a2880cb
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git a/DoubleGisIntegration/appsettings.json b/DoubleGisIntegration/appsettings.json
new file mode 100644
index 0000000..7376aad
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.json
@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+}

Jlteka added a commit to Jlteka/DoubleGisIntegration that referenced this pull request Apr 4, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (github/gitignore#2483 (comment))
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (github/gitignore#1529 (comment))
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git a/DoubleGisIntegration.sln b/DoubleGisIntegration.sln
new file mode 100644
index 0000000..c348434
--- /dev/null
+++ b/DoubleGisIntegration.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubleGisIntegration", "DoubleGisIntegration\DoubleGisIntegration.csproj", "{582F4B1A-7852-43D8-9A20-BBA865B01C72}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git a/DoubleGisIntegration/Controllers/HomeController.cs b/DoubleGisIntegration/Controllers/HomeController.cs
new file mode 100644
index 0000000..bfabcfb
--- /dev/null
+++ b/DoubleGisIntegration/Controllers/HomeController.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using DoubleGisIntegration.Models;
+using DoubleGisIntegration.Models.DTO;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using CarRouting.Models;
+
+
+namespace DoubleGisIntegration.Controllers
+{
+    public class HomeController : Controller
+    {
+        private const string URL = "http://catalog.api.2gis.ru/carrouting/4.0.0/{0}/?key={1}";
+        private const string City = "spb";
+        private const string ApiKey = "rupxwv7450";
+
+        private Uri BuildUri(string city, string key) => new Uri(string.Format(URL, city, key));
+
+        private readonly HttpClient _httpClient;
+
+        private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings()
+        {
+            ContractResolver = new CamelCasePropertyNamesContractResolver(),
+            NullValueHandling = NullValueHandling.Include
+        };
+
+        public HomeController(IHttpClientFactory factory)
+        {
+            _httpClient = factory.CreateClient();
+        }
+
+        [HttpGet]
+        public IActionResult Index()
+        {
+            var data = new ApiResponse(8, "Пустое тело запроса", null);
+            return Json(data, _serializerSettings);
+        }
+
+        [HttpPost]
+        public async Task<IActionResult> Index([FromBody] CarRoutingRequest request)
+        {
+            CarResponseInfo nearestCar = null;
+            var statusCode = 0;
+            var statusDescription = "Everything is OK";
+            try
+            {
+                var cars = await GetCarsInfo(request);
+                nearestCar = cars
+                    .Where(thisCar => thisCar.DistanceInMeters <= 2000)
+                    .OrderBy(thisCar => thisCar.TimeInSeconds)
+                    .FirstOrDefault();
+                if (nearestCar == null)
+                {
+                    throw new CarRoutingException(5, "Нет подходящих машин");
+                }
+            }
+
+            catch (CarRoutingException exception)
+            {
+                statusCode = exception.ErrorCode;
+                statusDescription = exception.ToString();
+            }
+
+            catch (Exception)
+            {
+                statusCode = -1;
+                statusDescription = "Неизвестная ошибка";
+            }
+
+            var data = new ApiResponse(statusCode, statusDescription, nearestCar);
+            return Json(data, _serializerSettings);
+
+        }
+
+        private async Task<List<CarResponseInfo>> GetCarsInfo(CarRoutingRequest request)
+        {
+            var cars = new List<CarResponseInfo>();
+            foreach (var car in request.Cars)
+            {
+                cars.Add(await MapToCarResponseInfo(request, car));
+            }
+            return cars;
+        }
+
+        private async Task<CarResponseInfo> MapToCarResponseInfo(CarRoutingRequest request, Car car)
+        {
+            var url = BuildUri(City, ApiKey);
+            var query = new CarRoutingQuery(car.Position, request.Destination);
+            var json = JsonConvert.SerializeObject(query, _serializerSettings);
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+            var response = await _httpClient.PostAsync(url, content);
+            if (response.IsSuccessStatusCode)
+            {
+                if (response.StatusCode == HttpStatusCode.OK)
+                {
+                    var responseText = await response.Content.ReadAsStringAsync();
+                    try
+                    {
+                        var responseObject = JsonConvert.DeserializeObject<CarRoutingQueryResult>(responseText);
+                        var result = responseObject.Result.First();
+                        return new CarResponseInfo(car.Id, result.Total_distance, result.Total_duration);
+                    }
+                    catch (Exception)
+                    {
+                        throw new CarRoutingException(1, "Не смогли представить в виде объекта.");//200 но дерьмо
+                    }
+                }
+                else if (response.StatusCode == HttpStatusCode.NoContent)
+                {
+                    throw new CarRoutingException(2, "В спб нет такого адреса.");//204
+                }
+                else
+                {
+                    throw new CarRoutingException(3, "Все ок, но вернули какую-то ебань.");// !200 !204
+                }
+            }
+            else
+            {
+                throw new CarRoutingException(4, "Гис сломался");//4xx 5xx
+            }
+        }
+
+    }
+}
diff --git a/DoubleGisIntegration/DoubleGisIntegration.csproj b/DoubleGisIntegration/DoubleGisIntegration.csproj
new file mode 100644
index 0000000..e63edfd
--- /dev/null
+++ b/DoubleGisIntegration/DoubleGisIntegration.csproj
@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.2</TargetFramework>
+    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
+  </PropertyGroup>
+
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.App" />
+    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Models\" />
+    <Folder Include="Models\DTO\" />
+  </ItemGroup>
+</Project>
diff --git a/DoubleGisIntegration/Models/ApiResponse.cs b/DoubleGisIntegration/Models/ApiResponse.cs
new file mode 100644
index 0000000..025aa0d
--- /dev/null
+++ b/DoubleGisIntegration/Models/ApiResponse.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class ApiResponse
+    {
+        public int StatusCode { get; }
+        public string StatusDescription { get; }
+        public CarResponseInfo Data { get; }
+
+        public ApiResponse(int statusCode, string statusDescription, CarResponseInfo data)
+        {
+            StatusCode = statusCode;
+            StatusDescription = statusDescription;
+            Data = data;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/Car.cs b/DoubleGisIntegration/Models/Car.cs
new file mode 100644
index 0000000..7f9d1c8
--- /dev/null
+++ b/DoubleGisIntegration/Models/Car.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class Car
+    {
+        public int Id { get; set; }
+        public GeoCoordinates Position { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarResponseInfo.cs b/DoubleGisIntegration/Models/CarResponseInfo.cs
new file mode 100644
index 0000000..aa6c63a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarResponseInfo.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class CarResponseInfo
+    {
+        public int ClosestCar { get; set; }
+        public int DistanceInMeters { get; set; }
+        public int TimeInSeconds { get; set; }
+
+        public CarResponseInfo (int closestCar, int distanceInMeters, int timeInSeconds)
+        {
+            ClosestCar = closestCar;
+            DistanceInMeters = distanceInMeters;
+            TimeInSeconds = timeInSeconds;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarRoutingException.cs b/DoubleGisIntegration/Models/CarRoutingException.cs
new file mode 100644
index 0000000..02dce60
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingException.cs
@@ -0,0 +1,14 @@
+namespace CarRouting.Models {
+    public class CarRoutingException : System.Exception {
+        public CarRoutingException(int errorCode, string message) {
+            Message = message;
+            ErrorCode = errorCode;
+        }
+        public int ErrorCode { get; set; }
+        public override string Message { get; }
+
+        public override string ToString() {
+            return $"Ошибка {ErrorCode}: {Message}";
+        }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/CarRoutingRequest.cs b/DoubleGisIntegration/Models/CarRoutingRequest.cs
new file mode 100644
index 0000000..a6bd22a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingRequest.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models
+{
+    public class CarRoutingRequest
+    {
+        public GeoCoordinates Destination { get; set; }
+        public IEnumerable<Car> Cars { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
new file mode 100644
index 0000000..97e7efd
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQuery
+    {
+        public string Locale { get; set; }
+        public string Point_a_name { get; set; }
+        public string Point_b_name { get; set; }
+        public List<GisCoordinate> Points { get; set; }
+        public string Type { get; set; }
+
+        public CarRoutingQuery(GeoCoordinates destination, GeoCoordinates carCoordinates)
+        {
+            Locale = "ru";
+            Point_a_name = null;
+            Point_b_name = null;
+            Type = "jam";
+
+            Points = new List<GisCoordinate>
+            {
+                new GisCoordinate(carCoordinates),
+                new GisCoordinate(destination)
+            };
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
new file mode 100644
index 0000000..12ea9f0
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQueryResult
+    {
+        public IEnumerable<QueryResultInner> Result { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/GisCoordinate.cs b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
new file mode 100644
index 0000000..adbb413
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class GisCoordinate
+    {
+        public string Type { get; set; }
+        public double X { get; set; }
+        public double Y { get; set; }
+
+        public GisCoordinate(GeoCoordinates coords)
+        {
+            Type = "pedo";
+            X = coords.Lng;
+            Y = coords.Lat;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/QueryResultInner.cs b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
new file mode 100644
index 0000000..cc92021
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
@@ -0,0 +1,9 @@
+using System;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class QueryResultInner
+    {
+        public int Total_distance { get; set; }
+        public int Total_duration { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/ErrorViewModel.cs b/DoubleGisIntegration/Models/ErrorViewModel.cs
new file mode 100644
index 0000000..33776b9
--- /dev/null
+++ b/DoubleGisIntegration/Models/ErrorViewModel.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace DoubleGisIntegration.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/GeoCoordinates.cs b/DoubleGisIntegration/Models/GeoCoordinates.cs
new file mode 100644
index 0000000..fde222f
--- /dev/null
+++ b/DoubleGisIntegration/Models/GeoCoordinates.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class GeoCoordinates
+    {
+        public double Lat { get; set; }
+        public double Lng { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Program.cs b/DoubleGisIntegration/Program.cs
new file mode 100644
index 0000000..7a790bc
--- /dev/null
+++ b/DoubleGisIntegration/Program.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace DoubleGisIntegration
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateWebHostBuilder(args).Build().Run();
+        }
+
+        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
+                .UseStartup<Startup>();
+    }
+}
diff --git a/DoubleGisIntegration/Properties/launchSettings.json b/DoubleGisIntegration/Properties/launchSettings.json
new file mode 100644
index 0000000..a330472
--- /dev/null
+++ b/DoubleGisIntegration/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:55659",
+      "sslPort": 44383
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "DoubleGisIntegration": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Startup.cs b/DoubleGisIntegration/Startup.cs
new file mode 100644
index 0000000..67861a7
--- /dev/null
+++ b/DoubleGisIntegration/Startup.cs
@@ -0,0 +1,36 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DoubleGisIntegration
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+            services.AddHttpClient();
+        }
+
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            app.UseDeveloperExceptionPage();
+
+            app.UseMvc(routes =>
+            {
+                routes.MapRoute(
+                    name: "default",
+                    template: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}
diff --git a/DoubleGisIntegration/appsettings.Development.json b/DoubleGisIntegration/appsettings.Development.json
new file mode 100644
index 0000000..a2880cb
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git a/DoubleGisIntegration/appsettings.json b/DoubleGisIntegration/appsettings.json
new file mode 100644
index 0000000..7376aad
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.json
@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+}

Jlteka added a commit to Jlteka/DoubleGisIntegration that referenced this pull request Apr 4, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (github/gitignore#2483 (comment))
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (github/gitignore#1529 (comment))
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git a/DoubleGisIntegration.sln b/DoubleGisIntegration.sln
new file mode 100644
index 0000000..c348434
--- /dev/null
+++ b/DoubleGisIntegration.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubleGisIntegration", "DoubleGisIntegration\DoubleGisIntegration.csproj", "{582F4B1A-7852-43D8-9A20-BBA865B01C72}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git a/DoubleGisIntegration/Controllers/HomeController.cs b/DoubleGisIntegration/Controllers/HomeController.cs
new file mode 100644
index 0000000..bfabcfb
--- /dev/null
+++ b/DoubleGisIntegration/Controllers/HomeController.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using DoubleGisIntegration.Models;
+using DoubleGisIntegration.Models.DTO;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using CarRouting.Models;
+
+
+namespace DoubleGisIntegration.Controllers
+{
+    public class HomeController : Controller
+    {
+        private const string URL = "http://catalog.api.2gis.ru/carrouting/4.0.0/{0}/?key={1}";
+        private const string City = "spb";
+        private const string ApiKey = "rupxwv7450";
+
+        private Uri BuildUri(string city, string key) => new Uri(string.Format(URL, city, key));
+
+        private readonly HttpClient _httpClient;
+
+        private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings()
+        {
+            ContractResolver = new CamelCasePropertyNamesContractResolver(),
+            NullValueHandling = NullValueHandling.Include
+        };
+
+        public HomeController(IHttpClientFactory factory)
+        {
+            _httpClient = factory.CreateClient();
+        }
+
+        [HttpGet]
+        public IActionResult Index()
+        {
+            var data = new ApiResponse(8, "Пустое тело запроса", null);
+            return Json(data, _serializerSettings);
+        }
+
+        [HttpPost]
+        public async Task<IActionResult> Index([FromBody] CarRoutingRequest request)
+        {
+            CarResponseInfo nearestCar = null;
+            var statusCode = 0;
+            var statusDescription = "Everything is OK";
+            try
+            {
+                var cars = await GetCarsInfo(request);
+                nearestCar = cars
+                    .Where(thisCar => thisCar.DistanceInMeters <= 2000)
+                    .OrderBy(thisCar => thisCar.TimeInSeconds)
+                    .FirstOrDefault();
+                if (nearestCar == null)
+                {
+                    throw new CarRoutingException(5, "Нет подходящих машин");
+                }
+            }
+
+            catch (CarRoutingException exception)
+            {
+                statusCode = exception.ErrorCode;
+                statusDescription = exception.ToString();
+            }
+
+            catch (Exception)
+            {
+                statusCode = -1;
+                statusDescription = "Неизвестная ошибка";
+            }
+
+            var data = new ApiResponse(statusCode, statusDescription, nearestCar);
+            return Json(data, _serializerSettings);
+
+        }
+
+        private async Task<List<CarResponseInfo>> GetCarsInfo(CarRoutingRequest request)
+        {
+            var cars = new List<CarResponseInfo>();
+            foreach (var car in request.Cars)
+            {
+                cars.Add(await MapToCarResponseInfo(request, car));
+            }
+            return cars;
+        }
+
+        private async Task<CarResponseInfo> MapToCarResponseInfo(CarRoutingRequest request, Car car)
+        {
+            var url = BuildUri(City, ApiKey);
+            var query = new CarRoutingQuery(car.Position, request.Destination);
+            var json = JsonConvert.SerializeObject(query, _serializerSettings);
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+            var response = await _httpClient.PostAsync(url, content);
+            if (response.IsSuccessStatusCode)
+            {
+                if (response.StatusCode == HttpStatusCode.OK)
+                {
+                    var responseText = await response.Content.ReadAsStringAsync();
+                    try
+                    {
+                        var responseObject = JsonConvert.DeserializeObject<CarRoutingQueryResult>(responseText);
+                        var result = responseObject.Result.First();
+                        return new CarResponseInfo(car.Id, result.Total_distance, result.Total_duration);
+                    }
+                    catch (Exception)
+                    {
+                        throw new CarRoutingException(1, "Не смогли представить в виде объекта.");//200 но дерьмо
+                    }
+                }
+                else if (response.StatusCode == HttpStatusCode.NoContent)
+                {
+                    throw new CarRoutingException(2, "В спб нет такого адреса.");//204
+                }
+                else
+                {
+                    throw new CarRoutingException(3, "Все ок, но вернули какую-то ебань.");// !200 !204
+                }
+            }
+            else
+            {
+                throw new CarRoutingException(4, "Гис сломался");//4xx 5xx
+            }
+        }
+
+    }
+}
diff --git a/DoubleGisIntegration/DoubleGisIntegration.csproj b/DoubleGisIntegration/DoubleGisIntegration.csproj
new file mode 100644
index 0000000..e63edfd
--- /dev/null
+++ b/DoubleGisIntegration/DoubleGisIntegration.csproj
@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.2</TargetFramework>
+    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
+  </PropertyGroup>
+
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.App" />
+    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Models\" />
+    <Folder Include="Models\DTO\" />
+  </ItemGroup>
+</Project>
diff --git a/DoubleGisIntegration/Models/ApiResponse.cs b/DoubleGisIntegration/Models/ApiResponse.cs
new file mode 100644
index 0000000..025aa0d
--- /dev/null
+++ b/DoubleGisIntegration/Models/ApiResponse.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class ApiResponse
+    {
+        public int StatusCode { get; }
+        public string StatusDescription { get; }
+        public CarResponseInfo Data { get; }
+
+        public ApiResponse(int statusCode, string statusDescription, CarResponseInfo data)
+        {
+            StatusCode = statusCode;
+            StatusDescription = statusDescription;
+            Data = data;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/Car.cs b/DoubleGisIntegration/Models/Car.cs
new file mode 100644
index 0000000..7f9d1c8
--- /dev/null
+++ b/DoubleGisIntegration/Models/Car.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class Car
+    {
+        public int Id { get; set; }
+        public GeoCoordinates Position { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarResponseInfo.cs b/DoubleGisIntegration/Models/CarResponseInfo.cs
new file mode 100644
index 0000000..aa6c63a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarResponseInfo.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class CarResponseInfo
+    {
+        public int ClosestCar { get; set; }
+        public int DistanceInMeters { get; set; }
+        public int TimeInSeconds { get; set; }
+
+        public CarResponseInfo (int closestCar, int distanceInMeters, int timeInSeconds)
+        {
+            ClosestCar = closestCar;
+            DistanceInMeters = distanceInMeters;
+            TimeInSeconds = timeInSeconds;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarRoutingException.cs b/DoubleGisIntegration/Models/CarRoutingException.cs
new file mode 100644
index 0000000..02dce60
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingException.cs
@@ -0,0 +1,14 @@
+namespace CarRouting.Models {
+    public class CarRoutingException : System.Exception {
+        public CarRoutingException(int errorCode, string message) {
+            Message = message;
+            ErrorCode = errorCode;
+        }
+        public int ErrorCode { get; set; }
+        public override string Message { get; }
+
+        public override string ToString() {
+            return $"Ошибка {ErrorCode}: {Message}";
+        }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/CarRoutingRequest.cs b/DoubleGisIntegration/Models/CarRoutingRequest.cs
new file mode 100644
index 0000000..a6bd22a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingRequest.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models
+{
+    public class CarRoutingRequest
+    {
+        public GeoCoordinates Destination { get; set; }
+        public IEnumerable<Car> Cars { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
new file mode 100644
index 0000000..97e7efd
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQuery
+    {
+        public string Locale { get; set; }
+        public string Point_a_name { get; set; }
+        public string Point_b_name { get; set; }
+        public List<GisCoordinate> Points { get; set; }
+        public string Type { get; set; }
+
+        public CarRoutingQuery(GeoCoordinates destination, GeoCoordinates carCoordinates)
+        {
+            Locale = "ru";
+            Point_a_name = null;
+            Point_b_name = null;
+            Type = "jam";
+
+            Points = new List<GisCoordinate>
+            {
+                new GisCoordinate(carCoordinates),
+                new GisCoordinate(destination)
+            };
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
new file mode 100644
index 0000000..12ea9f0
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQueryResult
+    {
+        public IEnumerable<QueryResultInner> Result { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/GisCoordinate.cs b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
new file mode 100644
index 0000000..adbb413
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class GisCoordinate
+    {
+        public string Type { get; set; }
+        public double X { get; set; }
+        public double Y { get; set; }
+
+        public GisCoordinate(GeoCoordinates coords)
+        {
+            Type = "pedo";
+            X = coords.Lng;
+            Y = coords.Lat;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/QueryResultInner.cs b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
new file mode 100644
index 0000000..cc92021
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
@@ -0,0 +1,9 @@
+using System;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class QueryResultInner
+    {
+        public int Total_distance { get; set; }
+        public int Total_duration { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/ErrorViewModel.cs b/DoubleGisIntegration/Models/ErrorViewModel.cs
new file mode 100644
index 0000000..33776b9
--- /dev/null
+++ b/DoubleGisIntegration/Models/ErrorViewModel.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace DoubleGisIntegration.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/GeoCoordinates.cs b/DoubleGisIntegration/Models/GeoCoordinates.cs
new file mode 100644
index 0000000..fde222f
--- /dev/null
+++ b/DoubleGisIntegration/Models/GeoCoordinates.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class GeoCoordinates
+    {
+        public double Lat { get; set; }
+        public double Lng { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Program.cs b/DoubleGisIntegration/Program.cs
new file mode 100644
index 0000000..7a790bc
--- /dev/null
+++ b/DoubleGisIntegration/Program.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace DoubleGisIntegration
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateWebHostBuilder(args).Build().Run();
+        }
+
+        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
+                .UseStartup<Startup>();
+    }
+}
diff --git a/DoubleGisIntegration/Properties/launchSettings.json b/DoubleGisIntegration/Properties/launchSettings.json
new file mode 100644
index 0000000..a330472
--- /dev/null
+++ b/DoubleGisIntegration/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:55659",
+      "sslPort": 44383
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "DoubleGisIntegration": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Startup.cs b/DoubleGisIntegration/Startup.cs
new file mode 100644
index 0000000..67861a7
--- /dev/null
+++ b/DoubleGisIntegration/Startup.cs
@@ -0,0 +1,36 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DoubleGisIntegration
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+            services.AddHttpClient();
+        }
+
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            app.UseDeveloperExceptionPage();
+
+            app.UseMvc(routes =>
+            {
+                routes.MapRoute(
+                    name: "default",
+                    template: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}
diff --git a/DoubleGisIntegration/appsettings.Development.json b/DoubleGisIntegration/appsettings.Development.json
new file mode 100644
index 0000000..a2880cb
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git a/DoubleGisIntegration/appsettings.json b/DoubleGisIntegration/appsettings.json
new file mode 100644
index 0000000..7376aad
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.json
@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+}

Jlteka added a commit to Jlteka/DoubleGisIntegration that referenced this pull request Apr 4, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (github/gitignore#2483 (comment))
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (github/gitignore#1529 (comment))
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git a/DoubleGisIntegration.sln b/DoubleGisIntegration.sln
new file mode 100644
index 0000000..c348434
--- /dev/null
+++ b/DoubleGisIntegration.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubleGisIntegration", "DoubleGisIntegration\DoubleGisIntegration.csproj", "{582F4B1A-7852-43D8-9A20-BBA865B01C72}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git a/DoubleGisIntegration/Controllers/HomeController.cs b/DoubleGisIntegration/Controllers/HomeController.cs
new file mode 100644
index 0000000..bfabcfb
--- /dev/null
+++ b/DoubleGisIntegration/Controllers/HomeController.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using DoubleGisIntegration.Models;
+using DoubleGisIntegration.Models.DTO;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using CarRouting.Models;
+
+
+namespace DoubleGisIntegration.Controllers
+{
+    public class HomeController : Controller
+    {
+        private const string URL = "http://catalog.api.2gis.ru/carrouting/4.0.0/{0}/?key={1}";
+        private const string City = "spb";
+        private const string ApiKey = "rupxwv7450";
+
+        private Uri BuildUri(string city, string key) => new Uri(string.Format(URL, city, key));
+
+        private readonly HttpClient _httpClient;
+
+        private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings()
+        {
+            ContractResolver = new CamelCasePropertyNamesContractResolver(),
+            NullValueHandling = NullValueHandling.Include
+        };
+
+        public HomeController(IHttpClientFactory factory)
+        {
+            _httpClient = factory.CreateClient();
+        }
+
+        [HttpGet]
+        public IActionResult Index()
+        {
+            var data = new ApiResponse(8, "Пустое тело запроса", null);
+            return Json(data, _serializerSettings);
+        }
+
+        [HttpPost]
+        public async Task<IActionResult> Index([FromBody] CarRoutingRequest request)
+        {
+            CarResponseInfo nearestCar = null;
+            var statusCode = 0;
+            var statusDescription = "Everything is OK";
+            try
+            {
+                var cars = await GetCarsInfo(request);
+                nearestCar = cars
+                    .Where(thisCar => thisCar.DistanceInMeters <= 2000)
+                    .OrderBy(thisCar => thisCar.TimeInSeconds)
+                    .FirstOrDefault();
+                if (nearestCar == null)
+                {
+                    throw new CarRoutingException(5, "Нет подходящих машин");
+                }
+            }
+
+            catch (CarRoutingException exception)
+            {
+                statusCode = exception.ErrorCode;
+                statusDescription = exception.ToString();
+            }
+
+            catch (Exception)
+            {
+                statusCode = -1;
+                statusDescription = "Неизвестная ошибка";
+            }
+
+            var data = new ApiResponse(statusCode, statusDescription, nearestCar);
+            return Json(data, _serializerSettings);
+
+        }
+
+        private async Task<List<CarResponseInfo>> GetCarsInfo(CarRoutingRequest request)
+        {
+            var cars = new List<CarResponseInfo>();
+            foreach (var car in request.Cars)
+            {
+                cars.Add(await MapToCarResponseInfo(request, car));
+            }
+            return cars;
+        }
+
+        private async Task<CarResponseInfo> MapToCarResponseInfo(CarRoutingRequest request, Car car)
+        {
+            var url = BuildUri(City, ApiKey);
+            var query = new CarRoutingQuery(car.Position, request.Destination);
+            var json = JsonConvert.SerializeObject(query, _serializerSettings);
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+            var response = await _httpClient.PostAsync(url, content);
+            if (response.IsSuccessStatusCode)
+            {
+                if (response.StatusCode == HttpStatusCode.OK)
+                {
+                    var responseText = await response.Content.ReadAsStringAsync();
+                    try
+                    {
+                        var responseObject = JsonConvert.DeserializeObject<CarRoutingQueryResult>(responseText);
+                        var result = responseObject.Result.First();
+                        return new CarResponseInfo(car.Id, result.Total_distance, result.Total_duration);
+                    }
+                    catch (Exception)
+                    {
+                        throw new CarRoutingException(1, "Не смогли представить в виде объекта.");//200 но дерьмо
+                    }
+                }
+                else if (response.StatusCode == HttpStatusCode.NoContent)
+                {
+                    throw new CarRoutingException(2, "В спб нет такого адреса.");//204
+                }
+                else
+                {
+                    throw new CarRoutingException(3, "Все ок, но вернули какую-то ебань.");// !200 !204
+                }
+            }
+            else
+            {
+                throw new CarRoutingException(4, "Гис сломался");//4xx 5xx
+            }
+        }
+
+    }
+}
diff --git a/DoubleGisIntegration/DoubleGisIntegration.csproj b/DoubleGisIntegration/DoubleGisIntegration.csproj
new file mode 100644
index 0000000..e63edfd
--- /dev/null
+++ b/DoubleGisIntegration/DoubleGisIntegration.csproj
@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.2</TargetFramework>
+    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
+  </PropertyGroup>
+
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.App" />
+    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Models\" />
+    <Folder Include="Models\DTO\" />
+  </ItemGroup>
+</Project>
diff --git a/DoubleGisIntegration/Models/ApiResponse.cs b/DoubleGisIntegration/Models/ApiResponse.cs
new file mode 100644
index 0000000..025aa0d
--- /dev/null
+++ b/DoubleGisIntegration/Models/ApiResponse.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class ApiResponse
+    {
+        public int StatusCode { get; }
+        public string StatusDescription { get; }
+        public CarResponseInfo Data { get; }
+
+        public ApiResponse(int statusCode, string statusDescription, CarResponseInfo data)
+        {
+            StatusCode = statusCode;
+            StatusDescription = statusDescription;
+            Data = data;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/Car.cs b/DoubleGisIntegration/Models/Car.cs
new file mode 100644
index 0000000..7f9d1c8
--- /dev/null
+++ b/DoubleGisIntegration/Models/Car.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class Car
+    {
+        public int Id { get; set; }
+        public GeoCoordinates Position { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarResponseInfo.cs b/DoubleGisIntegration/Models/CarResponseInfo.cs
new file mode 100644
index 0000000..aa6c63a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarResponseInfo.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models
+{
+    public class CarResponseInfo
+    {
+        public int ClosestCar { get; set; }
+        public int DistanceInMeters { get; set; }
+        public int TimeInSeconds { get; set; }
+
+        public CarResponseInfo (int closestCar, int distanceInMeters, int timeInSeconds)
+        {
+            ClosestCar = closestCar;
+            DistanceInMeters = distanceInMeters;
+            TimeInSeconds = timeInSeconds;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/CarRoutingException.cs b/DoubleGisIntegration/Models/CarRoutingException.cs
new file mode 100644
index 0000000..02dce60
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingException.cs
@@ -0,0 +1,14 @@
+namespace CarRouting.Models {
+    public class CarRoutingException : System.Exception {
+        public CarRoutingException(int errorCode, string message) {
+            Message = message;
+            ErrorCode = errorCode;
+        }
+        public int ErrorCode { get; set; }
+        public override string Message { get; }
+
+        public override string ToString() {
+            return $"Ошибка {ErrorCode}: {Message}";
+        }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/CarRoutingRequest.cs b/DoubleGisIntegration/Models/CarRoutingRequest.cs
new file mode 100644
index 0000000..a6bd22a
--- /dev/null
+++ b/DoubleGisIntegration/Models/CarRoutingRequest.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models
+{
+    public class CarRoutingRequest
+    {
+        public GeoCoordinates Destination { get; set; }
+        public IEnumerable<Car> Cars { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
new file mode 100644
index 0000000..97e7efd
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQuery.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQuery
+    {
+        public string Locale { get; set; }
+        public string Point_a_name { get; set; }
+        public string Point_b_name { get; set; }
+        public List<GisCoordinate> Points { get; set; }
+        public string Type { get; set; }
+
+        public CarRoutingQuery(GeoCoordinates destination, GeoCoordinates carCoordinates)
+        {
+            Locale = "ru";
+            Point_a_name = null;
+            Point_b_name = null;
+            Type = "jam";
+
+            Points = new List<GisCoordinate>
+            {
+                new GisCoordinate(carCoordinates),
+                new GisCoordinate(destination)
+            };
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
new file mode 100644
index 0000000..12ea9f0
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/CarRoutingQueryResult.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class CarRoutingQueryResult
+    {
+        public IEnumerable<QueryResultInner> Result { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/GisCoordinate.cs b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
new file mode 100644
index 0000000..adbb413
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/GisCoordinate.cs
@@ -0,0 +1,16 @@
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class GisCoordinate
+    {
+        public string Type { get; set; }
+        public double X { get; set; }
+        public double Y { get; set; }
+
+        public GisCoordinate(GeoCoordinates coords)
+        {
+            Type = "pedo";
+            X = coords.Lng;
+            Y = coords.Lat;
+        }
+    }
+}
diff --git a/DoubleGisIntegration/Models/DTO/QueryResultInner.cs b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
new file mode 100644
index 0000000..cc92021
--- /dev/null
+++ b/DoubleGisIntegration/Models/DTO/QueryResultInner.cs
@@ -0,0 +1,9 @@
+using System;
+namespace DoubleGisIntegration.Models.DTO
+{
+    public class QueryResultInner
+    {
+        public int Total_distance { get; set; }
+        public int Total_duration { get; set; }
+    }
+}
diff --git a/DoubleGisIntegration/Models/ErrorViewModel.cs b/DoubleGisIntegration/Models/ErrorViewModel.cs
new file mode 100644
index 0000000..33776b9
--- /dev/null
+++ b/DoubleGisIntegration/Models/ErrorViewModel.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace DoubleGisIntegration.Models
+{
+    public class ErrorViewModel
+    {
+        public string RequestId { get; set; }
+
+        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Models/GeoCoordinates.cs b/DoubleGisIntegration/Models/GeoCoordinates.cs
new file mode 100644
index 0000000..fde222f
--- /dev/null
+++ b/DoubleGisIntegration/Models/GeoCoordinates.cs
@@ -0,0 +1,8 @@
+namespace DoubleGisIntegration.Models
+{
+    public class GeoCoordinates
+    {
+        public double Lat { get; set; }
+        public double Lng { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Program.cs b/DoubleGisIntegration/Program.cs
new file mode 100644
index 0000000..7a790bc
--- /dev/null
+++ b/DoubleGisIntegration/Program.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace DoubleGisIntegration
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateWebHostBuilder(args).Build().Run();
+        }
+
+        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+            WebHost.CreateDefaultBuilder(args)
+                .UseStartup<Startup>();
+    }
+}
diff --git a/DoubleGisIntegration/Properties/launchSettings.json b/DoubleGisIntegration/Properties/launchSettings.json
new file mode 100644
index 0000000..a330472
--- /dev/null
+++ b/DoubleGisIntegration/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:55659",
+      "sslPort": 44383
+    }
+  },
+  "profiles": {
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "DoubleGisIntegration": {
+      "commandName": "Project",
+      "launchBrowser": true,
+      "applicationUrl": "https://localhost:5001;http://localhost:5000",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/DoubleGisIntegration/Startup.cs b/DoubleGisIntegration/Startup.cs
new file mode 100644
index 0000000..67861a7
--- /dev/null
+++ b/DoubleGisIntegration/Startup.cs
@@ -0,0 +1,36 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DoubleGisIntegration
+{
+    public class Startup
+    {
+        public Startup(IConfiguration configuration)
+        {
+            Configuration = configuration;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+            services.AddHttpClient();
+        }
+
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+        {
+            app.UseDeveloperExceptionPage();
+
+            app.UseMvc(routes =>
+            {
+                routes.MapRoute(
+                    name: "default",
+                    template: "{controller=Home}/{action=Index}/{id?}");
+            });
+        }
+    }
+}
diff --git a/DoubleGisIntegration/appsettings.Development.json b/DoubleGisIntegration/appsettings.Development.json
new file mode 100644
index 0000000..a2880cb
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git a/DoubleGisIntegration/appsettings.json b/DoubleGisIntegration/appsettings.json
new file mode 100644
index 0000000..7376aad
--- /dev/null
+++ b/DoubleGisIntegration/appsettings.json
@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+}

Jlteka added a commit to Jlteka/DoubleGisIntegration that referenced this pull request Apr 4, 2019

initial project version
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed9dbcb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,405 @@
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (github/gitignore#2483 (comment))
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (github/gitignore#1529 (comment))
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
\ No newline at end of file
diff --git a/DoubleGisIntegration.sln b/DoubleGisIntegration.sln
new file mode 100644
index 0000000..c348434
--- /dev/null
+++ b/DoubleGisIntegration.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubleGisIntegration", "DoubleGisIntegration\DoubleGisIntegration.csproj", "{582F4B1A-7852-43D8-9A20-BBA865B01C72}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{582F4B1A-7852-43D8-9A20-BBA865B01C72}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal
diff --git a/DoubleGisIntegration/Controllers/HomeController.cs b/DoubleGisIntegration/Controllers/HomeController.cs
new file mode 100644
index 0000000..bfabcfb
--- /dev/null
+++ b/DoubleGisIntegration/Controllers/HomeController.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Diag