Skip to content

Commit 4b89fca

Browse files
Merge pull request #51 from GeoChatter/v1.2.0.0
V1.2.0.0
2 parents ec9267c + 7a36ea6 commit 4b89fca

File tree

81 files changed

+8861
-612
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+8861
-612
lines changed

GeoChatter.iss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
33

44
#define MyAppName "GeoChatter"
5-
#define MyAppVersion "1.1.0.0"
5+
#define MyAppVersion "1.2.0.0"
66
#define MyAppPublisher "NoBuddy&Rhino"
77
#define MyAppURL "https://geochatter.tv"
88
#define MyAppExeName "GeoChatter.exe"
@@ -23,7 +23,7 @@ DisableProgramGroupPage=yes
2323
; Uncomment the following line to run in non administrative install mode (install for current user only.)
2424
;PrivilegesRequired=lowest
2525
OutputDir=C:\Users\Denis\Desktop\Setup
26-
OutputBaseFilename=GeoChatter_v1.1.0.0
26+
OutputBaseFilename=GeoChatter_v1.2.0.0
2727
SetupIconFile=D:\Projects\Github\GeoChatter\GeoChatter-Client\GeoChatter\GeoChatter\Resources\logo_clean.ico
2828
Compression=lzma
2929
SolidCompression=yes
@@ -43,7 +43,7 @@ Name: {app}; Permissions: everyone-full
4343
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\GeoChatter\GeoChatter\bin\Release\publish\*"; DestDir: "{app}"; Flags: ignoreversion
4444
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\GeoChatter\GeoChatter\bin\Release\publish\Styles\*"; DestDir: "{app}\Styles"; Flags: ignoreversion recursesubdirs
4545
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\GeoChatter\GeoChatter\bin\Release\publish\Scripts\*"; DestDir: "{app}\Scripts"; Flags: ignoreversion recursesubdirs
46-
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\Dependencies\Quickstart.pdf"; DestDir: "{app}\Scripts"; Flags: ignoreversion
46+
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\Dependencies\Quickstart.pdf"; DestDir: "{app}"; Flags: ignoreversion
4747
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\Dependencies\windowsdesktop-runtime-6.0.3-win-x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall dontcopy
4848
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\Dependencies\aspnetcore-runtime-6.0.3-win-x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall dontcopy
4949
Source: "D:\Projects\Github\GeoChatter\GeoChatter-Client\Dependencies\VC_redist.x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall dontcopy

GeoChatter/GeoChatter.Web/CommonCommands.cs renamed to GeoChatter/GeoChatter.Core/Commands/CommonCommands.cs

Lines changed: 63 additions & 60 deletions
Large diffs are not rendered by default.

GeoChatter/GeoChatter.Core/Helpers/BorderHelper.cs

Lines changed: 318 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System.Threading;
1616
using System.Threading.Tasks;
1717
using GeoChatter.Core.Common.Extensions;
18+
using CefSharp.DevTools.Audits;
1819

1920
namespace GeoChatter.Core.Helpers
2021
{
@@ -427,10 +428,73 @@ public static Coordinates GetRandomPointWithinBoundBox(Feature feature)
427428
/// Get given <paramref name="countryNameOrCode"/>'s <see cref="GeoJson"/>
428429
/// </summary>
429430
/// <param name="countryNameOrCode">Country name or code</param>
431+
/// <param name="feature">Feature found</param>
430432
/// <returns></returns>
431-
public static GeoJson GetCountry(string countryNameOrCode)
433+
public static GeoJson GetCountry(string countryNameOrCode, out Feature feature)
432434
{
433-
return BorderData.FirstOrDefault(g => g.features.Any(f => f.properties.shapeName == countryNameOrCode || f.properties.shapeISO == countryNameOrCode || f.properties.shapeGroup == countryNameOrCode));
435+
feature = null;
436+
if (string.IsNullOrWhiteSpace(countryNameOrCode))
437+
{
438+
return null;
439+
}
440+
441+
countryNameOrCode = countryNameOrCode.Trim();
442+
GeoJson g = null;
443+
List<Feature> feats = new List<Feature>();
444+
445+
foreach (var geo in BorderData)
446+
{
447+
foreach (var feat in geo.features)
448+
{
449+
if (feat.properties.shapeName.ToUpperInvariant() == countryNameOrCode.ToUpperInvariant()
450+
|| feat.properties.shapeName.ReplaceDefault(" ", "").ToUpperInvariant() == countryNameOrCode.ToUpperInvariant())
451+
{
452+
feature = feat;
453+
return geo;
454+
}
455+
else if (feat.properties.shapeISO.ToUpperInvariant() == countryNameOrCode.ToUpperInvariant()
456+
|| feat.properties.shapeISO.ReplaceDefault("-", "").ToUpperInvariant() == countryNameOrCode.ToUpperInvariant())
457+
{
458+
if (feat.properties.shapeGroup != feat.properties.shapeISO)
459+
{
460+
feature = feat;
461+
return geo;
462+
}
463+
else if (g == null || g == geo)
464+
{
465+
feats.Add(feat);
466+
g = geo;
467+
}
468+
else
469+
{
470+
feats.Clear();
471+
feats.Add(feat);
472+
g = geo;
473+
}
474+
}
475+
else if (feat.properties.shapeGroup.ToUpperInvariant() == countryNameOrCode.ToUpperInvariant()
476+
|| feat.properties.shapeGroup.ReplaceDefault("-", "").ToUpperInvariant() == countryNameOrCode.ToUpperInvariant())
477+
{
478+
if (g == null || g == geo)
479+
{
480+
feats.Add(feat);
481+
g = geo;
482+
}
483+
else
484+
{
485+
feats.Clear();
486+
feats.Add(feat);
487+
g = geo;
488+
}
489+
}
490+
}
491+
}
492+
493+
if (feats.Count > 0)
494+
{
495+
feature = feats[random.Next(feats.Count)];
496+
}
497+
return g;
434498
}
435499

436500
private static int GetFeatureFactor(GeoJson geo)
@@ -473,6 +537,20 @@ public static GeoJson GetRandomCountry()
473537
return GetRandomCountryCacheBorder[i];
474538
}
475539

540+
/// <summary>
541+
/// Get GeoJson of given country code or name
542+
/// </summary>
543+
/// <returns></returns>
544+
public static GeoJson GetGeoJSONOf(string codeOrName)
545+
{
546+
codeOrName = codeOrName?.Trim().ToUpperInvariant();
547+
return BorderData
548+
.FirstOrDefault(b => b.features
549+
.Any(f => f.properties.shapeGroup == codeOrName
550+
|| f.properties.shapeISO == codeOrName
551+
|| f.properties.shapeName.ToUpperInvariant() == codeOrName));
552+
}
553+
476554
/// <summary>
477555
/// Get a random feature from given country
478556
/// </summary>
@@ -485,12 +563,12 @@ public static Feature GetRandomFeature(GeoJson geo)
485563
}
486564

487565
/// <summary>
488-
/// See <see cref="GetRandomPointCloseOrWithinAPolygon(out Feature)"/>
566+
/// See <see cref="GetRandomPointCloseOrWithinARandomPolygon(out Feature)"/>
489567
/// </summary>
490568
/// <returns></returns>
491-
public static Coordinates GetRandomPointCloseOrWithinAPolygon()
569+
public static Coordinates GetRandomPointCloseOrWithinARandomPolygon()
492570
{
493-
return GetRandomPointCloseOrWithinAPolygon(out Feature _);
571+
return GetRandomPointCloseOrWithinARandomPolygon(out Feature _);
494572
}
495573

496574
/// <summary>
@@ -499,12 +577,246 @@ public static Coordinates GetRandomPointCloseOrWithinAPolygon()
499577
/// </summary>
500578
/// <param name="feature">Randomly picked feature</param>
501579
/// <returns></returns>
502-
public static Coordinates GetRandomPointCloseOrWithinAPolygon(out Feature feature)
580+
public static Coordinates GetRandomPointCloseOrWithinARandomPolygon(out Feature feature)
503581
{
504582
feature = GetRandomFeature(GetRandomCountry());
505583
return GetRandomPointWithinBoundBox(feature);
506584
}
507585

