public IEnumerable GetSuggestions(string filter, object parameter)
        {
            if (parameter == null)
            {
                return(this.citiesSuggestionProvider.GetSuggestions(filter, null));
            }

            var list = parameter as List <object>;

            string    geoObjectKind = list?[0] as string;
            GeoObject geoObject     = list?[1] as GeoObject;

            if (geoObject != null)
            {
                if (geoObject.GeocoderMetaData.Kind == GeoObjectKind.Locality && geoObjectKind == "Street")
                {
                    return(this.streetsSuggestionProvider.GetSuggestions(filter, geoObject));
                }

                if (geoObject.GeocoderMetaData.Kind == GeoObjectKind.Street && geoObjectKind == "Building")
                {
                    return(this.buildingsSuggestionProvider.GetSuggestions(filter, geoObject));
                }
            }

            return(null);
        }
예제 #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Feature" /> class.
 /// </summary>
 /// <param name="geometry">The Geometry Object.</param>
 /// <param name="properties">The properties.</param>
 /// <param name="id">The (optional) identifier.</param>
 // [JsonConstructor]
 public Feature(GeoObject geometry, Dictionary <string, object> properties = null, string id = null)
     : this()
 {
     Geometry   = geometry;
     Properties = properties ?? new Dictionary <string, object>();
     Id         = id;
 }
예제 #3
0
    private void TryCreateGeoTextObject(GeoData geoData, Vector3 objectPlace, bool containDescription)
    {
        if (!string.IsNullOrEmpty(geoData.description) || containDescription == false)
        {
            // Instantiate GeoText object.
            Vector3 textPlace      = objectPlace;
            double  distanceToUser = Calculator.DistanceBetween2GeoobjectsInM(currentLocation, geoData.location);

            if (distanceToUser > maxGeoTextDistance)
            {
                Vector3 mainCameraLocalPosition = _mainCamera.transform.position;
                textPlace = (objectPlace
                             - mainCameraLocalPosition).normalized * maxGeoTextDistance
                            + mainCameraLocalPosition;
            }

            GameObject prefab = Instantiate(GeoTextPrefab, textPlace, Quaternion.identity);

            prefab.transform.LookAt(_mainCamera.transform);
            prefab.transform.SetParent(ToNorth.transform);
            prefab.name = "GeoText " + geoData.title;
            prefab.tag  = nameof(GeoText);

            GeoObject geoObject = prefab.AddComponent <GeoObject>();
            geoObject.GeoData = geoData;
            prefab.GetComponent <GeoText>().Initialize(geoObject, distanceToUser, GetRelativeOffset(geoData));

            geoObjectsInScene[0].Add(geoData.id, prefab);
        }
    }
예제 #4
0
        public void ParsesRuOldStreetName(string fullStreetName, string expectedName, string expectedType)
        {
            var localizedOsm = new LocalizedOsmGeoObject(Language.Ru, new StreetName(fullStreetName, fullStreetName));

            var street = new GeoObject(localizedOsm);

            Assert.Equal(expectedName, street.OldName);
            Assert.Equal(expectedType, street.OldType);
        }
예제 #5
0
        public JsonResult GetGeoInfoNew(string address, string city)
        {
            if (String.IsNullOrEmpty(address) || String.IsNullOrEmpty(city))
            {
                return(Json(false));
            }
            GeoObject geoObject = geocodingAPI.GetGeoObject(address + " " + city);

            return(Json(geoObject));
        }
예제 #6
0
        public PartialViewResult GetGeoInfo(Guid?Id, string address, string city)
        {
            Store store = storeService.FindById(Id);

            System.Diagnostics.Debug.WriteLine("---------------  " + store.Address + "....." + store.City);
            GeoObject geoObject = geocodingAPI.GetGeoObject(store.Address + " " + store.City);

            System.Diagnostics.Debug.WriteLine("---------------  " + geoObject.Latitude + "....." + geoObject.Longitude);
            return(PartialView("GetGeoInfo", geoObject));
        }
예제 #7
0
        public void Can_Serialize_And_Deserialize_Geometry(GeoObject geometry)
        {
            var json = JsonSerializer.SerializeToString(geometry);

            var deserializedGeometry = JsonSerializer.DeserializeFromString <GeoObject>(json
                                                                                        //, new GeometryConverter()
                                                                                        );

            Assert.AreEqual(geometry, deserializedGeometry);
        }
