From 27a4a1cfb4aecac0f245796482ca8538a8b2e16e Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Mon, 26 Sep 2022 14:59:51 -0700 Subject: [PATCH] More strict birthday logic --- .vscode/launch.json | 36 +++++++++ Distance/Models/_E_Distance.cs | 12 +-- Instance/DlibDotNet.cs | 59 ++++++-------- Map/Models/Stateless/MapLogic.cs | 79 ++++++------------- Map/Models/Stateless/Methods/IMapLogic.cs | 8 +- Shared/Models/Methods/IFaceDistance.cs | 2 +- Shared/Models/Stateless/Methods/IAge.cs | 2 +- .../Stateless/Methods/IPersonContainer.cs | 5 ++ .../Stateless/Methods/PersonBirthday.cs | 6 +- .../Stateless/Methods/PersonContainer.cs | 76 ++++++++++++++++-- Tests/UnitTestCalculations.cs | 63 +++++++++++++++ 11 files changed, 237 insertions(+), 111 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1e8dcb9..d964162 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -54,6 +54,10 @@ // (637987913910140924) 9/14/2022 10:29 PM - 113 *.jpg && 109 *.json // (637989361172096980) 9/16/2022 02:41 PM - 094 *.jpg && 026 *.json // All including (637991052364021796) 9/18/2022 1:40 PM - 17435 *.jpg && 16237 *.json = 93.128763980499% with int match only +// List of people with current person key formatted in tab form +// Exclusion list for Robert +// Person birthday allow # +// Host face directory on Ubuntu // https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/49158951_2264915190186558_112485584324263936_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=84a396&_nc_ohc=Q78znguHVeMAX88OKg9&_nc_ht=scontent-lax3-2.xx&oh=00_AT_gJFk9xytYuXp9p5smDm0mMDXzsPnFS_EfKEbiL3KYqg&oe=63523F37 // https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/290625560_10217841255422109_3297482250419620718_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=730e14&_nc_ohc=O3ybqwDLK9AAX_V0FGP&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT-9rtBghXU7lAGkOy4KPHbV9Kyj8DGm-BGtUabWgQJbOg&oe=63335209 // https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/243093116_10216723829287154_8982585928017225043_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=730e14&_nc_ohc=TW6UDC8v9egAX-_YcWf&_nc_ht=scontent-lax3-1.xx&oh=00_AT8rE2JOfkJINSsA5imGVBDbXNDvxx1_uZn0sLM-6ITDUw&oe=633238A9 @@ -109,3 +113,35 @@ // https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/230074448_10103880528811228_6909448863476427135_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=0debeb&_nc_ohc=cUpp1Y_DO8MAX92tN_t&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT-K2_yEERUmvvjkjUKf7zwaV2Ofq1fHIQAtEkCt7I2Bhw&oe=63352B95 // https://scontent-lax3-2.xx.fbcdn.net/v/t31.18172-8/13502600_10210212049485607_95598559411189791_o.jpg?_nc_cat=101&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=AEojM0a2X5cAX8kmHfZ&_nc_ht=scontent-lax3-2.xx&oh=00_AT-ZX7vIfwazh_zcDpFCLxwLgp90gERyBG2CtGxIClEnYA&oe=6355A9C7 // https://scontent-lax3-2.xx.fbcdn.net/v/t31.18172-8/14195939_1314130471931770_9026437168267009241_o.jpg?_nc_cat=106&ccb=1-7&_nc_sid=730e14&_nc_ohc=f8owaBX7kMQAX8ioj3m&_nc_ht=scontent-lax3-2.xx&oh=00_AT8N8GR4GXmKa3w_dP952fl1_bx_s7CTz8qFtxaBK91S2w&oe=6355DBA1 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/67428022_1287438048070254_7628190366730027008_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=b9115d&_nc_ohc=wO9dTzPDXjcAX85VZFY&_nc_ht=scontent-lax3-1.xx&oh=00_AT9ZDKZuwlVncwGAKb6fkty_AaqnBNmKj46n2L3V1Y_V5w&oe=63589442 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/95959209_10221111135660559_6413640771529867264_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=730e14&_nc_ohc=tN-1cmyDpEsAX-GecHc&_nc_ht=scontent-lax3-2.xx&oh=00_AT9w87N6Gq277785G3f6iF5IhEtBtJ7FTZwxkK5dipNqOw&oe=63575F14 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/207486_1959635958499_5198863_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=2c4854&_nc_ohc=Z2KnsIT4a60AX9wPnkk&_nc_ht=scontent-lax3-2.xx&oh=00_AT8Vxh2vW53SBZ4sH9cgZEofWKOUnpf8fpMjQRjZGCR6oQ&oe=6355FB36 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/37219804_10213591073105306_9108104030982242304_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=pngJAV_sIesAX8zSJG-&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT8UXpCCDSQ8uOPtSrdzcty0tSpO6TCEKCL-K7q-BMb5CA&oe=6357898C +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/427539_3441473049618_710901137_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=3DPj0_PEbSsAX9ryGz1&_nc_ht=scontent-lax3-2.xx&oh=00_AT9t82wuMvW2xdHA8E1VokNBzIhHtgBbpH8fvrIxE_0rPQ&oe=6357DCF0 +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/241548211_237343028191419_6995991527624737723_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=nsC7CBQxaO8AX-De2g8&_nc_ht=scontent-lax3-1.xx&oh=00_AT_V2gvedewiVuhPIozJyq4ccKm6WoxBkXe0Ocm1fTZ3wA&oe=63365FAA +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/10253934_10152334525164461_3158331570278601806_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=ba80b0&_nc_ohc=0A0Haq5W-IgAX8Y28oA&_nc_ht=scontent-lax3-1.xx&oh=00_AT-3tqlxtQj1n0D5t1jzVfQi22q3OMyQQrBcw2ZBrmYGaA&oe=6356ACAB +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/308817118_10218508885627876_6441766117990882318_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=730e14&_nc_ohc=1kMU8trJLw4AX_R76M2&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT9k53CcIY7KnW3CjRR4bbE8wjuAUVVi6D1an-kcbOaF2g&oe=63363C9E +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/41038997_10156771390897533_9196241072043327488_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=174925&_nc_ohc=CK2PqvoqhVsAX9xGRSK&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT8qHnIW7OsQMRb7htRwC7byyqcK4X5qAkdz8IM4caO_iA&oe=6357DA17 +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/279316302_4583494791751734_5208076832025426501_n.jpg?_nc_cat=109&ccb=1-7&_nc_sid=e3f864&_nc_ohc=Mt2sOGHVzbMAX-ghCmr&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT_xdFzERKvZfApmuZ19H39uWsTz0vrJR7fivTuaLGiE1g&oe=63372D6C +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/213757548_10222718701187533_9216326465615113019_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=bMlCbM1DFccAX-UEjOE&_nc_oc=AQlwSf-Xrfqx-ldXQ8cz-gImrOZnTfVoNReVucU0i3C--RLTsfldVzKT8ij7sn7Jn3E&_nc_ht=scontent-lax3-2.xx&oh=00_AT-YAQ9scfYOoaPy5Kzb6yWcpe4t5MNTfE1pAP-RD3oBAA&oe=63379E32 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/1005197_172610252919953_1797035311_n.jpg?_nc_cat=102&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=9wV_ZoGuDfQAX9ZQWRM&_nc_ht=scontent-lax3-1.xx&oh=00_AT_M3_rgENbCEjmouX8Ar_N_s-P5Tke0TvPzza0Mwx90dg&oe=635764FD +// https://scontent-lax3-1.xx.fbcdn.net/v/t31.18172-8/24130218_2001836833160114_7527164989319060274_o.jpg?_nc_cat=104&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=ZxM5zjih3tYAX8IsXx9&_nc_ht=scontent-lax3-1.xx&oh=00_AT-G2-I-OXpcoq9TKqn_YT3gObzj8GMavpJe-KH7xj_5Lg&oe=6357091E +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/11745695_10206235519080812_1953505210138379535_n.jpg?_nc_cat=109&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=RDqIQjOVB0AAX8Q90_Z&_nc_ht=scontent-lax3-1.xx&oh=00_AT_FogaOVWhgLcesEzaidYx--sKeBVCD6xDg2IWJdvcafA&oe=6356095A +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/280118285_2094899397354077_5352291217200307805_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=YQDlNI2xTrIAX-curq5&_nc_ht=scontent-lax3-2.xx&oh=00_AT8SuwF2W7tioXfAfCCun6zQsrIUjArOSr0ZlRb3F_Ej2Q&oe=63378827 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/13233144_10101471840461827_9039193337970955304_n.jpg?_nc_cat=107&ccb=1-7&_nc_sid=cdbe9c&_nc_ohc=aiRRaotqsnYAX-slwLd&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT_CxgSXV-0uNiiz_jLV_s3cPAk2vUyoro5MVsXsVyiEcg&oe=6358E40F +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/305309404_10220461241674046_1323434462733520520_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=NajFsslaLvcAX8-Kuz_&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT89eIRz0st3qjPnhURiW9W7wXbaOV0usVykQiKRL_TRhg&oe=6337A145 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/32481784_10216908834904287_1754862128918953984_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=8mU2Cf_iAFwAX80s1xj&_nc_ht=scontent-lax3-2.xx&oh=00_AT8SXOmaqoNTZvBik5j4hE7YEenshkhPggwNgfLdIjIn4g&oe=6355E4D5 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/22814020_10211731412395324_9169598565701382472_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=UTLq0qx2PQwAX-Y9rIg&_nc_ht=scontent-lax3-2.xx&oh=00_AT_T9Bqd0LwRhuUkbMuUHQcCxcB7I3TAumrw7BR-UuEe3Q&oe=63563325 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/94927050_10220780432954871_7311541287197343744_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=qJofGIany9YAX_15Uhx&_nc_ht=scontent-lax3-1.xx&oh=00_AT_K9V-fQ-IOdVE3BtUQCtFvljScg3xdbjWK8LWh0fs3EQ&oe=6355F4D6 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/47685020_2061588197234140_3115001451777097728_n.jpg?_nc_cat=103&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=g2_slmBopOEAX-kvLeT&_nc_ht=scontent-lax3-2.xx&oh=00_AT9CXSXrom34MSI2zgqXx7qdPKAn8fhKG8dBqGE3l1c_Nw&oe=63567CA6 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.6435-9/39221047_10156127305716865_6824896341232058368_n.jpg?_nc_cat=106&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=osdlvseA5vkAX9zsbYp&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT96aJo9mM_AXgkaQau0AYQ6GgMk3m02z4fpuT1FwYvXtw&oe=6357B649 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/11037634_10204752644508765_3331659968007967889_n.jpg?_nc_cat=107&ccb=1-7&_nc_sid=730e14&_nc_ohc=mjDY6IkATEoAX_WhE62&_nc_ht=scontent-lax3-2.xx&oh=00_AT8gl0GngVzWAynqGAC8zrgZUqAEgahMmzE5X41KpPnYxQ&oe=635825BA +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/36371667_10213980051274137_6162910755566911488_n.jpg?_nc_cat=102&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=-j6ofEojPiIAX-yLrVV&_nc_ht=scontent-lax3-1.xx&oh=00_AT9ZvpazeIfHclhHr24SguNiu0m4WMAj2k5jm2I40JIv5w&oe=635612A1 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/13938350_626048368466_6216870049337020892_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=AbgIJkB2bH4AX-TuAoA&_nc_ht=scontent-lax3-2.xx&oh=00_AT-o0wi5Cz5vl1WDgcDm2BneTIBTuR-__qxxmR-3Fgyg_w&oe=63579473 +// https://scontent-lax3-1.xx.fbcdn.net/v/t39.30808-6/306356815_5223195104456342_2659949811667496237_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=730e14&_nc_ohc=NQdsObWTav0AX9EbW12&_nc_ht=scontent-lax3-1.xx&oh=00_AT8v-jsilYOUGKvQdlt7PXQmbdJRfZD0-GdycokWq-aNwg&oe=63365BAB +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/44500772_10217404839095591_8903105516822069248_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=RqwiyNoil04AX_Y4FGb&_nc_ht=scontent-lax3-1.xx&oh=00_AT85t0AjyzMXSj_UcUhKqWf7ZXdQOFAy12aFdeOO9cjBYg&oe=6356ED81 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/23659202_10212567297792300_7982751930141302131_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=ad2b24&_nc_ohc=9vxjTRupUuAAX8fJ3Qa&_nc_ht=scontent-lax3-2.xx&oh=00_AT8wFIaUMmI2_kLSejxewgzzMK6g0ngEJVfhEQukM0zQdQ&oe=63596B35 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.6435-9/92554157_10158297246718523_986365937043111936_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=lWhPQlbtKVoAX-4D9Ke&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-1.xx&oh=00_AT_P1suJEkfnHlSL3rPoDoYW2exSg_gQyN--HoylQbt_JQ&oe=63567442 +// https://scontent-lax3-2.xx.fbcdn.net/v/t39.30808-6/280689051_10209840036394561_8737214584492733274_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=iMAAHqNekCgAX8fvEAm&_nc_ht=scontent-lax3-2.xx&oh=00_AT8b7_ODsDN7lNgTKr7JZiUE65R7WWYxENl1vOUGeobpBw&oe=6336E678 +// https://scontent-lax3-1.xx.fbcdn.net/v/t1.18169-9/25110_107749419250772_1842086_n.jpg?_nc_cat=104&ccb=1-7&_nc_sid=09cbfe&_nc_ohc=xPyRCvImlaoAX9Z_UTs&_nc_ht=scontent-lax3-1.xx&oh=00_AT85xffhHDJlhzyFTBvWs8j3Gd4GyDCte_Pnd7hNM006sw&oe=635880C2 +// https://scontent-lax3-2.xx.fbcdn.net/v/t1.18169-9/10259940_10153561109653458_6837681277740526675_n.jpg?_nc_cat=100&ccb=1-7&_nc_sid=8bfeb9&_nc_ohc=T1v9Wfqz8rUAX8y6bxq&tn=D0unuoVdv--xjhpM&_nc_ht=scontent-lax3-2.xx&oh=00_AT9Y9j5s19n0EzgO_dZMom8tAweFYIrJLOEsrsr4HAWHkQ&oe=63588CAE \ No newline at end of file diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index be23bc4..7992435 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -249,7 +249,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance }); } - void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string a2PeopleSingletonDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) + void Shared.Models.Methods.IFaceDistance.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string? a2PeopleSingletonDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { char @char; string json; @@ -267,7 +267,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true }; foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer) { - if (personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) + if (a2PeopleSingletonDirectory is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) continue; personBirthday = personContainer.Birthdays[zero]; personDisplayDirectoryName = personDisplayDirectoryNames[^1]; @@ -586,7 +586,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance return results; } - public (int, int, int) GetUnableToMatchCountAndRenameMatches(string facesFileNameExtension, string eDistanceContentDirectory, MappingFromItem mappingFromItem, List faces, List<(string MappedFaceFile, int normalizedPixelPercentage)> collection) + public (int, int, int) GetUnableToMatchCountAndRenameMatches(string facesFileNameExtension, string? eDistanceContentDirectory, MappingFromItem mappingFromItem, List faces, List<(string MappedFaceFile, int normalizedPixelPercentage)> collection) { int result = 0; string? json; @@ -612,7 +612,7 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance if (json is null) { result++; - if (_DistanceMoveUnableToMatch) + if (!string.IsNullOrEmpty(eDistanceContentDirectory) && _DistanceMoveUnableToMatch) MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile); continue; } @@ -635,14 +635,14 @@ public class E_Distance : Shared.Models.Methods.IFaceDistance if (!checkFaces.Any()) { result++; - if (_DistanceMoveUnableToMatch) + if (!string.IsNullOrEmpty(eDistanceContentDirectory) && _DistanceMoveUnableToMatch) MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile); continue; } if (checkFaces.Count != 1) { result++; - if (_DistanceMoveUnableToMatch) + if (!string.IsNullOrEmpty(eDistanceContentDirectory) && _DistanceMoveUnableToMatch) MoveUnableToMatch(eDistanceContentDirectory, mappedFaceFile); continue; } diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 91ac1e6..b8b0067 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -129,10 +129,7 @@ public partial class DlibDotNet if (rootResultsDirectory is null) throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); - personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers( - storage, - configuration.PersonBirthdayFormat, - _Faces.FileNameExtension); + personContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat, _Faces.FileNameExtension); } if (!isSilent && configuration.TestDistanceResults) { @@ -363,7 +360,7 @@ public partial class DlibDotNet return result; } - private void FullParallelForWork(A_Property propertyLogic, Dictionary> idToMappedFaceFilesCollection, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List?> imageFaceCollections, Container container, int index, Item item) + private void FullParallelForWork(A_Property propertyLogic, Dictionary> idToMappedFaceFilesCollection, string outputResolution, string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string? eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, List>> metadataCollections, List> resizeKeyValuePairs, List?> imageFaceCollections, Container container, int index, Item item) { if (item.ImageFileHolder is null) throw new NullReferenceException(nameof(item.ImageFileHolder)); @@ -461,7 +458,7 @@ public partial class DlibDotNet string bResultsFullGroupDirectory, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, - string eDistanceContentDirectory, + string? eDistanceContentDirectory, List> sourceDirectoryChanges, List propertyFileHolderCollection, List propertyCollection, @@ -740,7 +737,7 @@ public partial class DlibDotNet return results.ToArray(); } - private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers, string eDistanceContentDirectory, Dictionary> idToMappedFaceFilesCollection) + private void FullDoWork(string argZero, Model? model, PredictorModel? predictorModel, string propertyRoot, long ticks, A_Property propertyLogic, int t, Container[] containers, string? eDistanceContentDirectory, Dictionary> idToMappedFaceFilesCollection) { if (_Log is null) throw new NullReferenceException(nameof(_Log)); @@ -891,7 +888,7 @@ public partial class DlibDotNet return results; } - private void DistanceThenMapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string dResultsFullGroupDirectory, string outputResolution) + private void DistanceThenMapLogic(string argZero, long ticks, PersonContainer[] personContainers, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2FacePartsContentDirectory, string eDistanceContentDirectory, string outputResolution) { int? useFiltersCounter = null; SortingContainer[] sortingContainers; @@ -899,9 +896,6 @@ public partial class DlibDotNet List distinctFilteredFaces = SetMappingThenGetDistinctFilteredFacesWithMapping(argZero, containers); Shared.Models.Face[] selectedFilteredFaces = E_Distance.GetSelectedFilteredFaces(distinctFilteredFaces); E_Distance.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, selectedFilteredFaces); - string eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); - string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}"); - string d2FacePartsContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D2_FaceParts), "()"); MapLogic mapLogic = new( _AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, @@ -1008,12 +1002,14 @@ public partial class DlibDotNet int f; int t; Container[] containers; + string? a2PeopleContentDirectory; string aResultsFullGroupDirectory; string bResultsFullGroupDirectory; string cResultsFullGroupDirectory; string dResultsFullGroupDirectory; - string eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); - Dictionary> idToMappedFaceFilesCollection = Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(_MapConfiguration, _Faces.FileNameExtension, ticks, eDistanceContentDirectory, personContainers); + string? eDistanceContentDirectory; + string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}"); + string d2FacePartsContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D2_FaceParts), "()"); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Container(s) - {totalSeconds} total second(s)"; A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, model, predictorModel); @@ -1024,22 +1020,24 @@ public partial class DlibDotNet (j, f, t, containers) = Property.Models.Stateless.Container.GetContainers(_Configuration.PropertyConfiguration, _FirstRun, propertyLogic); } Container? container = AreAllSameEndsWith(argZero, containers); - if (_ArgZeroIsConfigurationRootDirectory && container is not null) + if (!_ArgZeroIsConfigurationRootDirectory || container is null) { + a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); + eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); + } + else + { + a2PeopleContentDirectory = null; + eDistanceContentDirectory = null; string? newRootDirectory = SaveUrlAndGetNewRootDirectory(container); for (int i = 1; i < 10; i++) - _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Property.Models.Stateless.IResult.GetResultsGroupDirectory( - _Configuration.PropertyConfiguration, - string.Empty, - create: true)); + _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true)); argZero = newRootDirectory; _Configuration.PropertyConfiguration.ChangeRootDirectory(newRootDirectory); - propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory( - _Configuration.PropertyConfiguration, - nameof(A_Property), - create: false); + propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, model, predictorModel); } + Dictionary> idToMappedFaceFilesCollection = Map.Models.Stateless.Methods.IMapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(_MapConfiguration, _Faces.FileNameExtension, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers); FullDoWork(argZero, model, predictorModel, propertyRoot, ticks, propertyLogic, t, containers, eDistanceContentDirectory, idToMappedFaceFilesCollection); foreach (string outputResolution in _Configuration.OutputResolutions) { @@ -1050,28 +1048,21 @@ public partial class DlibDotNet && _Configuration.SaveResizedSubfiles && outputResolution == _Configuration.OutputResolutions[0] && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) - && _Exceptions.Count == 0) + && _Exceptions.Count == 0 + && !string.IsNullOrEmpty(eDistanceContentDirectory)) { if (!_Configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions.Any()) break; - DistanceThenMapLogic(argZero, ticks, personContainers, containers, dResultsFullGroupDirectory, outputResolution); + DistanceThenMapLogic(argZero, ticks, personContainers, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2FacePartsContentDirectory, eDistanceContentDirectory, outputResolution); if (_IsEnvironment.Development) continue; if (_FileKeyValuePairs.Any()) _Random.Random(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], _FileKeyValuePairs); G2_Identify identify = new(_Configuration); - List identifiedCollection = identify.GetIdentifiedCollection( - _IsEnvironment, - _Configuration.PropertyConfiguration, - _Faces.FileNameExtension); + List identifiedCollection = identify.GetIdentifiedCollection(_IsEnvironment, _Configuration.PropertyConfiguration, _Faces.FileNameExtension); identify.WriteAllText(_Configuration.PropertyConfiguration, _Configuration.OutputResolutions[0], identifiedCollection); if (_Configuration.LoadOrCreateThenSaveIndex && _FilePropertiesKeyValuePairs.Any()) - _Index.SetIndex( - _Configuration.PropertyConfiguration, - model, - predictorModel, - _Configuration.OutputResolutions[0], - _FilePropertiesKeyValuePairs); + _Index.SetIndex(_Configuration.PropertyConfiguration, model, predictorModel, _Configuration.OutputResolutions[0], _FilePropertiesKeyValuePairs); } if (!_IsEnvironment.Development) { diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 677fb1d..5d181e6 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -132,8 +132,6 @@ internal abstract class MapLogic { personFirstInitial = personDisplayDirectoryNames[^1][..1]; personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); - if (personNameDirectory != personFirstInitialDirectory) - Directory.Move(personNameDirectory, personFirstInitialDirectory); } files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); if (personKeyFormatted == nameof(IMapLogic.Sorting) && files.Any()) @@ -144,6 +142,11 @@ internal abstract class MapLogic throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!"); if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) continue; + if (personNameDirectory != personFirstInitialDirectory && !Directory.Exists(personFirstInitialDirectory)) + { + Directory.Move(personNameDirectory, personFirstInitialDirectory); + files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); + } foreach (string file in files) { if (file.EndsWith(".lnk") || file.EndsWith(".json")) @@ -194,17 +197,23 @@ internal abstract class MapLogic return results; } - internal static Dictionary> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, PersonContainer[] personContainers) + internal static Dictionary> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, PersonContainer[] personContainers) { Dictionary> results; string personKeyFormatted; + List<(long? PersonKey, string Line)> lines = new(); List personKeyFormattedCollection = new(); _ = GetDistinctCollection(configuration, personContainers.ToList(), new()); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); - string[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); + string[] ticksDirectories; + if (string.IsNullOrEmpty(eDistanceContentDirectory)) + ticksDirectories = Array.Empty(); + else + ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); string message = $") {ticksDirectories.Length:000} collect from and clean ticks Director(ies) - A - {totalSeconds} total second(s)"; foreach (PersonContainer personContainer in personContainers) { + lines.AddRange(IPersonContainer.GetDisplay(configuration.PersonBirthdayFormat, personContainer)); if (personContainer.Person is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any()) continue; foreach (PersonBirthday personBirthday in personContainer.Birthdays) @@ -213,12 +222,9 @@ internal abstract class MapLogic personKeyFormattedCollection.Add(personKeyFormatted); } } - List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection( - configuration, - facesFileNameExtension, - personKeyFormattedCollection, - ticksDirectories, - message); + if (!string.IsNullOrEmpty(a2PeopleContentDirectory)) + File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, "People - C.tsv"), from l in lines orderby l.PersonKey is null select l.Line); + List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, facesFileNameExtension, personKeyFormattedCollection, ticksDirectories, message); results = GetIdToCollection(facesFileNameExtension, collection); return results; } @@ -579,7 +585,7 @@ internal abstract class MapLogic } } - internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, long ticks, List personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, List distinctFilteredFaces, Shared.Models.Methods.IFaceDistance faceDistance, Dictionary personKeyToPersonContainer, Dictionary personKeyToRanges, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> idThenNormalizedPixelPercentageToPersonContainers) + internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, string facesFileNameExtension, long ticks, List personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, List distinctFilteredFaces, Shared.Models.Methods.IFaceDistance faceDistance, Dictionary personKeyToPersonContainer, Dictionary personKeyToRanges, List notMappedPersonContainers, Dictionary> skipCollection, Dictionary> idThenNormalizedPixelPercentageToPersonContainers) { if (configuration is null) throw new NullReferenceException(nameof(configuration)); @@ -594,14 +600,7 @@ internal abstract class MapLogic List<(string, string[], int, int)> personKeyFormattedIdThenNormalizedPixelPercentageCollection = new(); List<(string, int, int)> incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection = new(); Dictionary> incorrectIdThenNormalizedPixelPercentageToPersonContainers = new(); - SetPersonCollections( - configuration, - facesFileNameExtension, - personContainers, - personKeys, - personKeyFormattedToNewestPersonKeyFormatted, - personKeyFormattedCollection, - skipCollection); + SetPersonCollections(configuration, facesFileNameExtension, personContainers, personKeys, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedCollection, skipCollection); personContainers.AddRange(AddToPersonKeysThenGetNonSpecificPeopleCollection(configuration, personKeys)); foreach (Face face in distinctFilteredFaces) { @@ -616,32 +615,9 @@ internal abstract class MapLogic totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string[] ticksDirectories = Directory.GetDirectories(eDistanceContentDirectory, "*", SearchOption.TopDirectoryOnly); message = $") {ticksDirectories.Length:000} compile from and clean ticks Director(ies) - B - {totalSeconds} total second(s)"; - List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection( - configuration, - facesFileNameExtension, - personKeyFormattedCollection, - ticksDirectories, - message); - (int unableToMatchCount, int duplicateCount) = SetCollectionsAndGetUnableToMatchCount( - facesFileNameExtension, - ticks, - keyValuePairs, - personKeyFormattedToNewestPersonKeyFormatted, - personKeyFormattedIdThenNormalizedPixelPercentageCollection, - incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, - collection); - SetKeyValuePairs( - configuration, - ticks, - personContainers, - distinctFilteredFaces, - personKeyFormattedIdThenNormalizedPixelPercentageCollection, - incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, - personKeyToPersonContainer, - idThenNormalizedPixelPercentageToPersonContainers, - possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, - incorrectIdThenNormalizedPixelPercentageToPersonContainers, - personKeyToRanges); + List<(string, string[], string)> collection = DeleteEmptyDirectoriesAndGetCollection(configuration, facesFileNameExtension, personKeyFormattedCollection, ticksDirectories, message); + (int unableToMatchCount, int duplicateCount) = SetCollectionsAndGetUnableToMatchCount(facesFileNameExtension, ticks, keyValuePairs, personKeyFormattedToNewestPersonKeyFormatted, personKeyFormattedIdThenNormalizedPixelPercentageCollection, incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, collection); + SetKeyValuePairs(configuration, ticks, personContainers, distinctFilteredFaces, personKeyFormattedIdThenNormalizedPixelPercentageCollection, incorrectPersonKeyFormattedIdThenNormalizedPixelPercentageCollection, personKeyToPersonContainer, idThenNormalizedPixelPercentageToPersonContainers, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer, incorrectIdThenNormalizedPixelPercentageToPersonContainers, personKeyToRanges); totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); message = $") {collection.Count:000} message from ticks Director(ies) - D - {duplicateCount} Duplicate Count {unableToMatchCount} Unable To Match Count / {collection.Count} Collection - {totalSeconds} total second(s)"; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; @@ -657,18 +633,9 @@ internal abstract class MapLogic long[] personKeyCollection = (from l in nullablePersonKeyCollection where l is not null select l.Value).Distinct().ToArray(); SetPersonKeyToPersonContainer(configuration, personContainers, personKeyCollection, personKeyToPersonContainer); notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeyCollection)); - AppendToSkipCollection( - skipCollection, - idThenNormalizedPixelPercentageToPersonContainers, - incorrectIdThenNormalizedPixelPercentageToPersonContainers); + AppendToSkipCollection(skipCollection, idThenNormalizedPixelPercentageToPersonContainers, incorrectIdThenNormalizedPixelPercentageToPersonContainers); if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any()) - faceDistance.SavePossiblyNewPersonContainers( - propertyConfiguration, - configuration.PersonBirthdayFormat, - facesFileNameExtension, - a2PeopleSingletonDirectory, - personKeyToPersonContainer, - possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + faceDistance.SavePossiblyNewPersonContainers(propertyConfiguration, configuration.PersonBirthdayFormat, facesFileNameExtension, a2PeopleContentDirectory, personKeyToPersonContainer, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } } \ No newline at end of file diff --git a/Map/Models/Stateless/Methods/IMapLogic.cs b/Map/Models/Stateless/Methods/IMapLogic.cs index ef7e5c3..28cdc31 100644 --- a/Map/Models/Stateless/Methods/IMapLogic.cs +++ b/Map/Models/Stateless/Methods/IMapLogic.cs @@ -3,9 +3,9 @@ namespace View_by_Distance.Map.Models.Stateless.Methods; public interface IMapLogic { // ... - Dictionary> TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => - DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, facesFileNameExtension, ticks, eDistanceContentDirectory, personContainers); - static Dictionary> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => - MapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, facesFileNameExtension, ticks, eDistanceContentDirectory, personContainers); + Dictionary> TestStatic_DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => + DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, facesFileNameExtension, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers); + static Dictionary> DeleteEmptyDirectoriesAndGetMappedFaceFiles(Configuration configuration, string facesFileNameExtension, long ticks, string? a2PeopleContentDirectory, string? eDistanceContentDirectory, Shared.Models.PersonContainer[] personContainers) => + MapLogic.DeleteEmptyDirectoriesAndGetMappedFaceFiles(configuration, facesFileNameExtension, ticks, a2PeopleContentDirectory, eDistanceContentDirectory, personContainers); } \ No newline at end of file diff --git a/Shared/Models/Methods/IFaceDistance.cs b/Shared/Models/Methods/IFaceDistance.cs index 5367588..d22f8e9 100644 --- a/Shared/Models/Methods/IFaceDistance.cs +++ b/Shared/Models/Methods/IFaceDistance.cs @@ -3,6 +3,6 @@ namespace View_by_Distance.Shared.Models.Methods; public interface IFaceDistance { - void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string a2PeopleContentDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); + void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, string facesFileNameExtension, string? a2PeopleContentDirectory, Dictionary personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer); } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IAge.cs b/Shared/Models/Stateless/Methods/IAge.cs index 0d633f0..2e968ba 100644 --- a/Shared/Models/Stateless/Methods/IAge.cs +++ b/Shared/Models/Stateless/Methods/IAge.cs @@ -21,7 +21,7 @@ public interface IAge char[] TestStatic_GetChars() => GetChars(); static char[] GetChars() => - new char[] { '!', '^', '_', '~', '+' }; + new char[] { '!', '^', '_', '~', '+', '#' }; int? TestStatic_GetApproximateYears(string personDisplayDirectoryName, char[] chars) => GetApproximateYears(personDisplayDirectoryName, chars); diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index bcb3a1f..9c39bdd 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -10,4 +10,9 @@ public interface IPersonContainer static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, string facesFileNameExtension) => PersonContainer.GetPersonContainers(storage, personBirthdayFormat, facesFileNameExtension); + List<(long?, string)> TestStatic_GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) => + GetDisplay(personBirthdayFormat, personContainer); + static List<(long?, string)> GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) => + PersonContainer.GetDisplay(personBirthdayFormat, personContainer); + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/PersonBirthday.cs b/Shared/Models/Stateless/Methods/PersonBirthday.cs index e480383..3f7fc76 100644 --- a/Shared/Models/Stateless/Methods/PersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/PersonBirthday.cs @@ -13,7 +13,7 @@ internal abstract class PersonBirthday internal static bool DoesBirthDateExits(Properties.IStorage storage, string personBirthdayFormat, Models.PersonBirthday personBirthday) => File.Exists(GetFileFullName(storage, personBirthdayFormat, personBirthday)); internal static Models.PersonBirthday GetNextBirthDate(Properties.IStorage storage) => throw new Exception(storage.ToString()); // Person.GetNextBirthDate(storage); internal static string GetFileFullName(Properties.IStorage storage, string personBirthdayFormat, Models.PersonBirthday personBirthday) => Path.Combine(storage.PeopleRootDirectory, "{}", GetFileName(personBirthdayFormat, personBirthday)); - internal static DateTime? GetDateTime(string personBirthdayFormat, string personKey) => DateTime.TryParseExact(personKey, personBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateTime) ? dateTime : null; + internal static DateTime? GetDateTime(string personBirthdayFormat, string personKey) => DateTime.TryParseExact(personKey.Replace('#', '0'), personBirthdayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateTime) ? dateTime : null; internal static Models.PersonBirthday? GetPersonBirthday(string personBirthdayFormat, string personKey) { @@ -109,7 +109,7 @@ internal abstract class PersonBirthday return result; } - internal static List GetPersonBirthdays(string personBirthdayFormat, string[] personKeyDirectories, string personDisplayDirectory) + internal static Models.PersonBirthday[] GetDescendingOrderedPersonBirthdays(string personBirthdayFormat, string[] personKeyDirectories, string personDisplayDirectory) { List results = new(); string[] files; @@ -130,7 +130,7 @@ internal abstract class PersonBirthday continue; File.WriteAllText(Path.Combine(personKeyDirectory, $"{personKeyFormatted}.txt"), string.Empty); } - return results; + return results.OrderByDescending(l => l.Value.Ticks).ToArray(); } } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index 5aaa99e..647a08a 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -33,7 +33,7 @@ internal abstract class PersonContainer return results; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string personDisplayDirectory, string personDisplayDirectoryName, string[] personKeyDirectories, int? approximateYears, List collections) + private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string personDisplayDirectory, string personDisplayDirectoryName, string[] personKeyDirectories, int? approximateYears, Models.PersonBirthday[] personBirthdays) { List<(long?, Models.PersonContainer)> results = new(); long personKey; @@ -43,7 +43,6 @@ internal abstract class PersonContainer string personKeyFormatted; Models.PersonBirthday? personBirthday; Models.PersonContainer personContainer; - Models.PersonBirthday[] personBirthdays = collections.OrderByDescending(l => l.Value).ToArray(); string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); foreach (string personKeyDirectory in personKeyDirectories) { @@ -51,7 +50,11 @@ internal abstract class PersonContainer personBirthday = IPersonBirthday.GetPersonBirthday(personBirthdayFormat, personKeyFormatted); if (personBirthday is null) continue; + if (!IPersonBirthday.IsCounterPersonBirthday(personBirthday) && ((!personKeyDirectory.Contains('#') && (personDisplayDirectoryName.Contains('~') || personDisplayDirectoryName.Contains('#'))) || (personKeyDirectory.Contains('#') && !personDisplayDirectoryName.Contains('#')))) + throw new NotSupportedException(); personKey = personBirthdays[zero].Value.Ticks; + if (personKey != personBirthdays.OrderByDescending(l => l.Value.Ticks).ToArray()[0].Value.Ticks) + throw new NotSupportedException(); segments = personDisplayDirectoryName.Split(chars); person = IPerson.GetPerson(personKey, segments); personContainer = new(approximateYears, person, personBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey); @@ -68,14 +71,46 @@ internal abstract class PersonContainer return result; } + private static string? VerifyAge(string personDisplayDirectory, string minusOne, string personDisplayDirectoryName, int? approximateYears, Models.PersonBirthday[] personBirthdays) + { + string? result; + if (approximateYears is null) + throw new NotSupportedException(); + if (!personBirthdays.Any()) + throw new NotSupportedException(); + const int zero = 0; + int? updateApproximateYears; + DateTime dateTime = DateTime.Now; + TimeSpan timeSpan = new(personBirthdays[zero].Value.Ticks - dateTime.AddYears(-approximateYears.Value).Ticks); + if (timeSpan.TotalDays < -356) + updateApproximateYears = approximateYears.Value + 1; + else if (timeSpan.TotalDays > 356) + updateApproximateYears = approximateYears.Value - 1; + else + updateApproximateYears = null; + if (updateApproximateYears is null) + result = null; + else + { + result = Path.Combine(minusOne, $"{personDisplayDirectoryName.Split('^')[0]}^{updateApproximateYears}"); + if (Directory.Exists(result)) + result = null; + else + Directory.Move(personDisplayDirectory, result); + } + return result; + } + private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] chars, string[] personDisplayDirectories) { List<(long?, Models.PersonContainer)> results = new(); + string? minusOne; int? approximateYears; + List changes = new(); string[] personKeyDirectories; string? personDisplayDirectoryName; Models.PersonContainer personContainer; - List collections; + Models.PersonBirthday[] personBirthdays; foreach (string personDisplayDirectory in personDisplayDirectories) { personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); @@ -83,15 +118,26 @@ internal abstract class PersonContainer continue; approximateYears = Age.GetApproximateYears(personDisplayDirectoryName, chars); personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); - collections = PersonBirthday.GetPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectory); - if (collections.Any()) - results.AddRange(GetPersonContainersCollections(personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectory, personDisplayDirectoryName, personKeyDirectories, approximateYears, collections)); + personBirthdays = PersonBirthday.GetDescendingOrderedPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectory); + if (personDisplayDirectoryName.Contains('^')) + { + minusOne = Path.GetDirectoryName(personDisplayDirectory); + if (minusOne is null) + continue; + changes.Add(VerifyAge(personDisplayDirectory, minusOne, personDisplayDirectoryName, approximateYears, personBirthdays)); + } + if (changes.Any(l => l is not null)) + continue; + if (personBirthdays.Any()) + results.AddRange(GetPersonContainersCollections(personBirthdayFormat, facesFileNameExtension, chars, personDisplayDirectory, personDisplayDirectoryName, personKeyDirectories, approximateYears, personBirthdays)); else { personContainer = GetPersonContainer(facesFileNameExtension, personDisplayDirectory, personDisplayDirectoryName, approximateYears); results.Add(new(null, personContainer)); } } + if (changes.Any(l => l is not null)) + throw new NotImplementedException($"A directory was changed restart to look for more! {string.Join(Environment.NewLine, (from l in changes where l is not null select l).ToArray())}"); return results; } @@ -138,4 +184,22 @@ internal abstract class PersonContainer return results; } + internal static List<(long?, string)> GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) + { + List<(long?, string)> results = new(); + string personKeyFormatted; + Models.PersonContainer pc = personContainer; + if (pc.Person is null || pc.Key is null || pc.Birthdays is null || !pc.Birthdays.Any()) + results.Add(new(pc.Key, string.Concat('\t', pc.Key, '\t', pc.ApproximateYears, '\t', pc.DisplayDirectoryName))); + else + { + foreach (Models.PersonBirthday personBirthday in pc.Birthdays) + { + personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); + results.Add(new(pc.Key, string.Concat(personKeyFormatted, '\t', pc.Key, '\t', pc.ApproximateYears, '\t', pc.DisplayDirectoryName))); + } + } + return results; + } + } \ No newline at end of file diff --git a/Tests/UnitTestCalculations.cs b/Tests/UnitTestCalculations.cs index 56115cf..265597d 100644 --- a/Tests/UnitTestCalculations.cs +++ b/Tests/UnitTestCalculations.cs @@ -412,4 +412,67 @@ public class UnitTestCalculations Assert.IsTrue(distance == 1.4142135623730951); } + private static (string?, string, string) Get(string[] segments) + { + (string?, string, string) result; + if ((!segments[0].Contains('#') && (segments[3].Contains('~') || segments[3].Contains('#'))) || (segments[0].Contains('#') && !segments[3].Contains('#'))) + result = new(null, segments[3], segments[4]); + else + result = new(segments[0], segments[3], segments[4]); + return result; + } + + [TestMethod] + public void TestMoveToVerify() + { + string http; + string? minusOne; + string? minusTwo; + string[] segments; + string[] beforeSegments; + string[] matchDirectories; + string? personKeyFormattedNew; + string? personDisplayDirectory; + string personDisplayDirectoryNew; + string personDisplayDirectoryNameNew; + string personKeyFormattedDirectoryNew; + string sourceDirectory = @""; + string sourceFile = @"\People - C.tsv"; + if (!File.Exists(sourceFile)) + throw new Exception(); + string[] lines = File.ReadAllLines(sourceFile); + for (int i = 0; i < lines.Length; i++) + { + if (!lines[i].Contains("https://")) + continue; + segments = lines[i].Split('\t'); + beforeSegments = lines[i - 1].Split('\t'); + if (beforeSegments.Length < 4 || segments.Length < 5) + continue; + matchDirectories = Directory.GetDirectories(sourceDirectory, beforeSegments[0], SearchOption.AllDirectories); + if (matchDirectories.Length != 1) + continue; + personDisplayDirectory = Path.GetDirectoryName(matchDirectories[0]); + if (personDisplayDirectory is null) + continue; + minusOne = Path.GetDirectoryName(personDisplayDirectory); + if (minusOne is null) + continue; + minusTwo = Path.GetDirectoryName(minusOne); + if (minusTwo is null) + continue; + (personKeyFormattedNew, personDisplayDirectoryNameNew, http) = Get(segments); + if (personKeyFormattedNew is null) + continue; + personDisplayDirectoryNew = Path.Combine(minusTwo, "Verify", personDisplayDirectoryNameNew); + if (Directory.Exists(personDisplayDirectoryNew)) + continue; + personKeyFormattedDirectoryNew = Path.Combine(personDisplayDirectoryNew, personKeyFormattedNew); + Directory.Move(personDisplayDirectory, personDisplayDirectoryNew); + _ = Directory.CreateDirectory(personKeyFormattedDirectoryNew); + File.WriteAllText(Path.Combine(personKeyFormattedDirectoryNew, "Facebook.txt"), http); + } + Assert.IsTrue(lines.Any()); + } + } \ No newline at end of file