586+
/// <summary>
587+
/// See <see cref="GetRandomPointWithinARandomPolygon(out Feature, int)"/>
588+
/// </summary>
589+
/// <returns></returns>
590+
public static Coordinates GetRandomPointWithinARandomPolygon(int maxTries = 100)
591+
{
592+
return GetRandomPointWithinARandomPolygon(out Feature _, maxTries);
593+
}
594+
595+
/// <summary>
596+
/// Get a random point within ANY polygon
597+
/// </summary>
598+
/// <para>WARNING: This DOES NOT guarantee but tries <paramref name="maxTries"/> amount of times at max to ensure a hit on ANY polygon</para>
599+
/// <param name="maxTries">Maximum tries in case of misses by <see cref="GetRandomPointCloseOrWithinARandomPolygon(out Feature)"/></param>
600+
/// <param name="feature">Randomly picked feature</param>
601+
/// <returns></returns>
602+
public static Coordinates GetRandomPointWithinARandomPolygon(out Feature feature, int maxTries = 100)
603+
{
604+
Coordinates co = null;
605+
feature = null;
606+
int tries = 0;
607+
while (co == null && tries++ < maxTries)
608+
{
609+
GeoJson g = GetRandomCountry();
610+
co = GetRandomPointWithinBoundBox(GetRandomFeature(g));
611+
612+
GetFeatureHitBy(new double[2] { co.Longitude, co.Latitude }, out GeoJson gjhit, out feature, out _);
613+
614+
if (g == gjhit)
615+
{
616+
break;
617+
}
618+
}
619+
return co;
620+
}
621+
622+
/// <summary>
623+
/// See <see cref="GetRandomPointWithin(string, out Feature, int)"/>
624+
/// </summary>
625+
/// <returns></returns>
626+
public static Coordinates GetRandomPointWithin(string codeOrName, int maxTries = 100)
627+
{
628+
return GetRandomPointWithin(codeOrName, out Feature _, maxTries);
629+
}
630+
631+
/// <summary>
632+
/// Get a random point within a polygon of given <paramref name="codeOrName"/> geojson
633+
/// </summary>
634+
/// <param name="codeOrName">Country code or name, <see cref="GetCountry(string)"/></param>
635+
/// <param name="maxTries">Maximum tries in case of misses by <see cref="GetRandomPointCloseOrWithinARandomPolygon(out Feature)"/></param>
636+
/// <param name="feature">Randomly picked feature</param>
637+
/// <returns></returns>
638+
public static Coordinates GetRandomPointWithin(string codeOrName, out Feature feature, int maxTries = 100)
639+
{
640+
GeoJson g = GetCountry(codeOrName, out Feature feat);
641+
if (g == null)
642+
{
643+
return GetRandomPointCloseOrWithinARandomPolygon(out feature);
644+
}
645+
646+
Coordinates co = null;
647+
feature = null;
648+
int tries = 0;
649+
feat ??= GetRandomFeature(g);
650+
651+
while (tries++ < maxTries)
652+
{
653+
co = GetRandomPointWithinBoundBox(feat);
654+
655+
GetFeatureHitBy(new double[2] { co.Longitude, co.Latitude }, out GeoJson gjhit, out feature, out _);
656+
657+
if (g == gjhit)
658+
{
659+
break;
660+
}
661+
else
662+
{
663+
co = null;
664+
}
665+
}
666+
if (co == null)
667+
{
668+
return GetRandomPointCloseOrWithinARandomPolygon(out feature);
669+
}
670+
return co;
671+
}
672+
/// <summary>
673+
/// Get a random point within given country polygon's bounding box present in current border set
674+
/// <para>WARNING: This DOES NOT guarantee that the point will be within a polygon</para>
675+
/// </summary>
676+
/// <param name="codeOrName">Randomly picked feature</param>
677+
/// <param name="feature">Randomly picked feature</param>
678+
/// <returns></returns>
679+
public static Coordinates GetRandomPointCloseOrWithin(string codeOrName, out Feature feature)
680+
{
681+
feature = GetRandomFeature(GetGeoJSONOf(codeOrName));
682+
return GetRandomPointWithinBoundBox(feature);
683+
}
684+
685+
/// <summary>
686+
/// Get alpha3 code from alpha2 code or name
687+
/// </summary>
688+
/// <param name="codeOrName"></param>
689+
/// <returns></returns>
690+
public static string GetAlpha3FromCodeOrName(string codeOrName)
691+
{
692+
if (string.IsNullOrWhiteSpace(codeOrName))
693+
{
694+
return string.Empty;
695+
}
696+
697+
string match = codeOrName.ToUpperInvariant();
698+
if (match.Length == 2)
699+
match = ISO3166Helper.FromAlpha2(match)?.Alpha3;
700+
else
701+
match = ISO3166Helper.Collection.FirstOrDefault(c => c.Name.ToUpperInvariant() == match)?.Alpha3;
702+
703+
return match ?? codeOrName;
704+
}
705+
706+
private static string GetNameFromRandomGuessArg(string arg)
707+
{
708+
if (string.IsNullOrWhiteSpace(arg))
709+
{
710+
return string.Empty;
711+
}
712+
713+
string[] splt = arg.Split(':', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
714+
if (splt.Length >= 1)
715+
{
716+
return splt[0];
717+
}
718+
else
719+
{
720+
return arg;
721+
}
722+
}
723+
724+
private static double GetWeightFromRandomGuessArg(string arg)
725+
{
726+
if (string.IsNullOrWhiteSpace(arg))
727+
{
728+
return 0D;
729+
}
730+
731+
string[] splt = arg.Split(':', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
732+
if (splt.Length <= 1)
733+
{
734+
return 1D;
735+
}
736+
else
737+
{
738+
return splt[1].ParseAsDouble(1);
739+
}
740+
}
741+
/// <summary>
742+
/// Get random coordinates around given areas
743+
/// </summary>
744+
/// <param name="randomGuessQuery"><code>targetCountryNameOrCode</code> OR <code>target1:relativeProbability1 target2:relativeProbability2 ...</code></param>
745+
/// <returns></returns>
746+
public static Coordinates GetRandomCoordinateFromRandomGuessQuery(string randomGuessQuery)
747+
{
748+
Coordinates rand = null;
749+
try
750+
{
751+
if (string.IsNullOrWhiteSpace(randomGuessQuery))
752+
{
753+
return rand;
754+
}
755+
756+
// TODO: Refactor
757+
string[] countryArgs = randomGuessQuery
758+
.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
759+
.OrderBy(GetWeightFromRandomGuessArg)
760+
.ToArray();
761+
if (countryArgs.Length > 0)
762+
{
763+
764+
if (countryArgs.Length == 1)
765+
{
766+
string match = GetAlpha3FromCodeOrName(GetNameFromRandomGuessArg(countryArgs[0]));
767+
rand = GetRandomPointWithin(match);
768+
}
769+
else
770+
{
771+
List<string> matches = countryArgs
772+
.Select(GetNameFromRandomGuessArg)
773+
.ToList();
774+
775+
List<double> probs = countryArgs
776+
.Select(GetWeightFromRandomGuessArg)
777+
.ToList();
778+
779+
double totalProb = probs.Sum();
780+
781+
int i = matches.Count - 1;
782+
double r = random.NextDouble() * totalProb;
783+
while (r > 0 && i >= 0)
784+
{
785+
Coordinates old = rand;
786+
string match = GetAlpha3FromCodeOrName(matches[i]);
787+
rand = GetRandomPointWithin(match);
788+
789+
if (rand == null)
790+
{
791+
rand = old;
792+
}
793+
794+
r -= probs[i--];
795+
}
796+
797+
if (rand == null)
798+
{
799+
foreach (string m in matches)
800+
{
801+
string match = GetAlpha3FromCodeOrName(m);
802+
rand = GetRandomPointWithin(match);
803+
if (rand != null)
804+
{
805+
break;
806+
}
807+
}
808+
}
809+
}
810+
}
811+
return rand;
812+
}
813+
catch (Exception ex)
814+
{
815+
logger.Error(ex.Summarize());
816+
return rand;
817+
}
818+
}
819+
508820
/// <summary>
509821
/// Get location information of given coordinates <paramref name="point"/>
510822
/// </summary>

0 commit comments

Comments
 (0)