Skip to content

Instantly share code, notes, and snippets.

@ayende
Created June 25, 2024 09:03
Show Gist options
  • Save ayende/49cbff5cb3ba1f3a75f13f8c8fb71bf4 to your computer and use it in GitHub Desktop.
Save ayende/49cbff5cb3ba1f3a75f13f8c8fb71bf4 to your computer and use it in GitHub Desktop.
((double Lat, double Lng) Geo, string Destination, string Time)[] History = [
((32.355354528263994, 34.9002562539242), "Work", "2024-03-25T09:49:00.0000000+02:00"),
((32.20443901405383, 34.93259450598407), "Home", "2024-03-25T16:43:00.0000000+02:00"),
((32.349687437086715, 34.899238492826875), "Work", "2024-03-26T08:10:00.0000000+02:00"),
((32.20752707225241, 34.921327095186875), "Home", "2024-03-26T16:12:00.0000000+02:00"),
((32.354477116520954, 34.892769908553774), "Work", "2024-03-27T09:23:00.0000000+02:00"),
((32.20116825527815, 34.92382260561428), "Home", "2024-03-27T16:43:00.0000000+02:00"),
((32.34109251011839, 34.89341226084858), "Work", "2024-03-28T08:17:00.0000000+02:00"),
((32.205239647103994, 34.93315085030674), "Home", "2024-03-28T16:54:00.0000000+02:00"),
((32.339222505357505, 34.89714722360818), "His Parents", "2024-03-30T13:53:00.0000000+03:00"),
((32.21098586648375, 34.929369243203155), "Home", "2024-03-31T03:18:00.0000000+03:00"),
((32.351412672524255, 34.90358619547384), "Gym", "2024-03-31T07:02:00.0000000+03:00"),
((32.29310528933633, 34.8475444639754), "Work", "2024-03-31T08:51:00.0000000+03:00"),
((32.196358511119676, 34.92551462765405), "Home", "2024-03-31T15:42:00.0000000+03:00"),
((32.351561945752564, 34.90313863111579), "Work", "2024-04-01T08:28:00.0000000+03:00"),
((32.21234703790026, 34.93370500290865), "Home", "2024-04-01T15:27:00.0000000+03:00"),
((32.33769403063862, 34.90978510744675), "Work", "2024-04-02T09:38:00.0000000+03:00"),
((32.20650308166056, 34.934046329241085), "Home", "2024-04-02T17:53:00.0000000+03:00"),
((32.35336968928552, 34.902375494852265), "Work", "2024-04-03T07:53:00.0000000+03:00"),
((32.19607180708209, 34.92333316168208), "Home", "2024-04-03T15:46:00.0000000+03:00"),
((32.336853735875394, 34.90546386294724), "Her Parents", "2024-04-06T11:02:00.0000000+03:00"),
((32.21486658368296, 34.9285295120323), "Home", "2024-04-06T19:06:00.0000000+03:00"),
((32.3456753118718, 34.89795037398724), "Gym", "2024-04-07T07:03:00.0000000+03:00"),
((32.28121127093825, 34.85383292332124), "Work", "2024-04-07T08:33:00.0000000+03:00"),
((32.202541962046354, 34.93221728555143), "Home", "2024-04-07T16:44:00.0000000+03:00"),
((32.354319490812614, 34.89103577987536), "Work", "2024-04-08T09:52:00.0000000+03:00"),
((32.1976762805729, 34.92006697926429), "Home", "2024-04-08T14:11:00.0000000+03:00"),
((32.354675189574216, 34.89546385105261), "Work", "2024-04-09T08:54:00.0000000+03:00"),
((32.203313994234676, 34.9298494062283), "Home", "2024-04-09T18:58:00.0000000+03:00"),
((32.347486629204354, 34.89146135686296), "Work", "2024-04-10T08:30:00.0000000+03:00"),
((32.21584391848423, 34.921532040731265), "Home", "2024-04-10T18:20:00.0000000+03:00"),
((32.339091224693334, 34.89934523007388), "His Parents", "2024-04-13T13:00:00.0000000+03:00"),
((32.20783459114043, 34.931298501926506), "Home", "2024-04-13T23:09:00.0000000+03:00"),
((32.35394166465133, 34.90934654784728), "Work", "2024-04-14T09:59:00.0000000+03:00"),
((32.214964535228255, 34.92400328956001), "Home", "2024-04-14T15:20:00.0000000+03:00"),
((32.339538454218, 34.89315798774772), "Work", "2024-04-15T08:41:00.0000000+03:00"),
((32.20709533980929, 34.92856037642775), "Home", "2024-04-15T15:43:00.0000000+03:00"),
((32.34689134381371, 34.90047711725732), "Work", "2024-04-16T09:16:00.0000000+03:00"),
((32.21480610798368, 34.93583303702407), "Home", "2024-04-16T15:07:00.0000000+03:00"),
((32.34157607048966, 34.90739516095503), "Work", "2024-04-17T09:24:00.0000000+03:00"),
((32.19662830424501, 34.932965175023604), "Home", "2024-04-17T14:57:00.0000000+03:00"),
((32.35055624342156, 34.907113171202155), "Work", "2024-04-18T08:52:00.0000000+03:00"),
((32.210161235155994, 34.9361222497149), "Home", "2024-04-18T17:16:00.0000000+03:00"),
((32.34299008521176, 34.90381049877714), "Her Parents", "2024-04-20T13:18:00.0000000+03:00"),
((32.19747009925382, 34.93588416318614), "Home", "2024-04-20T20:35:00.0000000+03:00"),
((32.34844582020083, 34.90638995725594), "Gym", "2024-04-21T08:06:00.0000000+03:00"),
((32.290107486785445, 34.85446943188519), "Work", "2024-04-21T09:43:00.0000000+03:00"),
((32.21171874754776, 34.92359082084134), "Home", "2024-04-21T18:16:00.0000000+03:00"),
((32.33831443797631, 34.90166019014069), "Work", "2024-04-22T09:16:00.0000000+03:00"),
((32.198516434556616, 34.924546601989114), "Home", "2024-04-22T15:33:00.0000000+03:00"),
((32.34536860937939, 34.910490999868486), "Work", "2024-04-23T09:28:00.0000000+03:00"),
((32.20439670714099, 34.91708041866547), "Home", "2024-04-23T16:01:00.0000000+03:00"),
((32.337007507028375, 34.89750305895874), "Work", "2024-04-24T08:55:00.0000000+03:00"),
((32.19747802714215, 34.91921303306505), "Home", "2024-04-24T17:16:00.0000000+03:00"),
((32.34881149971922, 34.90532672631827), "Work", "2024-04-25T09:04:00.0000000+03:00"),
((32.204112078036886, 34.921694737983294), "Home", "2024-04-25T14:43:00.0000000+03:00"),
((32.350458167478386, 34.89869608598839), "Her Parents", "2024-04-26T11:54:00.0000000+03:00"),
((32.211500782416344, 34.93537956136123), "Home", "2024-04-26T21:35:00.0000000+03:00"),
((32.34211196586319, 34.89313507070821), "Her Parents", "2024-04-27T13:36:00.0000000+03:00"),
((32.20275536344345, 34.92345959204694), "Home", "2024-04-27T21:30:00.0000000+03:00"),
((32.33874952930543, 34.90342557390613), "Gym", "2024-04-28T06:00:00.0000000+03:00"),
((32.28900236795752, 34.85180758536501), "Work", "2024-04-28T07:23:00.0000000+03:00"),
((32.20009221789231, 34.91728159962269), "Home", "2024-04-28T16:37:00.0000000+03:00"),
((32.34675364386948, 34.90078984346078), "Work", "2024-04-29T08:41:00.0000000+03:00"),
((32.205925406538576, 34.926567639054326), "Home", "2024-04-29T16:58:00.0000000+03:00"),
((32.350779690047595, 34.89160099869478), "Work", "2024-04-30T08:51:00.0000000+03:00"),
((32.20715498129946, 34.92968716752862), "Home", "2024-04-30T17:10:00.0000000+03:00"),
((32.335885231359065, 34.892751958585755), "Work", "2024-05-01T08:37:00.0000000+03:00"),
((32.20379286933093, 34.92391444909922), "Home", "2024-05-01T18:35:00.0000000+03:00"),
((32.34579887874745, 34.893740886343046), "Her Parents", "2024-05-03T11:04:00.0000000+03:00"),
((32.204804327073575, 34.926150865483706), "Home", "2024-05-03T23:19:00.0000000+03:00"),
((32.33927163053143, 34.90742080359821), "Her Parents", "2024-05-04T10:32:00.0000000+03:00"),
((32.19768378777122, 34.91667346750477), "Home", "2024-05-04T23:32:00.0000000+03:00"),
((32.3489877489163, 34.910246343779455), "Gym", "2024-05-05T07:03:00.0000000+03:00"),
((32.28646826035535, 34.84922000082057), "Work", "2024-05-05T08:25:00.0000000+03:00"),
((32.20781730848673, 34.91995180378761), "Home", "2024-05-05T17:26:00.0000000+03:00"),
((32.35510804826788, 34.9030456202128), "Work", "2024-05-06T07:56:00.0000000+03:00"),
((32.21101831070671, 34.92995836067528), "Home", "2024-05-06T16:11:00.0000000+03:00"),
((32.35113335173645, 34.90292441601019), "Work", "2024-05-07T09:09:00.0000000+03:00"),
((32.19838720577387, 34.927240188162195), "Home", "2024-05-07T18:39:00.0000000+03:00"),
((32.353299545720574, 34.89745217862905), "Work", "2024-05-08T09:33:00.0000000+03:00"),
((32.19964746528955, 34.928030864880235), "Home", "2024-05-08T18:30:00.0000000+03:00"),
((32.34494112250143, 34.90874125408338), "Work", "2024-05-09T09:18:00.0000000+03:00"),
((32.207767902004576, 34.928583992539274), "Home", "2024-05-09T18:11:00.0000000+03:00"),
((32.35354294477932, 34.894902217590364), "Her Parents", "2024-05-10T12:44:00.0000000+03:00"),
((32.20401830244865, 34.93582820597121), "Home", "2024-05-11T03:13:00.0000000+03:00"),
((32.34502002757485, 34.89731347711218), "His Parents", "2024-05-11T10:55:00.0000000+03:00"),
((32.21143260247044, 34.92741392919891), "Home", "2024-05-11T19:41:00.0000000+03:00"),
((32.338426177193455, 34.893163521094856), "Gym", "2024-05-12T06:02:00.0000000+03:00"),
((32.29337113592004, 34.85954212335156), "Work", "2024-05-12T07:46:00.0000000+03:00"),
((32.204611545642514, 34.92592250014943), "Home", "2024-05-12T15:10:00.0000000+03:00"),
((32.34359466630336, 34.90413943275171), "Work", "2024-05-13T09:41:00.0000000+03:00"),
((32.20073370781909, 34.92950662880915), "Home", "2024-05-13T18:57:00.0000000+03:00"),
((32.34484526261022, 34.901439311506806), "Work", "2024-05-14T08:36:00.0000000+03:00"),
((32.198352352911634, 34.922556917174575), "Home", "2024-05-14T17:52:00.0000000+03:00"),
((32.342367567427985, 34.90446908945237), "Work", "2024-05-15T08:48:00.0000000+03:00"),
((32.20934262596354, 34.92235202777323), "Home", "2024-05-15T16:12:00.0000000+03:00"),
((32.34870579212682, 34.90065676357046), "His Parents", "2024-05-17T10:32:00.0000000+03:00"),
((32.206466152194494, 34.932140348827105), "Home", "2024-05-17T22:35:00.0000000+03:00"),
((32.350870278712954, 34.90970109354663), "His Parents", "2024-05-18T11:23:00.0000000+03:00"),
((32.21443688272355, 34.928807917703345), "Home", "2024-05-18T21:29:00.0000000+03:00"),
((32.346065551844916, 34.89134471085655), "Gym", "2024-05-19T07:25:00.0000000+03:00"),
((32.28156686527692, 34.85340281424257), "Work", "2024-05-19T09:13:00.0000000+03:00"),
((32.203381158558095, 34.92775196304094), "Home", "2024-05-19T16:46:00.0000000+03:00"),
((32.344826719974996, 34.90787611698911), "Work", "2024-05-20T09:45:00.0000000+03:00"),
((32.20536690310602, 34.9258015178195), "Home", "2024-05-20T18:53:00.0000000+03:00"),
((32.352254654594425, 34.90887434202967), "Work", "2024-05-21T09:54:00.0000000+03:00"),
((32.21459739979381, 34.92605409394667), "Home", "2024-05-21T15:47:00.0000000+03:00"),
((32.33604625307686, 34.903002897527415), "Work", "2024-05-22T08:49:00.0000000+03:00"),
((32.20102522268431, 34.933270235186406), "Home", "2024-05-22T15:26:00.0000000+03:00"),
((32.34592400029836, 34.905814336474485), "Work", "2024-05-23T09:01:00.0000000+03:00"),
((32.21481648044812, 34.927228521138446), "Home", "2024-05-23T16:01:00.0000000+03:00"),
];
Trip[] trips = History.Select(x => new Trip(x.Geo.Lat, x.Geo.Lng, x.Destination, DateTime.Parse(x.Time))).ToArray();
var historyByDest = new Dictionary<string, List<double[]>>();
foreach (var trip in trips)
{
if (historyByDest.TryGetValue(trip.Destination, out var list) is false)
{
historyByDest[trip.Destination] = list = new();
}
list.Add([
trip.Lat,
trip.Lng,
trip.Time.Hour * 100 + trip.Time.Minute,
trip.Time.DayOfYear,
(int)trip.Time.DayOfWeek
]);
}
var home = (32.33583, 34.89052);
var dests = SuggestDestination(home,
//new DateTime(2024,6,23, 07,00,00), // sunday morning
//new DateTime(2024, 6, 22, 12, 00, 00), // saturday noon
new DateTime(2024, 6, 24, 9, 00, 00), // monday morning
historyByDest);
foreach(var d in dests)
{
Console.WriteLine(d);
}
//GenerateData();
string[] SuggestDestination((double Lat, double Lng) location, DateTime now, Dictionary<string, List<double[]>> historyByDest)
{
double[] compare = [location.Lat, location.Lng, now.Hour * 100 + now.Minute, now.DayOfYear, (int)now.DayOfWeek];
List<(string Dest, double Score)> scores = new();
foreach (var (dest, items) in historyByDest)
{
double score = 0;
foreach (var cur in items)
{
for (var i = 0; i < cur.Length; i++)
{
score += Math.Abs(cur[i] - compare[i]);
}
}
score /= items.Count;
scores.Add((dest, score));
}
scores.Sort((x, y) => x.Score.CompareTo(y.Score));
return scores.Select(x => x.Dest).Take(3).ToArray();
}
////GenerateData();
void GenerateData()
{
var start = DateTime.Today.AddMonths(-3);
for (int i = 0; i < 60; i++)
{
var cur = start.AddDays(i);
switch (cur.DayOfWeek)
{
case DayOfWeek.Sunday:
if (PrintGym(80, cur) == false)
PrintWork(95, cur);
break;
case DayOfWeek.Monday:
case DayOfWeek.Tuesday:
case DayOfWeek.Wednesday:
PrintWork(95, cur);
break;
case DayOfWeek.Thursday:
PrintWork(50, cur);
break;
case DayOfWeek.Friday:
PrintParents(60, cur);
break;
case DayOfWeek.Saturday:
PrintParents(80, cur);
break;
}
}
bool PrintGym(int chance, DateTime cur)
{
if (Random.Shared.Next(0, 100) > chance)
return false;
double[] home = [
32.33583 + Random.Shared.NextDouble() / 50,
34.89052 + Random.Shared.NextDouble() / 50
];
double[] gym = [
32.273666 + Random.Shared.NextDouble() / 50,
34.842991 + Random.Shared.NextDouble() / 50
];
double[] work = [
32.19593 + Random.Shared.NextDouble() / 50,
34.91666 + Random.Shared.NextDouble() / 50
];
var start = cur.AddMinutes(Random.Shared.Next(360, 500));
Console.WriteLine($"(({home[0]},{home[1]}),\"Gym\",\"{start:O}\"),");
var goToWork = start.AddMinutes(Random.Shared.Next(80, 120));
Console.WriteLine($"(({gym[0]},{gym[1]}),\"Work\",\"{goToWork:O}\"),");
var end = cur.AddMinutes(Random.Shared.Next(850, 1140));
Console.WriteLine($"(({work[0]},{work[1]}),\"Home\",\"{end:O}\"),");
return true;
}
void PrintParents(int chance, DateTime cur)
{
if (Random.Shared.Next(0, 100) > chance)
return;
double[] home = [
32.33583 + Random.Shared.NextDouble() / 50,
34.89052 + Random.Shared.NextDouble() / 50
];
double[] hisParents = [
32.19593 + Random.Shared.NextDouble() / 50,
34.91666 + Random.Shared.NextDouble() / 50
];
double[] herParents = [
32.19593 + Random.Shared.NextDouble() / 50,
34.91666 + Random.Shared.NextDouble() / 50
];
var parents = Random.Shared.NextDouble() > 0.5 ? ("His Parents", hisParents) : ("Her Parents", herParents);
var start = cur.AddMinutes(Random.Shared.Next(600, 850));
Console.WriteLine($"(({home[0]},{home[1]}),\"{parents.Item1}\",\"{start:O}\"),");
var goHome = start.AddMinutes(Random.Shared.Next(300, 900));
Console.WriteLine($"(({parents.Item2[0]},{parents.Item2[1]}),\"Home\",\"{goHome:O}\"),");
}
void PrintWork(int chance, DateTime cur, TimeSpan adjust = default)
{
if (Random.Shared.Next(0, 100) > chance)
return;
double[] home = [
32.33583 + Random.Shared.NextDouble() / 50,
34.89052 + Random.Shared.NextDouble() / 50
];
double[] work = [
32.19593 + Random.Shared.NextDouble() / 50,
34.91666 + Random.Shared.NextDouble() / 50
];
var start = cur.AddMinutes(Random.Shared.Next(470, 600)) + adjust;
Console.WriteLine($"(({home[0]},{home[1]}),\"Work\",\"{start:O}\"),");
var end = cur.AddMinutes(Random.Shared.Next(850, 1140));
Console.WriteLine($"(({work[0]},{work[1]}),\"Home\",\"{end:O}\"),");
}
}
public record Trip(double Lat, double Lng, string Destination, DateTime Time);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment