Switch to side-by-side view

--- a/metric-providers/org.ossmeter.metricprovider.trans.rascal.activecommitters/src/ActiveCommitters.rsc
+++ b/metric-providers/org.ossmeter.metricprovider.trans.rascal.activecommitters/src/ActiveCommitters.rsc
@@ -10,7 +10,8 @@
 import DateTime;
 import String;
 import util::Math;
-
+import analysis::statistics::SimpleRegression;
+ 
 @metric{committersToday}
 @doc{activeCommitters}
 @friendlyName{activeCommitters}
@@ -30,6 +31,17 @@
   return {<d,t> | <d,t> <- prev, d > twoweeks} + {<today, committersToday>};  
 }
 
+@metric{longerTermActiveCommitters}
+@doc{Committers who have been active the last 6 months}
+@friendlyName{committersLastTwoWeeks}
+@uses{("org.ossmeter.metricprovider.trans.rascal.activecommitters.committersToday":"committersToday")}
+@appliesTo{generic()}
+rel[datetime, set[str]] longerTermActiveCommitters(ProjectDelta delta = \empty(), rel[datetime,set[str]] prev = {}, set[str] committersToday = {}) {
+  today    = delta.date;
+  twoweeks = decrementMonths(today, 6);
+  return {<d,t> | <d,t> <- prev, d > twoweeks} + {<today, committersToday>};  
+}
+
 
 @metric{numberOfActiveCommitters}
 @doc{Number of active committers over time}
@@ -38,6 +50,14 @@
 @appliesTo{generic()}
 @historic{}
 int numberOfActiveCommitters(rel[datetime, set[str]] activeCommitters = {}) 
+  = size({c | /str c := activeCommitters});
+  
+@metric{numberOfActiveCommittersLongTerm}
+@doc{Number of active committers over time}
+@friendlyName{numberOfActiveCommittersLongTerm}
+@uses{("org.ossmeter.metricprovider.trans.rascal.activecommitters.longerTermActiveCommitters" :"activeCommitters")}
+@appliesTo{generic()}
+int numberOfActiveCommittersLongTerm(rel[datetime, set[str]] activeCommitters = {}) 
   = size({c | /str c := activeCommitters});
 
 @metric{maximumActiveCommittersEver}
@@ -49,11 +69,46 @@
   return max(history<n>);
 }
 
-@metric{programmerCommunity}
+@metric{developmentTeamStability}
 @doc{based on committer activity, what is the health of the community?}
-@friendlyName{community of programmers}
+@friendlyName{Development team stability}
+@uses{("org.ossmeter.metricprovider.trans.rascal.activecommitters.numberOfActiveCommitters.historic" :"history"
+      ,"org.ossmeter.metricprovider.trans.rascal.activecommitters.maximumActiveCommittersEver":"maxDevs"
+      ,"org.ossmeter.metricprovider.trans.rascal.activecommitters.numberOfActiveCommitters":"activeDevs"
+      ,"org.ossmeter.metricprovider.trans.rascal.activecommitters.numberOfActiveCommittersLongTerm":"longTermActive")}
 @appliesTo{generic()}
-Factoid programmerCommunity() {
-  return factoid("This is a test", four());
+Factoid developmentTeamStability(rel[datetime day, int active] history = {}, int maxDevs = 0, int activeDevs = 0, int longTermActive = 0) {
+  sorted = sort(history, bool(tuple[datetime,int] a, tuple[datetime,int] b) { return a[0] < b[0]; });
+  
+  halfYearAgo = decrementMonths(sorted[-1].day, 6);  
+  lastYear = [<d,m> | <d,m> <- sorted, d > halfYearAgo];
+  sl = slope([<i,lastYear[i][1]> | i <- index(lastYear)]);
+
+  stability = \one();
+  team = "";
+  
+  if (-0.1 < sl && sl < 0.1 && longTermActive > 0) {
+    stability = \three(); 
+    team = "In the last half year the development team was stable and active.";
+  }
+  else if (-0.1 < sl && sl < 0.1 && longTermActive == 0) {
+    stability = \one(); // project is dead
+    team = "The project has seen hardly anybody developing in the last half year.";
+  } 
+  else if (sl < 0 && longTermActive > 0) {
+    stability = \two(); 
+    team = "People have been leaving the development team in the last half year.";
+  }
+  else if (sl > 0) {
+    stability = \four(); // people are coming
+    team = "In the last half year the development team has been growing.";
+  }
+  
+  txt = "<team>
+        'The maximum number of active developers for this project during its lifetime is <maxDevs>,
+        'and in the last two weeks there were <activeDevs> people actively developing, as compared to 
+        '<longTermActive> in the last six months.";
+        
+  return factoid(txt, stability);
 }