예제 #8
0
        public void Can_Serialize_And_Deserialize_Geometry_As_Object_Property(GeoObject geometry)
        {
            var classWithGeometry = new ClassWithGeometryProperty(geometry);

            var json = JsonSerializer.SerializeToString(classWithGeometry);

            var deserializedClassWithGeometry = JsonSerializer.DeserializeFromString <ClassWithGeometryProperty>(json);

            Assert.AreEqual(classWithGeometry, deserializedClassWithGeometry);
        }
        public IEnumerable GetSuggestions(string filter, object parameter)
        {
            GeoObject street = (GeoObject)parameter;

            IEnumerable <string> suggestions = this.GeoSuggester.SuggestAsync(this.BuildFilter(street, filter)).GetAwaiter().GetResult().Take(100);

            GeoObjectCollection objects = new GeoObjectCollection(suggestions.AsParallel().SelectMany(elem => this.Geocoder.GeocodeAsync(elem, 15).GetAwaiter().GetResult()));

            return(objects.Where(o => this.IsBuildingOnCity(o, street)).Distinct().ToList());
        }
        private bool IsStreetInCity(GeoObject data, GeoObject city)
        {
            if (data.GeocoderMetaData.Kind == GeoObjectKind.Street && !string.IsNullOrEmpty(data.ToString()) &&
                data.GeocoderMetaData.Address.Locality == city.GeocoderMetaData.Address.Locality &&
                data.GeocoderMetaData.Address.Province == city.GeocoderMetaData.Address.Province)
            {
                return(true);
            }

            return(false);
        }
예제 #11
0
파일: Node.cs 프로젝트: Venzz/VkPhotos
        public void AddObject(GeoObject geoObject)
        {
            if (Matrix == null)
            {
                GeoObjects.Add(geoObject);
                return;
            }

            var x = (Int32)((geoObject.Location.Longitude - Tile.Point.Longitude) / (Tile.Width / 2));
            var y = (Int32)((Tile.Point.Latitude - geoObject.Location.Latitude) / (Tile.Height / 2));

            Matrix[x, y].AddObject(geoObject);
        }
예제 #12
0
        /// <summary>
        /// Serialize geometry to standard WKT string
        /// </summary>
        /// <param name="geometry"></param>
        /// <returns></returns>
        public static string ToWkt(this GeoObject geometry)
        {
            if (geometry is GeoPoint)
            {
                string point = GeometryToWkt((GeoPoint)geometry);

                return(string.Format("POINT({0})", point));
            }

            if (geometry is GeoLineString)
            {
                string linestring = GeometryToWkt((GeoLineString)geometry);

                return(string.Format("LINESTRING({0})", linestring));
            }

            if (geometry is GeoPolygon)
            {
                string polygon = GeometryToWkt((GeoPolygon)geometry);

                return(string.Format("POLYGON({0})", polygon));
            }

            if (geometry is GeoMultiPoint)
            {
                string point = GeometryToWkt((GeoMultiPoint)geometry);

                return(string.Format("MULTIPOINT({0})", point));
            }

            if (geometry is GeoMultiLineString)
            {
                string multiLineString = GeometryToWkt((GeoMultiLineString)geometry);

                return(string.Format("MULTILINESTRING({0})", multiLineString));
            }

            if (geometry is GeoMultiPolygon)
            {
                string multiPolygon = GeometryToWkt((GeoMultiPolygon)geometry);

                return(string.Format("MULTIPOLYGON({0})", multiPolygon));
            }

            if (geometry is GeoCollection)
            {
                return(string.Format("GEOMETRYCOLLECTION({0})", string.Join(",", ((GeoCollection)geometry).Geometries.Select(x => x.ToWkt()))));
            }

            return(null);
        }
