flowchart TB
Start([User Opens Application]) --> LoadData[Load Data from Database]
LoadData --> DataCache[(Data Cache:<br/>Persons, Deals, Companies,<br/>Roles, History)]
DataCache --> Tab1[Top Affiliated Persons]
DataCache --> Tab2[Top Deal Makers]
DataCache --> Tab3[Connection Pathfinder]
style DataCache fill:#4fc3f7
style Tab1 fill:#ffb74d
style Tab2 fill:#81c784
style Tab3 fill:#ba68c8
Purpose: Rank persons by their total affiliations (companies worked at)
flowchart TD
Start1([Top Affiliated Persons]) --> GetPersons[Get All Persons<br/>from Database]
GetPersons --> CountAff[Count Affiliations<br/>per Person]
CountAff --> Query{User Filters?}
Query -->|Min Affiliations| Filter1[Filter by<br/>Min Count]
Query -->|Limit| Filter2[Limit Results]
Filter1 --> Sort[Sort by<br/>Affiliation Count DESC]
Filter2 --> Sort
Sort --> Display1[Display Table:<br/>- Name<br/>- Affiliation Count<br/>- Current Company<br/>- Current Position]
Display1 --> Export1[Export to CSV]
style Start1 fill:#ffb74d
style Display1 fill:#2e7d32,color:#fff
Key Metrics:
- Affiliation Count: Total number of companies person has worked at (from
df_history) - Sorting: Descending by affiliation count
- Filters: Minimum affiliations threshold, result limit
Purpose: Rank persons by their involvement in PJT-advised deals
flowchart TD
Start2([Top Deal Makers]) --> BuildGraph[Build Connection Graph]
BuildGraph --> Step1[1. Find PJT Advisors<br/>on ALL Deals]
Step1 --> Step2[2. Match Persons<br/>to Deal Companies]
Step2 --> Validate{Person Active<br/>During Deal?}
Validate -->|Yes| AddPerson[Add to Deal Persons]
Validate -->|No| Skip[Skip Person]
AddPerson --> Aggregate[Aggregate per Person:<br/>- Deal Count<br/>- Total Deal Value<br/>- Company Count]
Aggregate --> Sort2[Sort by<br/>Deal Count DESC]
Sort2 --> Display2[Display Table:<br/>- Name<br/>- # Deals<br/>- Total Deal Value<br/>- # Companies<br/>- Current Role<br/>- Action Button]
Display2 --> Action{User Action?}
Action -->|Click Find Connection| GoToTab3[Navigate to<br/>Connection Pathfinder]
Action -->|Export| Export2[Export to CSV]
style Start2 fill:#81c784
style Display2 fill:#2e7d32,color:#fff
style GoToTab3 fill:#ba68c8
Key Logic:
- No Date Filter: Includes ALL PJT deals (no 2015 filter)
- Deal Matching: Person must be active at target/acquiror company during deal announcement
- Active Check:
position_start_date <= deal_date <= position_end_date - Metrics: Count of deals, sum of deal values, count of unique companies
Purpose: Find shortest valid connection path from PJT Partners to target person
flowchart TD
Start3([Connection Pathfinder]) --> Input[User Enters<br/>Person ID]
Input --> CheckCache{Base Graph<br/>Cached?}
CheckCache -->|No| BuildBase[Build Base Graph]
CheckCache -->|Yes| UseCache[Use Cached Graph]
BuildBase --> FilterDeals[Filter Deals<br/>After 2015-01-01]
FilterDeals --> AddNodes[Add Graph Nodes]
AddNodes --> Node1[ADVISOR Nodes:<br/>PJT Advisors]
AddNodes --> Node2[DEAL Nodes:<br/>PJT-Advised Deals]
AddNodes --> Node3[PERSON Nodes:<br/>Deal-Related Persons]
AddNodes --> Node4[COMPANY Nodes:<br/>Shared Companies]
Node1 --> AddEdges[Add Graph Edges]
Node2 --> AddEdges
Node3 --> AddEdges
Node4 --> AddEdges
AddEdges --> Edge1[ADVISOR→DEAL:<br/>PJT advised on deal]
AddEdges --> Edge2[DEAL→PERSON:<br/>Person active at<br/>deal company]
AddEdges --> Edge3[PERSON→COMPANY:<br/>Overlapping colleagues]
Edge1 --> CacheBase[(Cache Base Graph)]
Edge2 --> CacheBase
Edge3 --> CacheBase
CacheBase --> UseCache
style Start3 fill:#ba68c8
style CacheBase fill:#4fc3f7
flowchart TD
BaseGraph[(Base Graph:<br/>178 persons)] --> CheckTarget{Target Person<br/>in Base Graph?}
CheckTarget -->|Yes| UseDirect[Use Base Graph]
CheckTarget -->|No| Expand[Expand Graph]
Expand --> Pass1[Pass 1:<br/>Find All Companies<br/>of Base Persons]
Pass1 --> Pass2[Pass 2:<br/>Find All Persons<br/>at Those Companies<br/>+ Target Person]
Pass2 --> BuildEdges[Build PERSON-COMPANY<br/>Edges with Overlap Check]
BuildEdges --> OverlapCheck{Persons Overlapped<br/>at Company?}
OverlapCheck -->|Yes| AddEdge[Add Edge with<br/>Time Periods]
OverlapCheck -->|No| SkipEdge[Skip Edge]
AddEdge --> CacheExpanded[(Cache Expanded Graph<br/>for This Person)]
SkipEdge --> CacheExpanded
CacheExpanded --> UseDirect
UseDirect --> FilterDeals2[Filter to Deals<br/>After 2015-01-01]
FilterDeals2 --> FindPaths[Find All Paths<br/>Using NetworkX]
style BaseGraph fill:#4fc3f7
style CacheExpanded fill:#4fc3f7
flowchart TD
AllPaths[All Potential Paths<br/>from NetworkX] --> Loop{For Each Path}
Loop --> ValidateDeal[Validate Deal Connection]
ValidateDeal --> CheckDirector{First Director<br/>Active During<br/>Deal Date?}
CheckDirector -->|No| Reject1[❌ Reject Path:<br/>Director Not Active]
CheckDirector -->|Yes| ValidateOverlaps[Validate All<br/>Person Overlaps]
ValidateOverlaps --> LoopConnections{For Each<br/>PERSON→COMPANY→PERSON}
LoopConnections --> CheckOverlap{Time Periods<br/>Overlap?}
CheckOverlap -->|No| Reject2[❌ Reject Path:<br/>No Overlap]
CheckOverlap -->|Yes| NextConnection[Check Next<br/>Connection]
NextConnection --> MoreConnections{More<br/>Connections?}
MoreConnections -->|Yes| LoopConnections
MoreConnections -->|No| Accept[✅ Accept Path:<br/>All Valid]
Accept --> ValidPaths[Valid Paths List]
Reject1 --> Loop
Reject2 --> Loop
ValidPaths --> SelectShortest[Select Shortest<br/>Valid Path]
SelectShortest --> DisplayPath[Display Path<br/>in UI]
DisplayPath --> ShowSteps[Show Each Step:<br/>- Node Name<br/>- Connection Detail<br/>- Time Periods<br/>- Deal Dates]
style Accept fill:#2e7d32,color:#fff
style Reject1 fill:#c62828,color:#fff
style Reject2 fill:#c62828,color:#fff
style DisplayPath fill:#2e7d32,color:#fff
flowchart LR
subgraph "Deal Validation"
Deal[DEAL Node] --> Person1[PERSON Node]
Person1 --> Check1{Person Active<br/>at Deal Company<br/>During Deal Date?}
Check1 -->|Yes| Valid1[✅ Valid]
Check1 -->|No| Invalid1[❌ Invalid]
end
subgraph "Overlap Validation"
Person2[PERSON A] --> Company[COMPANY Node]
Company --> Person3[PERSON B]
Person2 -.->|Works: 2010-2015| TimeA[Time Period A]
Person3 -.->|Works: 2012-2020| TimeB[Time Period B]
TimeA --> Check2{Periods Overlap?<br/>2012-2015}
TimeB --> Check2
Check2 -->|Yes| Valid2[✅ Valid]
Check2 -->|No| Invalid2[❌ Invalid]
end
style Valid1 fill:#2e7d32,color:#fff
style Invalid1 fill:#c62828,color:#fff
style Valid2 fill:#2e7d32,color:#fff
style Invalid2 fill:#c62828,color:#fff
flowchart LR
subgraph Database
DB[(MySQL Database)]
end
subgraph Backend
Cache[(Data Cache)]
Graph[(Connection Graph)]
end
subgraph Frontend
Tab1[Top Affiliated<br/>Persons]
Tab2[Top Deal<br/>Makers]
Tab3[Connection<br/>Pathfinder]
end
DB -->|Load on Startup| Cache
Cache -->|Build Graph| Graph
Cache -->|Count Affiliations| Tab1
Graph -->|Count Deals| Tab2
Graph -->|Find Path| Tab3
Tab2 -.->|Click Find Connection| Tab3
style DB fill:#ef6c00
style Cache fill:#4fc3f7
style Graph fill:#4fc3f7
flowchart TD
Opt1[Caching Strategy] --> Cache1[Base Graph Cache:<br/>Shared Across Searches]
Opt1 --> Cache2[Expanded Graph Cache:<br/>Per-Person Cache]
Opt2[Graph Building] --> Build1[Filter Deals After 2015<br/>(Pathfinder Only)]
Opt2 --> Build2[Only Overlap Check<br/>for Edges]
Opt2 --> Build3[Skip Companies with<br/>>50 Persons]
Opt3[Validation] --> Val1[Early Rejection:<br/>Invalid Deal Director]
Opt3 --> Val2[Early Rejection:<br/>No Overlap]
style Opt1 fill:#1565c0,color:#fff
style Opt2 fill:#1565c0,color:#fff
style Opt3 fill:#1565c0,color:#fff
- Algorithm: Simple aggregation and sort
- Complexity: O(n) where n = number of persons
- Data Source:
df_historytable
- Algorithm: Graph-based deal matching with temporal validation
- Complexity: O(d × p) where d = deals, p = persons per deal
- Data Source:
df_deals,df_history,df_fees - Note: Includes ALL PJT deals (no date filter)
- Algorithm:
- Filter deals to after 2015-01-01
- NetworkX shortest path (BFS)
- Post-processing validation (temporal overlap)
- Complexity: O(V + E) for pathfinding + O(p²) for validation where p = path length
- Data Source: All tables combined into graph structure
- Note: Only includes deals announced after 2015-01-01
- Deal Connection: Director must be active at deal company during deal announcement
- Person Connection: Two persons must have overlapping work periods at the same company
- Time Overlap:
start1 <= end2 AND start2 <= end1