From 3493225dc551525ecfcc2ed26a2c1947bedd0799 Mon Sep 17 00:00:00 2001 From: Hamid Reza Mohammadi Date: Sat, 3 Oct 2026 21:16:42 +0330 Subject: [PATCH] people tags #387 --- .../Pages/ReviewPersonRelationEdits.cshtml | 3 ++ GanjooRazor/Areas/User/Pages/Editor.cshtml | 6 ++++ .../Pages/SuggestNewPersonRelation.cshtml | 5 +++ .../Pages/SuggestNewPersonRelation.cshtml.cs | 33 ++++++++++++++++--- .../Pages/SuggestPersonRelationEdit.cshtml | 3 ++ GanjooRazor/Pages/PersonWindow.cshtml.cs | 6 +++- GanjooRazor/wwwroot/js/peoplegraph.js | 3 +- .../Models/Ganjoor/PersonAffiliationType.cs | 26 +++++++++++++++ RMuseum/RMuseum.xml | 26 +++++++++++++++ 9 files changed, 105 insertions(+), 6 deletions(-) diff --git a/GanjooRazor/Areas/Admin/Pages/ReviewPersonRelationEdits.cshtml b/GanjooRazor/Areas/Admin/Pages/ReviewPersonRelationEdits.cshtml index 14e8b861..95bca967 100644 --- a/GanjooRazor/Areas/Admin/Pages/ReviewPersonRelationEdits.cshtml +++ b/GanjooRazor/Areas/Admin/Pages/ReviewPersonRelationEdits.cshtml @@ -34,6 +34,9 @@ case PersonAffiliationType.Successor: return "جانشین"; case PersonAffiliationType.Panegyrized: return "مدح‌گو"; case PersonAffiliationType.Satirized: return "هجوگو"; + case PersonAffiliationType.MilitaryCommander: return "سردار"; + case PersonAffiliationType.Champion: return "پهلوان"; + case PersonAffiliationType.Contemporary: return "هم‌عصر"; case PersonAffiliationType.Other: return "نوع دیگر"; default: return t.ToString(); } diff --git a/GanjooRazor/Areas/User/Pages/Editor.cshtml b/GanjooRazor/Areas/User/Pages/Editor.cshtml index 979102b9..6507cb9f 100644 --- a/GanjooRazor/Areas/User/Pages/Editor.cshtml +++ b/GanjooRazor/Areas/User/Pages/Editor.cshtml @@ -264,6 +264,9 @@ '' + '' + '' + + '' + + '' + + '' + '' + '' + '' + @@ -378,6 +381,9 @@ Ally: function (p1, p2) { return p1 + ' و ' + p2 + ' متحد هم هستند.'; }, Rival: function (p1, p2) { return p1 + ' و ' + p2 + ' رقیب هم هستند.'; }, Companion: function (p1, p2) { return p1 + ' و ' + p2 + ' همراه هم هستند.'; }, + MilitaryCommander: function (p1, p2) { return p1 + ' سردار ' + p2 + ' است.'; }, + Champion: function (p1, p2) { return p1 + ' پهلوان ' + p2 + ' است.'; }, + Contemporary: function (p1, p2) { return p1 + ' و ' + p2 + ' هم‌عصر هم هستند.'; }, Other: function (p1, p2) { return p1 + ' با ' + p2 + ' نسبتی دارد (طبق یادداشت).'; } } }; diff --git a/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml b/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml index 98f5e0d7..47126cf7 100644 --- a/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml +++ b/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml @@ -98,9 +98,14 @@ else + + + + + diff --git a/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml.cs b/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml.cs index 03a6d51e..6e9b0dcd 100644 --- a/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml.cs +++ b/GanjooRazor/Areas/User/Pages/SuggestNewPersonRelation.cshtml.cs @@ -147,10 +147,10 @@ namespace GanjooRazor.Areas.User.Pages // OtherIsPerson1/SubjectIsPerson1 pairs translate the direction-aware choice into the // symmetric Person1Id/Person2Id pair, following the direction each PersonAffiliationType - // value's own doc comment defines (Minister/Advisor/Courtier/Servant: Person1 is the - // subordinate one; Patron/Successor: Person1 is the patron/later one; Panegyrized/ - // Satirized: Person1 is the poet; Ally/Rival/Companion/Other: symmetric, direction - // doesn't matter) + // value's own doc comment defines (Minister/Advisor/Courtier/Servant/MilitaryCommander/ + // Champion: Person1 is the subordinate one; Patron/Successor: Person1 is the + // patron/later one; Panegyrized/Satirized: Person1 is the poet; Ally/Rival/Companion/ + // Contemporary/Other: symmetric, direction doesn't matter) switch (AffiliationKind) { case "Minister_Other": // the other person served as minister to this one @@ -233,6 +233,26 @@ namespace GanjooRazor.Areas.User.Pages suggestion.Person2Id = OtherPersonId; suggestion.SuggestedAffiliationType = PersonAffiliationType.Satirized; break; + case "MilitaryCommander_Other": // the other person served as military commander (سردار) to this one + suggestion.Person1Id = OtherPersonId; + suggestion.Person2Id = personId; + suggestion.SuggestedAffiliationType = PersonAffiliationType.MilitaryCommander; + break; + case "MilitaryCommander_Subject": // this person served as military commander (سردار) to the other one + suggestion.Person1Id = personId; + suggestion.Person2Id = OtherPersonId; + suggestion.SuggestedAffiliationType = PersonAffiliationType.MilitaryCommander; + break; + case "Champion_Other": // the other person was champion/warrior (پهلوان) to this one + suggestion.Person1Id = OtherPersonId; + suggestion.Person2Id = personId; + suggestion.SuggestedAffiliationType = PersonAffiliationType.Champion; + break; + case "Champion_Subject": // this person was champion/warrior (پهلوان) to the other one + suggestion.Person1Id = personId; + suggestion.Person2Id = OtherPersonId; + suggestion.SuggestedAffiliationType = PersonAffiliationType.Champion; + break; case "Ally": suggestion.Person1Id = personId; suggestion.Person2Id = OtherPersonId; @@ -248,6 +268,11 @@ namespace GanjooRazor.Areas.User.Pages suggestion.Person2Id = OtherPersonId; suggestion.SuggestedAffiliationType = PersonAffiliationType.Companion; break; + case "Contemporary": // symmetric - no other relationship implied, just overlapping lifetimes + suggestion.Person1Id = personId; + suggestion.Person2Id = OtherPersonId; + suggestion.SuggestedAffiliationType = PersonAffiliationType.Contemporary; + break; case "Other": suggestion.Person1Id = personId; suggestion.Person2Id = OtherPersonId; diff --git a/GanjooRazor/Areas/User/Pages/SuggestPersonRelationEdit.cshtml b/GanjooRazor/Areas/User/Pages/SuggestPersonRelationEdit.cshtml index 51ac629c..0799d6f1 100644 --- a/GanjooRazor/Areas/User/Pages/SuggestPersonRelationEdit.cshtml +++ b/GanjooRazor/Areas/User/Pages/SuggestPersonRelationEdit.cshtml @@ -66,9 +66,12 @@ else + + +

