@@ -71,15 +71,11 @@ impl RustTeams {
7171 . filter ( |team| team. website_data . is_some ( ) )
7272 // On the main page, show the leadership-council and all top-level
7373 // teams.
74- . filter ( |team| team . kind == TeamKind :: Team && team . subteam_of . is_none ( ) )
74+ . filter ( is_toplevel_team )
7575 . map ( |team| IndexTeam {
7676 section : kind_to_str ( team. kind ) ,
7777 page_name : team. website_data . clone ( ) . unwrap ( ) . page ,
78- url : format ! (
79- "{}/{}" ,
80- kind_to_str( team. kind) ,
81- team. website_data. as_ref( ) . unwrap( ) . page
82- ) ,
78+ url : get_team_relative_url ( & team) ,
8379 team,
8480 } )
8581 . collect :: < Vec < IndexTeam > > ( ) ;
@@ -234,6 +230,111 @@ impl RustTeams {
234230
235231 AllTeamMembers { active, alumni }
236232 }
233+
234+ pub fn all_person_data ( & self ) -> Vec < PersonData > {
235+ let mut people: HashMap < String , PersonData > = HashMap :: new ( ) ;
236+
237+ enum TeamMode {
238+ Member ,
239+ Alumni ,
240+ MemberOfArchivedTeam ,
241+ }
242+
243+ fn add_team (
244+ people : & mut HashMap < String , PersonData > ,
245+ ctx : & RustTeams ,
246+ member : & TeamMember ,
247+ team : & Team ,
248+ mode : TeamMode ,
249+ ) {
250+ let person = people
251+ . entry ( member. github . clone ( ) )
252+ . or_insert_with ( move || PersonData {
253+ name : member. name . clone ( ) ,
254+ github : member. github . clone ( ) ,
255+ active_teams : vec ! [ ] ,
256+ alumni_teams : vec ! [ ] ,
257+ } ) ;
258+ let teams = match mode {
259+ TeamMode :: Member => & mut person. active_teams ,
260+ TeamMode :: Alumni | TeamMode :: MemberOfArchivedTeam => & mut person. alumni_teams ,
261+ } ;
262+ let url = match mode {
263+ TeamMode :: Member | TeamMode :: Alumni => ctx. get_toplevel_team_url ( team) ,
264+ TeamMode :: MemberOfArchivedTeam => Some ( "archived-teams.html" . to_string ( ) ) ,
265+ } ;
266+ teams. push ( PersonTeam :: new ( team, member, url) ) ;
267+ }
268+
269+ for team in & self . archived_teams {
270+ for member in team. members . iter ( ) . chain ( & team. alumni ) {
271+ add_team (
272+ & mut people,
273+ self ,
274+ member,
275+ team,
276+ TeamMode :: MemberOfArchivedTeam ,
277+ ) ;
278+ }
279+ }
280+ for team in & self . teams {
281+ if team. kind == TeamKind :: MarkerTeam && team. website_data . is_none ( ) {
282+ continue ;
283+ }
284+
285+ for member in & team. members {
286+ add_team ( & mut people, self , member, team, TeamMode :: Member ) ;
287+ }
288+ for member in & team. alumni {
289+ add_team ( & mut people, self , member, team, TeamMode :: Alumni ) ;
290+ }
291+ }
292+
293+ let mut people: Vec < PersonData > = people. into_values ( ) . collect ( ) ;
294+ people. sort_by ( |a, b| a. github . cmp ( & b. github ) ) ;
295+
296+ for person in & mut people {
297+ person
298+ . active_teams
299+ . sort_by ( |a, b| a. webpage_name . cmp ( & b. webpage_name ) ) ;
300+ person
301+ . alumni_teams
302+ . sort_by ( |a, b| a. webpage_name . cmp ( & b. webpage_name ) ) ;
303+ }
304+
305+ people
306+ }
307+
308+ fn get_toplevel_team_url < ' a > ( & ' a self , mut team : & ' a Team ) -> Option < String > {
309+ while !is_toplevel_team ( team) {
310+ let Some ( parent) = & team. subteam_of else {
311+ return None ;
312+ } ;
313+ let parent = self . teams . iter ( ) . find ( |t| t. name == * parent) ?;
314+ team = parent;
315+ }
316+
317+ if team. website_data . is_some ( ) {
318+ Some ( get_team_relative_url ( team) )
319+ } else {
320+ None
321+ }
322+ }
323+ }
324+
325+ /// Get a relative URL of a team that should be appended to
326+ /// Should only be used for top-level teams.
327+ fn get_team_relative_url ( team : & Team ) -> String {
328+ assert ! ( is_toplevel_team( team) ) ;
329+ format ! (
330+ "{}/{}" ,
331+ kind_to_str( team. kind) ,
332+ team. website_data. as_ref( ) . unwrap( ) . page
333+ )
334+ }
335+
336+ fn is_toplevel_team ( team : & Team ) -> bool {
337+ team. kind == TeamKind :: Team && team. subteam_of . is_none ( )
237338}
238339
239340#[ derive( Serialize ) ]
@@ -272,6 +373,58 @@ pub struct AllTeamMembers {
272373 alumni : Vec < TeamMember > ,
273374}
274375
376+ #[ derive( Serialize ) ]
377+ pub struct PersonTeam {
378+ team : Team ,
379+ toplevel_url : Option < String > ,
380+ webpage_name : String ,
381+ roles : Vec < String > ,
382+ }
383+
384+ impl PersonTeam {
385+ fn new ( team : & Team , member : & TeamMember , toplevel_url : Option < String > ) -> Self {
386+ // Turn inside-rust-reviewers into Inside Rust Reviewers
387+ let normalize_name = |name : & str | {
388+ name. split ( "-" )
389+ . map ( |p| {
390+ p. chars ( )
391+ . take ( 1 )
392+ . flat_map ( |c| c. to_uppercase ( ) )
393+ . chain ( p. chars ( ) . skip ( 1 ) )
394+ . collect :: < String > ( )
395+ } )
396+ . collect :: < Vec < String > > ( )
397+ . join ( " " )
398+ } ;
399+
400+ let webpage_name = team
401+ . website_data
402+ . as_ref ( )
403+ . map ( |w| w. name . clone ( ) )
404+ . unwrap_or_else ( || normalize_name ( & team. name ) ) ;
405+
406+ let mut roles = vec ! [ ] ;
407+ if member. is_lead {
408+ roles. push ( "Lead" . to_string ( ) ) ;
409+ }
410+ roles. extend ( member. roles . iter ( ) . map ( |r| normalize_name ( r) ) ) ;
411+ Self {
412+ team : team. clone ( ) ,
413+ toplevel_url,
414+ webpage_name,
415+ roles,
416+ }
417+ }
418+ }
419+
420+ #[ derive( Serialize ) ]
421+ pub struct PersonData {
422+ name : String ,
423+ pub github : String ,
424+ active_teams : Vec < PersonTeam > ,
425+ alumni_teams : Vec < PersonTeam > ,
426+ }
427+
275428pub fn load_rust_teams ( ) -> anyhow:: Result < RustTeams > {
276429 println ! ( "Downloading Team API data" ) ;
277430
0 commit comments