<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>http://digida.mgpu.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D1%81%D1%87%D0%B8%D1%82%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%28GitLab%29%2FCode</id>
	<title>Как посчитать метрики командности (GitLab)/Code - История изменений</title>
	<link rel="self" type="application/atom+xml" href="http://digida.mgpu.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D1%81%D1%87%D0%B8%D1%82%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%28GitLab%29%2FCode"/>
	<link rel="alternate" type="text/html" href="http://digida.mgpu.ru/index.php?title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D1%81%D1%87%D0%B8%D1%82%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D0%B8_(GitLab)/Code&amp;action=history"/>
	<updated>2026-05-21T22:24:19Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>http://digida.mgpu.ru/index.php?title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D1%81%D1%87%D0%B8%D1%82%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D0%B8_(GitLab)/Code&amp;diff=44949&amp;oldid=prev</id>
		<title>Patarakin в 10:35, 17 марта 2026</title>
		<link rel="alternate" type="text/html" href="http://digida.mgpu.ru/index.php?title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D1%81%D1%87%D0%B8%D1%82%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D0%B8_(GitLab)/Code&amp;diff=44949&amp;oldid=prev"/>
		<updated>2026-03-17T10:35:05Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Предыдущая версия&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Версия от 13:35, 17 марта 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Строка 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* [[Как посчитать метрики командности (GitLab)]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Только код ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Только код ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Patarakin</name></author>
	</entry>
	<entry>
		<id>http://digida.mgpu.ru/index.php?title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D1%81%D1%87%D0%B8%D1%82%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D0%B8_(GitLab)/Code&amp;diff=44947&amp;oldid=prev</id>
		<title>Patarakin: Новая страница: «== Только код ==  &lt;syntaxhighlight lang=&quot;R&quot; line&gt;  library(tidyverse) library(lubridate) library(ineq) library(scales) library(knitr)  URL &lt;- paste0(   &quot;https://raw.githubusercontent.com/patarakin/stat-data/&quot;,   &quot;1118a56e7544839d7df91a60df2a25ba577c4dd4/datasets/csv/df_rich_team.csv&quot; )  df &lt;- read_csv(URL, show_col_types = FALSE) |&gt;   mutate(     commit_time = ymd_hms(commit_time, tz = &quot;UTC&quot;),     commit_date = as.Date(commit_time)   )  glimpse(df)...»</title>
		<link rel="alternate" type="text/html" href="http://digida.mgpu.ru/index.php?title=%D0%9A%D0%B0%D0%BA_%D0%BF%D0%BE%D1%81%D1%87%D0%B8%D1%82%D0%B0%D1%82%D1%8C_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B8_%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D0%B8_(GitLab)/Code&amp;diff=44947&amp;oldid=prev"/>
		<updated>2026-03-17T10:33:39Z</updated>

		<summary type="html">&lt;p&gt;Новая страница: «== Только код ==  &amp;lt;syntaxhighlight lang=&amp;quot;R&amp;quot; line&amp;gt;  library(tidyverse) library(lubridate) library(ineq) library(scales) library(knitr)  URL &amp;lt;- paste0(   &amp;quot;https://raw.githubusercontent.com/patarakin/stat-data/&amp;quot;,   &amp;quot;1118a56e7544839d7df91a60df2a25ba577c4dd4/datasets/csv/df_rich_team.csv&amp;quot; )  df &amp;lt;- read_csv(URL, show_col_types = FALSE) |&amp;gt;   mutate(     commit_time = ymd_hms(commit_time, tz = &amp;quot;UTC&amp;quot;),     commit_date = as.Date(commit_time)   )  glimpse(df)...»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Только код ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;R&amp;quot; line&amp;gt;&lt;br /&gt;
&lt;br /&gt;
library(tidyverse)&lt;br /&gt;
library(lubridate)&lt;br /&gt;
library(ineq)&lt;br /&gt;
library(scales)&lt;br /&gt;
library(knitr)&lt;br /&gt;
&lt;br /&gt;
URL &amp;lt;- paste0(&lt;br /&gt;
  &amp;quot;https://raw.githubusercontent.com/patarakin/stat-data/&amp;quot;,&lt;br /&gt;
  &amp;quot;1118a56e7544839d7df91a60df2a25ba577c4dd4/datasets/csv/df_rich_team.csv&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
df &amp;lt;- read_csv(URL, show_col_types = FALSE) |&amp;gt;&lt;br /&gt;
  mutate(&lt;br /&gt;
    commit_time = ymd_hms(commit_time, tz = &amp;quot;UTC&amp;quot;),&lt;br /&gt;
    commit_date = as.Date(commit_time)&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
glimpse(df)&lt;br /&gt;
&lt;br /&gt;
##-- Functions&lt;br /&gt;
gini_contrib &amp;lt;- function(changes_vec) {&lt;br /&gt;
  if (length(changes_vec) &amp;lt; 2 || sum(changes_vec) == 0) return(0)&lt;br /&gt;
  ineq::Gini(changes_vec)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
succession_ratio &amp;lt;- function(authors_vec) {&lt;br /&gt;
  n &amp;lt;- length(authors_vec)&lt;br /&gt;
  if (n &amp;lt; 2) return(NA_real_)&lt;br /&gt;
  sum(authors_vec[-1] != authors_vec[-n]) / (n - 1)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
burstiness &amp;lt;- function(times_vec) {&lt;br /&gt;
  times_vec &amp;lt;- sort(times_vec)&lt;br /&gt;
  if (length(times_vec) &amp;lt; 3) return(NA_real_)&lt;br /&gt;
  deltas &amp;lt;- as.numeric(diff(times_vec), units = &amp;quot;secs&amp;quot;)&lt;br /&gt;
  deltas &amp;lt;- deltas[deltas &amp;gt; 0]&lt;br /&gt;
  if (length(deltas) &amp;lt; 2) return(NA_real_)&lt;br /&gt;
  mu &amp;lt;- mean(deltas)&lt;br /&gt;
  sigma &amp;lt;- sd(deltas)&lt;br /&gt;
  if ((sigma + mu) == 0) return(NA_real_)&lt;br /&gt;
  (sigma - mu) / (sigma + mu)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
shared_activity_index &amp;lt;- function(author_vec, date_vec) {&lt;br /&gt;
  authors &amp;lt;- unique(author_vec)&lt;br /&gt;
  n &amp;lt;- length(authors)&lt;br /&gt;
  if (n &amp;lt; 2) return(0)&lt;br /&gt;
  &lt;br /&gt;
  dates_by_author &amp;lt;- split(date_vec, author_vec)&lt;br /&gt;
  pairs &amp;lt;- combn(authors, 2, simplify = FALSE)&lt;br /&gt;
  &lt;br /&gt;
  overlap_count &amp;lt;- sum(vapply(pairs, function(p) {&lt;br /&gt;
    length(intersect(dates_by_author[[p[1]]],&lt;br /&gt;
                     dates_by_author[[p[2]]])) &amp;gt; 0&lt;br /&gt;
  }, logical(1)))&lt;br /&gt;
  &lt;br /&gt;
  overlap_count / length(pairs)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
mean_response_minutes &amp;lt;- function(authors_vec, times_vec) {&lt;br /&gt;
  n &amp;lt;- length(authors_vec)&lt;br /&gt;
  if (n &amp;lt; 2) return(NA_real_)&lt;br /&gt;
  intervals &amp;lt;- numeric(0)&lt;br /&gt;
  for (i in seq(2, n)) {&lt;br /&gt;
    if (authors_vec[i] != authors_vec[i - 1]) {&lt;br /&gt;
      delta &amp;lt;- as.numeric(difftime(times_vec[i],&lt;br /&gt;
                                   times_vec[i - 1],&lt;br /&gt;
                                   units = &amp;quot;mins&amp;quot;))&lt;br /&gt;
      intervals &amp;lt;- c(intervals, delta)&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  if (length(intervals) == 0) return(NA_real_)&lt;br /&gt;
  mean(intervals)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#--------------------------&lt;br /&gt;
author_contrib &amp;lt;- df |&amp;gt;&lt;br /&gt;
  group_by(project_id, author_anon) |&amp;gt;&lt;br /&gt;
  summarise(author_changes = sum(total_changes), .groups = &amp;quot;drop&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
gini_by_project &amp;lt;- author_contrib |&amp;gt;&lt;br /&gt;
  group_by(project_id) |&amp;gt;&lt;br /&gt;
  summarise(&lt;br /&gt;
    gini_contribution = gini_contrib(author_changes),&lt;br /&gt;
    .groups = &amp;quot;drop&amp;quot;&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
project_metrics &amp;lt;- df |&amp;gt;&lt;br /&gt;
  arrange(project_id, commit_time) |&amp;gt;&lt;br /&gt;
  group_by(project_id) |&amp;gt;&lt;br /&gt;
  summarise(&lt;br /&gt;
    # Inputs&lt;br /&gt;
    n_authors     = n_distinct(author_anon),&lt;br /&gt;
    n_commits     = n(),&lt;br /&gt;
    total_changes = sum(total_changes),&lt;br /&gt;
    duration_days = as.numeric(&lt;br /&gt;
      difftime(max(commit_time), min(commit_time), units = &amp;quot;days&amp;quot;)&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    # Action processes&lt;br /&gt;
    succession_ratio = succession_ratio(author_anon),&lt;br /&gt;
    burstiness       = burstiness(commit_time),&lt;br /&gt;
    commit_rate_per_day = n() / pmax(&lt;br /&gt;
      as.numeric(difftime(max(commit_time),&lt;br /&gt;
                          min(commit_time), units = &amp;quot;days&amp;quot;)),&lt;br /&gt;
      0.01&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    # Emergent states&lt;br /&gt;
    shared_activity_index =&lt;br /&gt;
      shared_activity_index(author_anon, commit_date),&lt;br /&gt;
    &lt;br /&gt;
    # Output: зрелость работы&lt;br /&gt;
    refactoring_ratio = sum(deletions) / pmax(sum(total_changes), 1),&lt;br /&gt;
    &lt;br /&gt;
    # Stigmergy: скорость реакции&lt;br /&gt;
    mean_response_min =&lt;br /&gt;
      mean_response_minutes(author_anon, commit_time),&lt;br /&gt;
    &lt;br /&gt;
    .groups = &amp;quot;drop&amp;quot;&lt;br /&gt;
  ) |&amp;gt;&lt;br /&gt;
  left_join(gini_by_project, by = &amp;quot;project_id&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
glimpse(project_metrics)&lt;br /&gt;
&lt;br /&gt;
# Нормируем ключевые метрики и агрегируем их в &amp;#039;&amp;#039;&amp;#039;индекс командности&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
minmax_norm &amp;lt;- function(x) {&lt;br /&gt;
  rng &amp;lt;- range(x, na.rm = TRUE)&lt;br /&gt;
  if (diff(rng) == 0) return(rep(0, length(x)))&lt;br /&gt;
  (x - rng) / diff(rng)[1]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
project_metrics &amp;lt;- project_metrics |&amp;gt;&lt;br /&gt;
  mutate(&lt;br /&gt;
    balance_score   = minmax_norm(1 - gini_contribution),&lt;br /&gt;
    stigmergy_score = minmax_norm(succession_ratio),&lt;br /&gt;
    sync_score      = minmax_norm(shared_activity_index),&lt;br /&gt;
    teamwork_index  = (balance_score + stigmergy_score + sync_score) / 3,&lt;br /&gt;
    teamwork_tier   = ntile(teamwork_index, 4) |&amp;gt;&lt;br /&gt;
      factor(levels = 1:4,&lt;br /&gt;
             labels = c(&amp;quot;Q1_low&amp;quot;, &amp;quot;Q2&amp;quot;, &amp;quot;Q3&amp;quot;, &amp;quot;Q4_high&amp;quot;))&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
glimpse(project_metrics)&lt;br /&gt;
&lt;br /&gt;
tier_summary &amp;lt;- project_metrics |&amp;gt;&lt;br /&gt;
  group_by(teamwork_tier) |&amp;gt;&lt;br /&gt;
  summarise(&lt;br /&gt;
    n_projects      = n(),&lt;br /&gt;
    avg_authors     = mean(n_authors),&lt;br /&gt;
    avg_commits     = mean(n_commits),&lt;br /&gt;
    avg_gini        = mean(gini_contribution),&lt;br /&gt;
    avg_succession  = mean(succession_ratio),&lt;br /&gt;
    avg_shared      = mean(shared_activity_index),&lt;br /&gt;
    avg_refactoring = mean(refactoring_ratio),&lt;br /&gt;
    median_resp_min = median(mean_response_min, na.rm = TRUE),&lt;br /&gt;
    .groups = &amp;quot;drop&amp;quot;&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
kable(tier_summary, digits = 3,&lt;br /&gt;
      caption = &amp;quot;Характеристики проектов по квартилям командности&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
glimpse(tier_summary)&lt;br /&gt;
&lt;br /&gt;
#---------------&lt;br /&gt;
&lt;br /&gt;
ggplot(project_metrics,&lt;br /&gt;
       aes(x = teamwork_tier, y = succession_ratio,&lt;br /&gt;
           fill = teamwork_tier)) +&lt;br /&gt;
  geom_boxplot(alpha = 0.7, outlier.size = 0.8, outlier.alpha = 0.4) +&lt;br /&gt;
  stat_summary(fun = mean, geom = &amp;quot;point&amp;quot;, shape = 18,&lt;br /&gt;
               size = 3, colour = &amp;quot;white&amp;quot;) +&lt;br /&gt;
  scale_fill_manual(values = c(&amp;quot;#c0392b&amp;quot;,&amp;quot;#e67e22&amp;quot;,&amp;quot;#2980b9&amp;quot;,&amp;quot;#27ae60&amp;quot;)) +&lt;br /&gt;
  labs(&lt;br /&gt;
    title    = &amp;quot;Стигмергический обмен следами по уровням командности&amp;quot;,&lt;br /&gt;
    subtitle = &amp;quot;Succession ratio = доля коммитов, где следующий автор — другой участник&amp;quot;,&lt;br /&gt;
    x        = &amp;quot;Уровень командности (IMOI–Stigmergy)&amp;quot;,&lt;br /&gt;
    y        = &amp;quot;Succession ratio&amp;quot;&lt;br /&gt;
  ) +&lt;br /&gt;
  theme_minimal(base_size = 13) +&lt;br /&gt;
  theme(legend.position = &amp;quot;none&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#----  Компоненты индекса командности&lt;br /&gt;
&lt;br /&gt;
components_long &amp;lt;- project_metrics |&amp;gt;&lt;br /&gt;
  group_by(teamwork_tier) |&amp;gt;&lt;br /&gt;
  summarise(&lt;br /&gt;
    `Баланс участия`   = mean(balance_score,   na.rm = TRUE),&lt;br /&gt;
    `Stigmergy (след)` = mean(stigmergy_score, na.rm = TRUE),&lt;br /&gt;
    `Синхронность`     = mean(sync_score,      na.rm = TRUE),&lt;br /&gt;
    .groups = &amp;quot;drop&amp;quot;&lt;br /&gt;
  ) |&amp;gt;&lt;br /&gt;
  pivot_longer(-teamwork_tier,&lt;br /&gt;
               names_to = &amp;quot;component&amp;quot;, values_to = &amp;quot;value&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
ggplot(components_long,&lt;br /&gt;
       aes(x = teamwork_tier, y = value, fill = component)) +&lt;br /&gt;
  geom_col(position = &amp;quot;dodge&amp;quot;, alpha = 0.85) +&lt;br /&gt;
  scale_fill_manual(values = c(&amp;quot;#2980b9&amp;quot;,&amp;quot;#27ae60&amp;quot;,&amp;quot;#e67e22&amp;quot;)) +&lt;br /&gt;
  labs(&lt;br /&gt;
    title    = &amp;quot;Компоненты индекса командности по квартилям&amp;quot;,&lt;br /&gt;
    subtitle = &amp;quot;IMOI–Stigmergy: баланс участия, стигмергия, синхронность&amp;quot;,&lt;br /&gt;
    x        = &amp;quot;Уровень командности&amp;quot;,&lt;br /&gt;
    y        = &amp;quot;Нормированное значение (0–1)&amp;quot;,&lt;br /&gt;
    fill     = &amp;quot;Компонент&amp;quot;&lt;br /&gt;
  ) +&lt;br /&gt;
  theme_minimal(base_size = 13) +&lt;br /&gt;
  theme(legend.position = &amp;quot;top&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# --  Радар-график профилей квартилей&lt;br /&gt;
&lt;br /&gt;
library(fmsb) &lt;br /&gt;
&lt;br /&gt;
radar_data &amp;lt;- project_metrics |&amp;gt;&lt;br /&gt;
  group_by(teamwork_tier) |&amp;gt;&lt;br /&gt;
  summarise(&lt;br /&gt;
    balance   = mean(balance_score,   na.rm = TRUE),&lt;br /&gt;
    stigmergy = mean(stigmergy_score, na.rm = TRUE),&lt;br /&gt;
    sync      = mean(sync_score,      na.rm = TRUE),&lt;br /&gt;
    .groups = &amp;quot;drop&amp;quot;&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
radar_df &amp;lt;- rbind(&lt;br /&gt;
  max = c(1, 1, 1),&lt;br /&gt;
  min = c(0, 0, 0),&lt;br /&gt;
  radar_data |&amp;gt; select(balance, stigmergy, sync)&lt;br /&gt;
)&lt;br /&gt;
rownames(radar_df) &amp;lt;- c(&amp;quot;max&amp;quot;, &amp;quot;min&amp;quot;, as.character(radar_data$teamwork_tier))&lt;br /&gt;
&lt;br /&gt;
radarchart(radar_df,&lt;br /&gt;
           axistype = 1,&lt;br /&gt;
           pcol = c(&amp;quot;red&amp;quot;,&amp;quot;orange&amp;quot;,&amp;quot;blue&amp;quot;,&amp;quot;darkgreen&amp;quot;),&lt;br /&gt;
           plwd = 2, plty = 1,&lt;br /&gt;
           title = &amp;quot;Профили командности IMOI–Stigmergy по квартилям&amp;quot;)&lt;br /&gt;
legend(&amp;quot;topright&amp;quot;, legend = as.character(radar_data$teamwork_tier),&lt;br /&gt;
       col = c(&amp;quot;red&amp;quot;,&amp;quot;orange&amp;quot;,&amp;quot;blue&amp;quot;,&amp;quot;darkgreen&amp;quot;), lwd = 2, bty = &amp;quot;n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#------------------- Баланс вклада vs стигмергия&lt;br /&gt;
&lt;br /&gt;
plot_data &amp;lt;- project_metrics |&amp;gt;&lt;br /&gt;
  filter(!is.na(gini_contribution), !is.na(succession_ratio)) |&amp;gt;&lt;br /&gt;
  mutate(&lt;br /&gt;
    tier = factor(teamwork_tier,&lt;br /&gt;
                  levels = c(&amp;quot;Q1_low&amp;quot;,&amp;quot;Q2&amp;quot;,&amp;quot;Q3&amp;quot;,&amp;quot;Q4_high&amp;quot;),&lt;br /&gt;
                  labels = c(&amp;quot;Q1 low&amp;quot;,&amp;quot;Q2&amp;quot;,&amp;quot;Q3&amp;quot;,&amp;quot;Q4 high&amp;quot;))&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
ggplot(plot_data,&lt;br /&gt;
       aes(x = gini_contribution,&lt;br /&gt;
           y = succession_ratio,&lt;br /&gt;
           color = tier)) +&lt;br /&gt;
  geom_point(alpha = 0.35, size = 1.2) +&lt;br /&gt;
  geom_smooth(aes(group = 1),&lt;br /&gt;
              method = &amp;quot;loess&amp;quot;, formula = y ~ x,&lt;br /&gt;
              se = TRUE, color = &amp;quot;black&amp;quot;,&lt;br /&gt;
              linewidth = 1.2, linetype = &amp;quot;solid&amp;quot;) +&lt;br /&gt;
  geom_vline(xintercept = 0.20, linetype = &amp;quot;dashed&amp;quot;,&lt;br /&gt;
             color = &amp;quot;steelblue&amp;quot;, linewidth = 0.8) +&lt;br /&gt;
  geom_vline(xintercept = 0.50, linetype = &amp;quot;dashed&amp;quot;,&lt;br /&gt;
             color = &amp;quot;tomato&amp;quot;, linewidth = 0.8) +&lt;br /&gt;
  annotate(&amp;quot;text&amp;quot;, x = 0.10, y = 0.97,&lt;br /&gt;
           label = &amp;quot;Zone A\nequal&amp;quot;, color = &amp;quot;steelblue&amp;quot;,&lt;br /&gt;
           size = 3.2, fontface = &amp;quot;italic&amp;quot;) +&lt;br /&gt;
  annotate(&amp;quot;text&amp;quot;, x = 0.34, y = 0.97,&lt;br /&gt;
           label = &amp;quot;Zone B\noptimal&amp;quot;, color = &amp;quot;grey20&amp;quot;,&lt;br /&gt;
           size = 3.2, fontface = &amp;quot;bold&amp;quot;) +&lt;br /&gt;
  annotate(&amp;quot;text&amp;quot;, x = 0.70, y = 0.97,&lt;br /&gt;
           label = &amp;quot;Zone C\ndominance&amp;quot;, color = &amp;quot;tomato&amp;quot;,&lt;br /&gt;
           size = 3.2, fontface = &amp;quot;italic&amp;quot;) +&lt;br /&gt;
  scale_color_manual(&lt;br /&gt;
    values = c(&amp;quot;Q1 low&amp;quot;  = &amp;quot;#c0392b&amp;quot;,&lt;br /&gt;
               &amp;quot;Q2&amp;quot;      = &amp;quot;#e67e22&amp;quot;,&lt;br /&gt;
               &amp;quot;Q3&amp;quot;      = &amp;quot;#2980b9&amp;quot;,&lt;br /&gt;
               &amp;quot;Q4 high&amp;quot; = &amp;quot;#27ae60&amp;quot;),&lt;br /&gt;
    name = &amp;quot;Teamwork tier&amp;quot;&lt;br /&gt;
  ) +&lt;br /&gt;
  labs(&lt;br /&gt;
    title   = &amp;quot;Contribution balance vs Stigmergic exchange&amp;quot;,&lt;br /&gt;
    subtitle= &amp;quot;Gini coefficient vs Succession ratio | N ≈ 3,400 GitLab-проектов&amp;quot;,&lt;br /&gt;
    x       = &amp;quot;Gini of contribution (0 = equal, 1 = one author does all)&amp;quot;,&lt;br /&gt;
    y       = &amp;quot;Succession ratio (fraction of commits: next author != previous)&amp;quot;,&lt;br /&gt;
    caption = &amp;quot;Black line = LOESS trend; dashed lines = zone boundaries&amp;quot;&lt;br /&gt;
  ) +&lt;br /&gt;
  theme_minimal(base_size = 13) +&lt;br /&gt;
  theme(&lt;br /&gt;
    plot.title    = element_text(face = &amp;quot;bold&amp;quot;),&lt;br /&gt;
    plot.subtitle = element_text(color = &amp;quot;grey40&amp;quot;),&lt;br /&gt;
    legend.position = &amp;quot;right&amp;quot;&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Patarakin</name></author>
	</entry>
</feed>