예제 #13
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="YandexResponse" /> class.
        /// </summary>
        /// <param name="geoObject">Yandex geo object.</param>
        public YandexResponse(GeoObject geoObject)
        {
            if (geoObject != null)
            {
                Name        = geoObject.name;
                Description = geoObject.description;

                Point            = new LocationPoint(geoObject.Point.pos);
                PointLowerCorner = new LocationPoint(geoObject.boundedBy.Envelope.lowerCorner);
                PointUpperCorner = new LocationPoint(geoObject.boundedBy.Envelope.upperCorner);

                var metadataProperty = geoObject.metaDataProperty;

                var geocoderMetaData = metadataProperty?.GeocoderMetaData;
                if (geocoderMetaData == null)
                {
                    return;
                }

                Text = geocoderMetaData.text;
                Kind = geocoderMetaData.kind;

                var addressDetails = geocoderMetaData.AddressDetails;
                if (addressDetails == null)
                {
                    return;
                }

                var country = addressDetails.Country;
                AddressLine = country.AddressLine;
                CountryName = country.CountryName;
                CountryCode = country.CountryNameCode;

                var administrativeArea = country.AdministrativeArea;
                if (administrativeArea == null)
                {
                    return;
                }

                AdministrativeAreaName = administrativeArea.AdministrativeAreaName;

                var subAdministrativeArea = administrativeArea.SubAdministrativeArea;
                if (subAdministrativeArea == null)
                {
                    return;
                }

                SubAdministrativeArea = subAdministrativeArea.SubAdministrativeAreaName;
                LocalityName          = subAdministrativeArea.Locality?.LocalityName;
            }
        }