جهت وابستگی (کدام طرف زیردست/حامی/... است) قابل تغییر نیست؛ در صورت اشتباه بودن جهت، این وابستگی را حذف و یکی تازه پیشنهاد کنید.

diff --git a/GanjooRazor/Pages/PersonWindow.cshtml.cs b/GanjooRazor/Pages/PersonWindow.cshtml.cs index e4cbb8db..271a43a6 100644 --- a/GanjooRazor/Pages/PersonWindow.cshtml.cs +++ b/GanjooRazor/Pages/PersonWindow.cshtml.cs @@ -115,12 +115,16 @@ namespace GanjooRazor.Pages { PersonAffiliationType.Successor, "جانشینِ" }, { PersonAffiliationType.Panegyrized, "مدح‌گویِ" }, { PersonAffiliationType.Satirized, "هجوگویِ" }, + { PersonAffiliationType.MilitaryCommander, "سردارِ" }, + { PersonAffiliationType.Champion, "پهلوانِ" }, + { PersonAffiliationType.Contemporary, "هم‌عصرِ" }, { PersonAffiliationType.Other, "دارای نسبتی (به یادداشت نگاه کنید) با" }, }; private static bool IsSymmetricAffiliation(PersonAffiliationType t) => t == PersonAffiliationType.Ally || t == PersonAffiliationType.Rival || - t == PersonAffiliationType.Companion || t == PersonAffiliationType.Other; + t == PersonAffiliationType.Companion || t == PersonAffiliationType.Contemporary || + t == PersonAffiliationType.Other; public async Task OnGetAsync(int id) { diff --git a/GanjooRazor/wwwroot/js/peoplegraph.js b/GanjooRazor/wwwroot/js/peoplegraph.js index 51f06f67..ef59eb0e 100644 --- a/GanjooRazor/wwwroot/js/peoplegraph.js +++ b/GanjooRazor/wwwroot/js/peoplegraph.js @@ -8,7 +8,8 @@ // person2Id, person2Name, category, typeValue, degreeHint, note}] } where category is // "Relation" (typeValue is PersonRelationType: 0=Parent,1=Sibling,2=Spouse,3=Ancestor) or // "Affiliation" (typeValue is PersonAffiliationType: 0=Minister,1=Advisor,2=Courtier,3=Patron, -// 4=Ally,5=Rival,6=Servant,7=Companion,8=Successor,9=Panegyrized,10=Satirized,99=Other). directlyTagged is false only on +// 4=Ally,5=Rival,6=Servant,7=Companion,8=Successor,9=Panegyrized,10=Satirized,11=MilitaryCommander, +// 12=Champion,13=Contemporary,99=Other). directlyTagged is false only on // the category-scoped graph (GET api/ganjoor/cat/{id}/persongraph, the "characters in this work" // tab): such a node was pulled in as a one-hop relative/affiliate of someone actually named in the // work's verses, and is never false on the whole-site graph fed by PeopleExplorer.cshtml. importance diff --git a/RMuseum/Models/Ganjoor/PersonAffiliationType.cs b/RMuseum/Models/Ganjoor/PersonAffiliationType.cs index 5b57fc47..8f027dc3 100644 --- a/RMuseum/Models/Ganjoor/PersonAffiliationType.cs +++ b/RMuseum/Models/Ganjoor/PersonAffiliationType.cs @@ -70,6 +70,32 @@ namespace RMuseum.Models.Ganjoor /// Satirized = 10, + /// + /// Person1 served as a military commander/general (سردار) under Person2 - directional, same + /// subordinate-side convention as Minister/Advisor/Courtier, but deliberately kept separate + /// from Courtier: a سردار's tie to Person2 is a military command relationship, not a court + /// role, and (unlike e.g. Minister, which implies one standing appointment) doesn't imply the + /// tie held continuously - a commander could serve across campaigns/kings, with specifics + /// (which campaign, how long) left to Note + /// + MilitaryCommander = 11, + + /// + /// Person1 was a champion/legendary warrior (پهلوان) associated with Person2 - directional, + /// same subordinate-side convention as MilitaryCommander, but distinct from it: a پهلوان's + /// standing comes from individual prowess/heroism (e.g. Rostam), not from holding a command + /// post, and like MilitaryCommander this doesn't imply a permanent/continuous tie + /// + Champion = 12, + + /// + /// Person1 and Person2 lived in the same era (هم‌عصر), with no other relationship between + /// them necessarily known/implied - symmetric (order doesn't matter). Unlike every other + /// value here, this doesn't assert any kind of tie or interaction, only overlapping lifetimes; + /// use one of the other types instead whenever an actual relationship is known + /// + Contemporary = 13, + /// /// doesn't fit any of the above - rely on Note for what the tie actually is /// diff --git a/RMuseum/RMuseum.xml b/RMuseum/RMuseum.xml index dc46be5a..2eddeb0a 100644 --- a/RMuseum/RMuseum.xml +++ b/RMuseum/RMuseum.xml @@ -11926,6 +11926,32 @@ the satire's target) - directional, same convention as Minister/Patron + + + Person1 served as a military commander/general (سردار) under Person2 - directional, same + subordinate-side convention as Minister/Advisor/Courtier, but deliberately kept separate + from Courtier: a سردار's tie to Person2 is a military command relationship, not a court + role, and (unlike e.g. Minister, which implies one standing appointment) doesn't imply the + tie held continuously - a commander could serve across campaigns/kings, with specifics + (which campaign, how long) left to Note + + + + + Person1 was a champion/legendary warrior (پهلوان) associated with Person2 - directional, + same subordinate-side convention as MilitaryCommander, but distinct from it: a پهلوان's + standing comes from individual prowess/heroism (e.g. Rostam), not from holding a command + post, and like MilitaryCommander this doesn't imply a permanent/continuous tie + + + + + Person1 and Person2 lived in the same era (هم‌عصر), with no other relationship between + them necessarily known/implied - symmetric (order doesn't matter). Unlike every other + value here, this doesn't assert any kind of tie or interaction, only overlapping lifetimes; + use one of the other types instead whenever an actual relationship is known + + doesn't fit any of the above - rely on Note for what the tie actually is