예제 #14
0
    private IEnumerator TryCreateGeoAudioObject(string audioURL, AudioType audioType,
                                                GeoData geoData, Vector3 objectPlace)
    {
        if (geoData.hasAudio)
        {
            // Create dummy object while loading audio.
            GameObject prefab = Instantiate(GeoAudioPrefab, objectPlace, Quaternion.identity);
            prefab.name = "GeoAudio " + ("[LOADING] ") + geoData.title;
            GeoObject geoObject = prefab.AddComponent <GeoObject>();
            geoObject.GeoData = geoData;
            geoObjectsInScene[2].Add(geoData.id, prefab);

            // Load audio from server.
            using (var request = UnityWebRequestMultimedia.GetAudioClip(audioURL, audioType))
            {
                yield return(request.SendWebRequest());

                bool result = request.result == UnityWebRequest.Result.Success;

                // Instantiate GeoAudio object.
                // Don't display radio model if geoData.hasModel.

                prefab.name = "GeoAudio " + (result ? "" : "[ERROR] ") + geoData.title;
                prefab.transform.SetParent(ToNorth.transform);
                prefab.transform.position = objectPlace;
                prefab.tag = nameof(GeoAudio);

                AudioClip audio = null;

                Debug.Log(audioURL + " " + geoData.title);

                if (result)
                {
                    audio = DownloadHandlerAudioClip.GetContent(request);
                }
                else
                {
                    Debug.LogError("Failed to load Audio: " + audioURL);
                }

                prefab.GetComponent <GeoAudio>().Initialize(geoObject, audio, GetRelativeOffset(geoData));
                // Display title if GeoAudio don't have GeoText.
                prefab.GetComponent <GeoAudio>().SetTitle(geoData.title, !geoData.hasText);

                prefab.GetComponent <AudioSource>().volume = 1;
                prefab.GetComponent <AudioSource>().Play();
            }
        }
    }
        private bool IsBuildingOnCity(GeoObject data, GeoObject street)
        {
            if (data.GeocoderMetaData.Kind == GeoObjectKind.Locality || data.GeocoderMetaData.Kind == GeoObjectKind.House)
            {
                if (!string.IsNullOrEmpty(data.ToString()) &&
                    data.GeocoderMetaData.Address.Locality == street.GeocoderMetaData.Address.Locality &&
                    data.GeocoderMetaData.Address.Province == street.GeocoderMetaData.Address.Province &&
                    data.GeocoderMetaData.Address?.Street == street.GeocoderMetaData.Address.Street)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Feature" /> class.
        /// </summary>
        /// <param name="geometry">The Geometry Object.</param>
        /// <param name="properties">
        /// Class used to fill feature properties. Any public member will be added to feature
        /// properties
        /// </param>
        /// <param name="id">The (optional) identifier.</param>
        public Feature(GeoObject geometry, object properties, string id = null)
            : this()
        {
            Geometry = geometry;
            Id       = id;

            if (properties == null)
            {
                Properties = new Dictionary <string, object>();
            }
            else
            {
                Properties = properties.GetType()
                             .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                             .ToDictionary(prop => prop.Name, prop => prop.GetValue(properties, null));
            }
        }
    void Start()
    {
        this._moduleId = Interlocked.Increment(ref _moduleIdCounter);
        this.randRot   = Rnd.Range(0, 4) * 90; // either 0, 90, 180, 270 degrees
        Log("Module rotation angle is " + this.randRot + (this.randRot == 0 ? "." : ". Oh no :("));

        this.originalVertexColor = this.BaseVertex.GetComponent <MeshRenderer>().material.color;

        this.schlafli = inUseShapes.Keys.PickRandom();
        //this.schlafli = "4 3 3";

        Log("Picked the following shape: {" + this.schlafli.Replace(' ', ',') + "}");

        SchlafliInterpreter.SchlafliStruct schlafliData = new SchlafliInterpreter.SchlafliStruct();

        try
        {
            schlafliData = SchlafliInterpreter.GetGeometryDataFromSchlafli(this.schlafli.Split(' '));
        }
        catch (SchlafliInterpreterException)
        {
            this.Module.HandlePass();
            return;
        }

        this.geoObject = ScriptableObject.CreateInstance <GeoObject>();
        this.geoObject.SetBaseObjects(this.BaseVertex, this.BaseEdge, this.BaseFace);


        float scaleFactor = 2.5f;

        this.geoObject.LoadVerticesEdgesAndFaces(
            schlafliData.VertexLocations.Select(x => x.Select(y => y * scaleFactor).ToArray()).ToArray(), schlafliData.EdgeVertexIndexes, schlafliData.FaceVertexIndexes);


        string[] rotCombinations = GetRotationPermutations(GetDimensionCount());

        this.rotations   = Enumerable.Range(0, numberOfRotations).Select(x => rotCombinations[rand.Next(rotCombinations.Length)]).ToArray();
        this.vertexCount = schlafliData.VertexLocations.Length;

        this.geoObject.OnVertexClicked += GeoObject_OnVertexClicked;

        Log("Rotations are: " + string.Join(", ", this.rotations));

        this._rotationCoroutine = StartCoroutine(RotateDimKing());
    }
예제 #18
0
        private void UpdateBus(GeoObject obj)
        {
            MapIcon busIcon;
            var     bus = (Bus)obj;

            if (!_busToIcon.TryGetValue(bus, out busIcon))
            {
                busIcon        = new MapIcon();
                busIcon.ZIndex = 1;
                busIcon.Title  = bus.Code;
                busIcon.Image  = _busIconResource;
                // TODO image etc...
                _busToIcon.Add(bus, busIcon);
                CanberraMap.MapElements.Add(busIcon);
            }
            busIcon.Location = bus.Point;
        }
예제 #19
0
        public GeoObject GetGeoObject(string address)
        {
            GeocodingRequest request = new GeocodingRequest(address);//store.Address+store.City

            request.IsSensor = false;
            GeocodingResponse response = request.GetResponse();
            var result = response.Results.First();

            LatLng location  = result.Geometry.Location;
            double latitude  = location.Latitude;
            double longitude = location.Longitude;

            System.Diagnostics.Debug.WriteLine("---------------  " + latitude);
            System.Diagnostics.Debug.WriteLine("+++++++++++  " + longitude);
            GeoObject obj = new GeoObject
            {
                Latitude  = latitude,
                Longitude = longitude
            };

            return(obj);
        }
예제 #20
0
        public async Task <BuildingAddress> GetBuildingAsync(GeoPoint geoPoint)
        {
            GeoObjectCollection objectCollection =
                await this.Geocoder.ReverseGeocodeAsync(geoPoint, GeoObjectKind.House, 1, LangType.RU);

            GeoObject geoObject = objectCollection.First();
            Address   address   = geoObject.GeocoderMetaData.Address;

            int buildingId =
                await this.BuildingRepository.GetBuildingIdOrDefaultAsync(geoPoint.Latitude, geoPoint.Longitude);

            if (buildingId != default(int))
            {
                return(await this.BuildingRepository.GetBuildingAsync(buildingId));
            }

            int id = await this.PolyclinicRegionProvider.GetPolyclinicRegionIdAsync(address);

            PolyclinicRegion region = await this.PolyclinicRegionService.GetRegionAsync(id);

            BuildingAddress building = new BuildingAddress
            {
                City             = $"{address.Locality}, {address.Province}, {address.Country}",
                Street           = address.Street,
                Building         = address.House,
                Latitude         = geoPoint.Latitude,
                Longitude        = geoPoint.Longitude,
                PolyclinicRegion = region
            };

            int insertedBuildingId = await this.InsertOrUpdateBuildingAsync(building);

            building.Id = insertedBuildingId;

            return(building);
        }
예제 #21
0
 public void AddObject(GeoObject geoObject) => Root.AddObject(geoObject);
예제 #22
0
            public Boolean IsAccepted(GeoObject geoObject)
            {
                var photo = (Photo)geoObject.Value;

                return(photo.Tag.HasFlag(PhotoTag.SharedLink));
            }
예제 #23
0
 public ClassWithGeometryProperty(GeoObject geometry)
 {
     Geometry = geometry;
 }
예제 #24
0
 public void Has_Bounding_Box(GeoObject geometry)
 {
     Assert.IsTrue(!geometry.BoundingBox.IsNull);
 }
예제 #25
0
    private void UpdateGeoObjectsPositions(LocationDataModel location)
    {
        foreach (var line in lines)
        {
            if (line)
            {
                Destroy(line);
            }
        }
        lines = new List <GameObject>();
        float minDistance = float.MaxValue;

        foreach (var dictionary in geoObjectsInScene)
        {
            foreach (KeyValuePair <string, GameObject> geoObjectPair in dictionary)
            {
                string    geoObjectId = geoObjectPair.Key;
                GeoObject geoObject   = geoObjectPair.Value.GetComponent <GeoObject>();

                Vector3 positionOfGeoObject = GPSEncoder.GPSToUCS(geoObject.GeoData.location.lat, geoObject.GeoData.location.lng);
                double  distanceToUser      = Calculator.DistanceBetween2GeoobjectsInM(location, geoObject.GeoData.location);
                float   distanceToUserUnity = Vector3.Distance(geoObject.transform.localPosition, _mainCamera.transform.position);

                if (placingAccuracy <= distanceToUser && distanceToUser <= maxGeoTextDistance && placingAccuracy <= distanceToUserUnity)
                {
                    geoObject.transform.localPosition = Vector3.Lerp(geoObject.transform.localPosition,
                                                                     positionOfGeoObject, 1f * Time.deltaTime);
                }

                if (geoObject.gameObject.TryGetComponent <GeoText>(out GeoText geoText))
                {
                    if (placingAccuracy <= distanceToUser &&
                        distanceToUser <= maxGeoTextDistance &&
                        placingAccuracy <= distanceToUserUnity)
                    {
                        geoObject.transform.localPosition = Vector3.Lerp(geoObject.transform.localPosition, positionOfGeoObject, 1f * Time.deltaTime);
                    }

                    // GeoText should be closer than maxGeoTextDistance.

                    if (distanceToUser > maxGeoTextDistance)
                    {
                        Vector3 cameraLocalPosition = _mainCamera.transform.position;
                        Vector3 newPosition         = ((positionOfGeoObject - cameraLocalPosition).normalized * maxGeoTextDistance) + cameraLocalPosition;
                        newPosition.y = cameraLocalPosition.y;

                        geoObject.transform.localPosition = Vector3.Lerp(geoObject.transform.localPosition, newPosition, 1f * Time.deltaTime);
                    }

                    if (geoText)
                    {
                        geoText.distance.text = Convert.ToUInt32(distanceToUser).ToString() + " m";
                    }
                }

                if (geoObject.gameObject.TryGetComponent <GeoAudio>(out GeoAudio geoAudio))
                {
                    geoObject.GetComponent <CanvasGroup>().alpha = (distanceToUser < maxGeoAudioDistance) ? 1 : 0;

                    if (distanceToUser > maxGeoTextDistance)
                    {
                        Vector3 cameraLocalPosition = _mainCamera.transform.position;
                        Vector3 newPosition         = ((positionOfGeoObject - cameraLocalPosition).normalized * maxGeoTextDistance) + cameraLocalPosition;

                        newPosition.y = cameraLocalPosition.y;

                        geoObject.transform.localPosition = Vector3.Lerp(geoObject.transform.localPosition, newPosition, 1f * Time.deltaTime);

                        geoObject.GetComponent <AudioSource>().volume = 0;
                    }
                    else
                    {
                        geoObject.GetComponent <AudioSource>().volume = 1;
                    }

                    DrawLine(geoObject.transform.position, _mainCamera.transform.position - Vector3.up * 0.1f, Color.green);
                }

                if (geoObject.gameObject.TryGetComponent <GeoModel>(out GeoModel geoModel))
                {
                    DrawLine(geoObject.transform.position, _mainCamera.transform.position - Vector3.up * 0.1f, Color.red);
                }
            }
        }
    }
예제 #26
0
    private IEnumerator TryCreateGeoModelObject(string assetBundleURL, GeoData geoData, Vector3 objectPlace)
    {
        if (geoData.hasModel)
        {
            // Create dummy object while loading AssetBundle.
            GameObject dummy = Instantiate(new GameObject());
            dummy.name = "GeoModel [LOADING] " + geoData.title;
            geoObjectsInScene[1].Add(geoData.id, dummy);
            dummy.AddComponent <GeoModel>();
            GeoObject dummyGeoObject = dummy.AddComponent <GeoObject>();
            dummyGeoObject.GeoData = geoData;
            dummy.GetComponent <GeoModel>().Initialize(dummyGeoObject, assetBundleURL);

            // Instantiate Title above model if it doesn't have GeoText.
            if (!geoData.hasText)
            {
                TryCreateGeoTextObject(geoData, objectPlace, false);
            }

            // Send request with a path related to the platform.
            var request = UnityWebRequestAssetBundle.GetAssetBundle(assetBundleURL, 0);
            Debug.Log("Loading AssetBundle, URI: " + assetBundleURL);
            yield return(request.SendWebRequest());

            // Download requested AssetBundle.
            AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

            if (bundle == null)
            {
                Debug.Log("Failed to load AssetBundle!");
            }
            else
            {
                string[] allAssetsPath  = bundle.GetAllAssetNames();
                string[] allPrefabsPath = allAssetsPath.Where(x => x.Contains(".prefab")).ToArray();

                for (int i = 0; i < allPrefabsPath.Length; i++)
                {
                    GameObject prefab = bundle.LoadAsset <GameObject>(allPrefabsPath[i]);

                    prefab.name = "GeoModel " + geoData.title;
                    prefab.transform.SetParent(ToNorth.transform);
                    prefab.transform.position = objectPlace;
                    prefab.tag = nameof(GeoModel);

                    prefab.AddComponent <GeoModel>();
                    prefab.AddComponent <SphereCollider>();
                    prefab.GetComponent <SphereCollider>().radius    = 12;
                    prefab.GetComponent <SphereCollider>().isTrigger = true;

                    GeoObject geoObject = prefab.AddComponent <GeoObject>();
                    geoObject.GeoData = geoData;
                    prefab.GetComponent <GeoModel>().Initialize(geoObject, assetBundleURL);

                    Instantiate(prefab);

                    Destroy(GameObject.Find("GeoModel [LOADING] " + geoData.title));
                    geoObjectsInScene[1][geoData.id] = prefab;
                    bundle.Unload(false);
                }
            }
        }
    }
예제 #27
0
 public void ShowDescription(GeoObject geoObject)
 {
     title.text        = geoObject.GeoData.title;
     description.text  = geoObject.GeoData.description;
     canvasGroup.alpha = 1;
 }
 private string BuildFilter(GeoObject city, string filter)
 {
     return($"{city.GeocoderMetaData.Address.Locality} {city.GeocoderMetaData.Address.Street} {filter}");
 }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            using (var scope = provider.CreateScope())
            {
                dbContext         = scope.ServiceProvider.GetRequiredService <ApplicationContext>();
                geoliteManager    = scope.ServiceProvider.GetRequiredService <IGeoliteManager>();
                hostEnvironment   = scope.ServiceProvider.GetRequiredService <IWebHostEnvironment>();
                connectionManager = scope.ServiceProvider.GetRequiredService <IConnectionStringManager>();



                // update every 7 days
                int updateIntervalInMilliseconds = TimeSpan.FromDays(7).Milliseconds;
                dbContext.Database.EnsureCreated();

                if (!dbContext.GeoObjects.Any())
                {
                    FillDatabase();

                    // install timer to UpdateDatabase every 7 days
                    timer = new Timer(async(obj) =>
                                      await UpdateDatabaseAsync(), null, updateIntervalInMilliseconds, updateIntervalInMilliseconds);
                }
                else
                {
                    GeoObject geoObject = await dbContext.GeoObjects.FirstOrDefaultAsync();

                    DateTime lastUpdateTime = geoObject.UpdateTime;
                    DateTime currentTime    = DateTime.UtcNow;
                    DateTime nextUpdateTime = CalculateNextUpdateTime(currentTime);
                    TimeSpan dayPassed      = currentTime - lastUpdateTime;
                    DateTime dateToUpdate   = nextUpdateTime - dayPassed;
                    TimeSpan daysLeft       = dateToUpdate - currentTime;


                    if (daysLeft.Days > 0)
                    {
                        // install timer to UpdateDatabase when left days will pass and set interval to repeat this action every 7 days
                        // so we update our DB every week (Wednesday)
                        timer = new Timer(async(obj) =>
                                          await UpdateDatabaseAsync(), null, daysLeft.Milliseconds, updateIntervalInMilliseconds);
                    }
                    else
                    {   // install timer to UpdateDatabase now and set interval to repeat this action every 7 days
                        // so we update our DB every week (Wednesday)
                        timer = new Timer(async(obj) =>
                                          await UpdateDatabaseAsync(), null, 0, updateIntervalInMilliseconds);
                    }
                }
            }


            DateTime CalculateNextUpdateTime(DateTime currentTime)
            => currentTime.DayOfWeek switch
            {
                DayOfWeek.Sunday => currentTime + TimeSpan.FromDays(3),
                DayOfWeek.Monday => currentTime + TimeSpan.FromDays(2),
                DayOfWeek.Tuesday => currentTime + TimeSpan.FromDays(1),
                DayOfWeek.Wednesday => currentTime,
                DayOfWeek.Thursday => currentTime + TimeSpan.FromDays(6),
                DayOfWeek.Friday => currentTime + TimeSpan.FromDays(5),
                DayOfWeek.Saturday => currentTime + TimeSpan.FromDays(4),
                _ => currentTime
            };

            // since we have no data in DB we should not call this method in async mode
            // because we first should migrate data to our DB and don't let any controller to be able to access DB before we
            // so this is why it's better to do it in sync
            // because we don't want our API work when DB is empty
            void FillDatabase()
            {
                var root      = hostEnvironment.ContentRootPath;
                var directory = Path.Combine(root, "Geolite");

                Directory.CreateDirectory(directory);

                string geoliteDb = geoliteManager.DownloadDbFileAsync(directory).Result;

                geoliteManager.MigrateToDbContext(geoliteDb, dbContext).Wait();
            }

            async Task UpdateDatabaseAsync()
            {
                var root      = hostEnvironment.ContentRootPath;
                var directory = Path.Combine(root, "Geolite");

                Directory.CreateDirectory(directory);

                string geoliteDb = await geoliteManager.DownloadDbFileAsync(directory);

                #region Migrate geoliteDb to new Database

                string newDatabaseConnection = connectionManager.GenerateNewConnectionString();

                var newDbConnectionBuilder = new DbContextOptionsBuilder <ApplicationContext>();
                newDbConnectionBuilder.UseNpgsql(newDatabaseConnection);

                using (var context = new ApplicationContext(newDbConnectionBuilder.Options))
                {
                    await context.Database.EnsureCreatedAsync();

                    await geoliteManager.MigrateToDbContext(geoliteDb, context);
                }

                #endregion


                // get currentDbConnection so that to delete
                // because we already created new DB
                string outdatedConnectionString = connectionManager.ConnectionString;

                // set CurrentConnectionString to our new DB
                connectionManager.ConnectionString = newDatabaseConnection;


                #region Delete outdated Database

                var outdatedDbBuilder = new DbContextOptionsBuilder <ApplicationContext>();
                outdatedDbBuilder.UseNpgsql(outdatedConnectionString);

                using (var outdatedContext = new ApplicationContext(outdatedDbBuilder.Options))
                {
                    await outdatedContext.Database.EnsureDeletedAsync();
                }

                #endregion
            }
        }
    }
예제 #30
0
 public GeoObjectDto(GeoObject geoObject)
 {
     Name = geoObject.Name;
 }