[GitHub] asfgit closed pull request #57: IGNITE-9849 Refactor Master trends

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[GitHub] asfgit closed pull request #57: IGNITE-9849 Refactor Master trends

GitBox
asfgit closed pull request #57: IGNITE-9849 Refactor Master trends
URL: https://github.com/apache/ignite-teamcity-bot/pull/57
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
index 824dc4a3..121f895e 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
@@ -66,6 +66,8 @@
 
     private static final String BUILD_STATISTICS = "buildStatistics";
 
+    private static final String BUILD_CONDITIONS_CACHE_NAME = "buildConditions";
+
     public static final String TESTS_COUNT_7700 = ",count:7700";
 
     //V1 caches, 1024 parts
@@ -407,6 +409,7 @@ public void dataMigration(
         applyDestroyIgnCacheMigration(TESTS);
         applyDestroyIgnCacheMigration(STAT);
         applyDestroyIgnCacheMigration(BUILD_STATISTICS);
+        applyDestroyIgnCacheMigration(BUILD_CONDITIONS_CACHE_NAME);
         applyDestroyCacheMigration(TEAMCITY_BUILD_CACHE_NAME_OLD, TEAMCITY_BUILD_CACHE_NAME_OLD);
     }
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
index a3aff88e..a0f6d369 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefCompacted.java
@@ -140,7 +140,7 @@ public int branchName() {
     }
 
     /** */
-    private int status() {
+    public int status() {
         return status;
     }
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java
index 0d7467a9..8a9a2643 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/BuildRefDao.java
@@ -34,6 +34,7 @@
 import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.di.cache.GuavaCached;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.util.GridIntList;
 import org.jetbrains.annotations.NotNull;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
index cfdaa2eb..3e69094d 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
@@ -17,9 +17,10 @@
 package org.apache.ignite.ci.teamcity.ignited;
 
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import javax.annotation.Nullable;
-import org.apache.ignite.ci.tcbot.condition.BuildCondition;
+import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildCondition;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
@@ -40,7 +41,7 @@
     public String host();
 
     /**
-     * Retun all builds for branch and suite, without relation to its status.
+     * Return all builds for branch and suite, without relation to its status.
      *
      * @param buildTypeId Build type identifier.
      * @param branchName Branch name.
@@ -50,7 +51,6 @@
             @Nullable String buildTypeId,
             @Nullable String branchName);
 
-
     /**
      * Retun all builds for branch and suite, without relation to its status.
      *
@@ -62,6 +62,21 @@
         @Nullable String buildTypeId,
         @Nullable String branchName);
 
+    /**
+     * Return all builds for branch and suite with finish status.
+     *
+     * @param buildTypeId Build type identifier.
+     * @param branchName Branch name.
+     * @param sinceDate Since date.
+     * @param untilDate Until date.
+     * @return list of builds in history in finish status.
+     */
+    public List<BuildRefCompacted> getFinishedBuildsCompacted(
+        @Nullable String buildTypeId,
+        @Nullable String branchName,
+        @Nullable Date sinceDate,
+        @Nullable Date untilDate);
+
     /**
      * Trigger build. Enforces TC Bot to load all builds related to this triggered one.
      *
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
index ce05e930..ec1bf228 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
@@ -18,12 +18,13 @@
 
 
 import com.google.common.collect.Sets;
+import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.ignite.ci.ITeamcity;
 import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.di.MonitoredTask;
 import org.apache.ignite.ci.di.scheduler.IScheduler;
-import org.apache.ignite.ci.tcbot.condition.BuildCondition;
-import org.apache.ignite.ci.tcbot.condition.BuildConditionDao;
+import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildCondition;
+import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
@@ -44,6 +45,8 @@
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
+import static org.apache.ignite.ci.tcmodel.hist.BuildRef.STATUS_UNKNOWN;
+
 public class TeamcityIgnitedImpl implements ITeamcityIgnited {
     /** Logger. */
     private static final Logger logger = LoggerFactory.getLogger(TeamcityIgnitedImpl.class);
@@ -116,6 +119,153 @@ private String taskName(String taskName) {
         return conn.host();
     }
 
+    /** {@inheritDoc} */
+    public List<BuildRefCompacted> getFinishedBuildsCompacted(
+        @Nullable String buildTypeId,
+        @Nullable String branchName,
+        @Nullable Date sinceDate,
+        @Nullable Date untilDate) {
+        final int allDatesOutOfBounds = -1;
+        final int someDatesOutOfBounds = -2;
+        final int invalidVal = -3;
+        final int unknownStatus = compactor.getStringId(STATUS_UNKNOWN);
+
+        List<BuildRefCompacted> buildRefs = getBuildHistoryCompacted(buildTypeId, branchName)
+            .stream().filter(b -> b.status() != unknownStatus).collect(Collectors.toList());
+
+        int idSince = 0;
+        int idUntil = buildRefs.size() - 1;
+
+        if (sinceDate != null) {
+            idSince = binarySearchDate(buildRefs, 0, buildRefs.size(), sinceDate, true);
+            idSince = (idSince == someDatesOutOfBounds) ? 0 : idSince;
+        }
+
+        if (untilDate != null) {
+            idUntil = (idSince < 0) ? allDatesOutOfBounds :
+                binarySearchDate(buildRefs, idSince, buildRefs.size(), untilDate, false);
+            idUntil = (idUntil == someDatesOutOfBounds) ? buildRefs.size() - 1 : idUntil;
+        }
+
+        if (idSince == invalidVal || idUntil == invalidVal) {
+            AtomicBoolean stopFilter = new AtomicBoolean();
+            AtomicBoolean addBuild = new AtomicBoolean();
+
+            return buildRefs.stream()
+                .filter(b -> {
+                    if (stopFilter.get())
+                        return addBuild.get();
+
+                    FatBuildCompacted build = getFatBuild(b.id());
+
+                    if (build == null || build.isFakeStub())
+                        return false;
+
+                    Date date = build.getStartDate();
+
+                    if (sinceDate != null && untilDate != null)
+                        if ((date.after(sinceDate) || date.equals(sinceDate)) &&
+                            (date.before(untilDate) || date.equals(untilDate)))
+                            return true;
+                        else {
+                            if (date.after(untilDate)) {
+                                stopFilter.set(true);
+                                addBuild.set(false);
+                            }
+
+                            return false;
+                        }
+                    else if (sinceDate != null) {
+                        if (date.after(sinceDate) || date.equals(sinceDate)) {
+                            stopFilter.set(true);
+                            addBuild.set(true);
+
+                            return true;
+                        }
+
+                        return false;
+                    }
+                    else {
+                        if (date.after(untilDate)) {
+                            stopFilter.set(true);
+                            addBuild.set(false);
+
+                            return false;
+                        }
+
+                        return true;
+                    }
+                })
+                .collect(Collectors.toList());
+        } else if (idSince == allDatesOutOfBounds || idUntil == allDatesOutOfBounds)
+            return Collections.emptyList();
+        else
+            return buildRefs.subList(idSince, idUntil + 1);
+    }
+
+    /**
+     * @param buildRefs Build refs list.
+     * @param fromIdx From index.
+     * @param toIdx To index.
+     * @param key Key.
+     * @param since {@code true} If key is sinceDate, {@code false} is untilDate.
+     *
+     * @return {@value >= 0} Build id from list with min interval between key. If since {@code true}, min interval
+     * between key and same day or later. If since {@code false}, min interval between key and same day or earlier;
+     * {@value -1} All dates out of bounds. If sinceDate after last list element date or untilDate before first list
+     * element;
+     * {@value -2} Some dates out of bounds. If sinceDate before first list element or untilDate after last list
+     * element;
+     * {@value -3} Invalid value. If method get null or fake stub build.
+     */
+    private int binarySearchDate(List<BuildRefCompacted> buildRefs, int fromIdx, int toIdx, Date key, boolean since) {
+        final int allDatesOutOfBounds = -1;
+        final int someDatesOutOfBounds = -2;
+        final int invalidVal = -3;
+
+        int low = fromIdx;
+        int high = toIdx - 1;
+        long minDiff = key.getTime();
+        int minDiffId = since ? low : high;
+        long temp;
+
+        FatBuildCompacted highBuild = getFatBuild(buildRefs.get(high).id());
+        FatBuildCompacted lowBuild = getFatBuild(buildRefs.get(low).id());
+
+        if (highBuild != null && !highBuild.isFakeStub()){
+            if (highBuild.getStartDate().before(key))
+                return since ? allDatesOutOfBounds : someDatesOutOfBounds;
+        }
+
+        if (lowBuild != null && !lowBuild.isFakeStub()){
+            if (lowBuild.getStartDate().after(key))
+                return since ? someDatesOutOfBounds : allDatesOutOfBounds;
+        }
+
+        while (low <= high) {
+            int mid = (low + high) >>> 1;
+            FatBuildCompacted midVal = getFatBuild(buildRefs.get(mid).id());
+
+            if (midVal != null && !midVal.isFakeStub()) {
+                if (midVal.getStartDate().after(key))
+                    high = mid - 1;
+                else if (midVal.getStartDate().before(key))
+                    low = mid + 1;
+                else
+                    return mid;
+
+                temp = midVal.getStartDate().getTime() - key.getTime();
+
+                if ((temp > 0 == since) && (Math.abs(temp) < minDiff)) {
+                    minDiff = Math.abs(temp);
+                    minDiffId = mid;
+                }
+            } else
+                return invalidVal;
+        }
+        return minDiffId;
+    }
+
     /** {@inheritDoc} */
     @AutoProfiling
     @Override public List<BuildRef> getBuildHistory(
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
index 691c6d9f..ceb427fd 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
@@ -18,7 +18,7 @@
 
 import com.google.inject.AbstractModule;
 import com.google.inject.internal.SingletonScope;
-import org.apache.ignite.ci.tcbot.condition.BuildConditionDao;
+import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeDao;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildCondition.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildCondition.java
similarity index 97%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildCondition.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildCondition.java
index 6a1e0fa2..ac50f48a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildCondition.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildCondition.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.tcbot.condition;
+package org.apache.ignite.ci.teamcity.ignited.buildcondition;
 
 import java.util.Date;
 import java.util.Objects;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionCompacted.java
similarity index 95%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionCompacted.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionCompacted.java
index 430eb8d0..93074cd2 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionCompacted.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.tcbot.condition;
+package org.apache.ignite.ci.teamcity.ignited.buildcondition;
 
 import java.util.Date;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
@@ -44,7 +44,7 @@ public BuildConditionCompacted() {
     }
 
     /**
-     * @param compactor Compacter.
+     * @param compactor Compactor.
      * @param cond Build condition.
      */
     public BuildConditionCompacted(IStringCompactor compactor, BuildCondition cond) {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionDao.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionDao.java
similarity index 87%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionDao.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionDao.java
index 633eddc6..5862b141 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionDao.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildcondition/BuildConditionDao.java
@@ -15,18 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.tcbot.condition;
+package org.apache.ignite.ci.teamcity.ignited.buildcondition;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
-import org.apache.ignite.ci.db.TcHelperDb;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 
+import static org.apache.ignite.ci.teamcity.ignited.IgniteStringCompactor.getCache8PartsConfig;
+
 public class BuildConditionDao {
     /** Cache name*/
-    public static final String BUILD_CONDITIONS_CACHE_NAME = "buildConditions";
+    public static final String BUILDS_CONDITIONS_CACHE_NAME = "buildsConditions";
 
     /** Ignite provider. */
     @Inject private Provider<Ignite> igniteProvider;
@@ -42,7 +43,7 @@
      */
     public void init () {
         Ignite ignite = igniteProvider.get();
-        buildsCache = ignite.getOrCreateCache(TcHelperDb.getCacheV2Config(BUILD_CONDITIONS_CACHE_NAME));
+        buildsCache = ignite.getOrCreateCache(getCache8PartsConfig(BUILDS_CONDITIONS_CACHE_NAME));
     }
 
     /**
@@ -50,7 +51,6 @@ public void init () {
      * @param buildId Build id.
      */
     private long buildIdToCacheKey(long srvIdMaskHigh, int buildId) {
-
         return (long)buildId | srvIdMaskHigh << 32;
     }
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
index 04f2a638..4ffc4598 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
@@ -18,6 +18,8 @@
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.ignite.ci.analysis.IVersionedEntity;
 import org.apache.ignite.ci.db.Persisted;
 import org.apache.ignite.ci.tcmodel.conf.BuildType;
@@ -56,6 +58,9 @@
 
     /**   flag offset. */
     public static final int FAKE_BUILD_F = 4;
+
+    /** Failed to start flag offset. */
+    public static final int FAILED_TO_START_F = 6;
     public static final int[] EMPTY = new int[0];
 
     /** Entity fields version. */
@@ -121,15 +126,25 @@ public FatBuildCompacted(IStringCompactor compactor, Build build) {
             name = compactor.getStringId(type.getName());
         }
 
+        AtomicBoolean failedToStart = new AtomicBoolean();
+
         int[] arr = build.getSnapshotDependenciesNonNull().stream()
-            .filter(b -> b.getId() != null).mapToInt(BuildRef::getId).toArray();
+            .filter(b -> {
+                if (!(failedToStart.get() || b.isNotCancelled()))
+                    failedToStart.set(true);
+
+                return b.getId() != null;
+            }).mapToInt(BuildRef::getId).toArray();
 
         snapshotDeps = arr.length > 0 ? arr : null;
 
         setFlag(DEF_BR_F, build.defaultBranch);
         setFlag(COMPOSITE_F, build.composite);
 
-        if(build.isFakeStub())
+        if (failedToStart.get())
+            setFlag(FAILED_TO_START_F, true);
+
+        if (build.isFakeStub())
             setFlag(FAKE_BUILD_F, true);
     }
 
@@ -246,12 +261,17 @@ public TestOccurrencesFull getTestOcurrences(IStringCompactor compactor) {
 
         TestOccurrencesFull testOccurrences = new TestOccurrencesFull();
 
-        testOccurrences.setTests(res);
         testOccurrences.count = res.size();
+        testOccurrences.setTests(res);
 
         return testOccurrences;
     }
 
+    /** Start date. */
+    public Date getStartDate() {
+        return new Date(startDate);
+    }
+
     /** {@inheritDoc} */
     @Override public boolean equals(Object o) {
         if (this == o)
@@ -290,6 +310,24 @@ public boolean isComposite() {
         return flag != null && flag;
     }
 
+    /**
+     *
+     */
+    public boolean isFakeStub() {
+        Boolean flag = getFlag(FAKE_BUILD_F);
+
+        return flag != null && flag;
+    }
+
+    /**
+     *
+     */
+    public boolean isFailedToStart() {
+        Boolean flag = getFlag(FAILED_TO_START_F);
+
+        return flag != null && flag;
+    }
+
     public Stream<TestCompacted> getFailedNotMutedTests(IStringCompactor compactor) {
         if (tests == null)
             return Stream.of();
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
index f15c4189..9340682f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
@@ -82,7 +82,7 @@ public ProblemOccurrence toProblemOccurrence(IStringCompactor compactor, int bui
 
         String fullStrId =
                 "problem:(id:" + id + ")," +
-                        " build:(id:" + buildId + ")";
+                        "build:(id:" + buildId + ")";
         occurrence.id(fullStrId);
         occurrence.type = compactor.getStringFromId(type);
         occurrence.identity = compactor.getStringFromId(identity);
@@ -148,6 +148,10 @@ public boolean isSnapshotDepProblem(IStringCompactor compactor) {
                 || compactor.getStringId(ProblemOccurrence.SNAPSHOT_DEPENDENCY_ERROR_BUILD_PROCEEDS_TYPE) == type;
     }
 
+    public int type() {
+        return type;
+    }
+
     @Override public String toString() {
         return MoreObjects.toStringHelper(this)
             .add("id", id)
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
index 753a0bae..2433849a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
@@ -345,6 +345,10 @@ public boolean isInvestigated() {
         return investigatedFlag != null && investigatedFlag;
     }
 
+    public int status() {
+        return status;
+    }
+
     @Nullable
     public Integer getDuration() {
         return duration < 0 ? null : duration;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/BuildStatisticsSummary.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/BuildStatisticsSummary.java
index 0c604cd9..a46d4611 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/BuildStatisticsSummary.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/BuildStatisticsSummary.java
@@ -27,19 +27,23 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 import javax.annotation.Nonnull;
-import org.apache.ignite.ci.ITeamcity;
-import org.apache.ignite.ci.tcmodel.hist.BuildRef;
-import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.tcmodel.result.TestOccurrencesRef;
-import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
-import org.apache.ignite.ci.web.rest.parms.FullQueryParams;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProblemCompacted;
+
+import static org.apache.ignite.ci.tcmodel.hist.BuildRef.STATUS_SUCCESS;
+import static org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence.*;
 
 /**
  * Summary of build statistics.
  */
 public class BuildStatisticsSummary {
+    /** String ids. */
+    public static HashMap<String, Integer> strIds = new HashMap<>();
+
     /** Short problem names. */
     public static final String TOTAL = "TOTAL";
 
@@ -51,10 +55,10 @@
 
     static {
         shortProblemNames.put(TOTAL, "TT");
-        shortProblemNames.put(ProblemOccurrence.TC_EXECUTION_TIMEOUT, "ET");
-        shortProblemNames.put(ProblemOccurrence.TC_JVM_CRASH, "JC");
-        shortProblemNames.put(ProblemOccurrence.TC_OOME, "OO");
-        shortProblemNames.put(ProblemOccurrence.TC_EXIT_CODE, "EC");
+        shortProblemNames.put(TC_EXECUTION_TIMEOUT, "ET");
+        shortProblemNames.put(TC_JVM_CRASH, "JC");
+        shortProblemNames.put(TC_OOME, "OO");
+        shortProblemNames.put(TC_EXIT_CODE, "EC");
 
         fullProblemNames = shortProblemNames.inverse();
     }
@@ -66,10 +70,10 @@
     public String startDate;
 
     /** Test occurrences. */
-    public TestOccurrencesRef testOccurrences;
+    public TestOccurrencesRef testOccurrences = new TestOccurrencesRef();
 
     /** List of problem occurrences. */
-    private List<ProblemOccurrence> problemOccurrenceList;
+    private List<ProblemCompacted> problemOccurrenceList;
 
     /** Duration (seconds). */
     public long duration;
@@ -86,13 +90,21 @@
     /**
      * @param buildId Build id.
      */
-    public BuildStatisticsSummary(Integer buildId){
+    public BuildStatisticsSummary(Integer buildId) {
         this.buildId = buildId;
     }
 
     /** Initialize build statistics. */
-    public void initialize(@Nonnull final ITeamcity teamcity) {
-        Build build = teamcity.getBuild(buildId);
+    public void initialize(@Nonnull final IStringCompactor compactor, @Nonnull final ITeamcityIgnited ignitedTeamcity) {
+        if (strIds.isEmpty()) {
+            strIds.put(STATUS_SUCCESS, compactor.getStringId(STATUS_SUCCESS));
+            strIds.put(TC_EXIT_CODE, compactor.getStringId(TC_EXIT_CODE));
+            strIds.put(TC_OOME, compactor.getStringId(TC_OOME));
+            strIds.put(TC_JVM_CRASH, compactor.getStringId(TC_JVM_CRASH));
+            strIds.put(TC_EXECUTION_TIMEOUT, compactor.getStringId(TC_EXECUTION_TIMEOUT));
+        }
+
+        FatBuildCompacted build = ignitedTeamcity.getFatBuild(buildId);
 
         isFakeStub = build.isFakeStub();
 
@@ -100,113 +112,107 @@ public void initialize(@Nonnull final ITeamcity teamcity) {
             return;
 
         DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy'T'HH:mm:ss");
-        dateFormat.format(build.getFinishDate());
+
         startDate = dateFormat.format(build.getStartDate());
 
-        testOccurrences = build.testOccurrences;
+        int[] arr = new int[4];
 
-        duration = (build.getFinishDate().getTime() - build.getStartDate().getTime()) / 1000;
+        build.getAllTests().forEach(t -> {
+                if (t.getIgnoredFlag())
+                    arr[0]++;
+                else if (t.getMutedFlag())
+                    arr[1]++;
+                else if (t.status() != strIds.get(STATUS_SUCCESS))
+                    arr[2]++;
 
-        List<BuildRef> snapshotDependencies = getSnapshotDependencies(teamcity, build);
+            arr[3]++;
+        });
 
-        List<BuildRef> snapshotDependenciesWithProblems = getBuildsWithProblems(snapshotDependencies);
+        testOccurrences.ignored = arr[0];
+        testOccurrences.muted = arr[1];
+        testOccurrences.failed = arr[2];
+        testOccurrences.count = arr[3];
+        testOccurrences.passed = testOccurrences.count - testOccurrences.failed - testOccurrences.ignored -
+        testOccurrences.muted;
 
-        problemOccurrenceList = getProblems(teamcity, snapshotDependenciesWithProblems);
+        duration = build.buildDuration(compactor) / 1000;
 
-        totalProblems = getRes();
-    }
+        List<FatBuildCompacted> snapshotDependencies = getSnapshotDependencies(ignitedTeamcity, buildId);
 
-    private long getExecutionTimeoutCount(String buildTypeId) {
-        return getProblemsStream(buildTypeId).filter(ProblemOccurrence::isExecutionTimeout).count();
-    }
+        List<FatBuildCompacted> snapshotDependenciesWithProblems = getBuildsWithProblems(snapshotDependencies);
 
-    private long getJvmCrashProblemCount(String buildTypeId) {
-        return getProblemsStream(buildTypeId).filter(ProblemOccurrence::isJvmCrash).count();
-    }
+        problemOccurrenceList = getProblems(snapshotDependenciesWithProblems);
 
-    private long getExitCodeProblemsCount(String buildTypeId) {
-        return getProblemsStream(buildTypeId).filter(ProblemOccurrence::isExitCode).count();
+        totalProblems = getBuildTypeProblemsCount();
     }
 
-    private long getOomeProblemCount(String buildTypeId) {
-        return getProblemsStream(buildTypeId).filter(ProblemOccurrence::isOome).count();
+    /**
+     * @param problemName Problem name.
+     */
+    private long getProblemsCount(String problemName) {
+        if (problemOccurrenceList == null)
+            return 0;
+
+        return problemOccurrenceList.stream()
+            .filter(Objects::nonNull)
+            .filter(p -> p.type() == strIds.get(problemName)).count();
     }
 
     /**
      * Problems for all snapshot-dependencies.
      *
-     * @param teamcity Teamcity.
+     * @param builds Builds.
      */
-    private List<ProblemOccurrence> getProblems(@Nonnull final ITeamcity teamcity, List<BuildRef> builds){
-        List<ProblemOccurrence> problemOccurrences = new ArrayList<>();
-
-        for (BuildRef buildRef : builds)
-            problemOccurrences.addAll(teamcity
-                .getProblems(buildRef)
-                .getProblemsNonNull());
-
+    private List<ProblemCompacted> getProblems(List<FatBuildCompacted> builds) {
+        List<ProblemCompacted> problemOccurrences = new ArrayList<>();
+
+        for (FatBuildCompacted build : builds) {
+            problemOccurrences.addAll(
+                build.problems()
+            );
+        }
         return problemOccurrences;
     }
 
     /**
      * Snapshot-dependencies for build.
      *
-     * @param teamcity Teamcity.
-     * @param buildRef Build reference.
+     * @param ignitedTeamcity ignitedTeamcity.
+     * @param buildId Build Id.
      */
-    private List<BuildRef> getSnapshotDependencies(@Nonnull final ITeamcity teamcity, BuildRef buildRef){
-        FullQueryParams key = new FullQueryParams();
+    private List<FatBuildCompacted> getSnapshotDependencies(@Nonnull final ITeamcityIgnited ignitedTeamcity,
+        Integer buildId) {
+        List<FatBuildCompacted> snapshotDependencies = new ArrayList<>();
+        FatBuildCompacted build = ignitedTeamcity.getFatBuild(buildId);
 
-        key.setServerId(teamcity.serverId());
-        key.setBuildId(buildRef.getId());
+        if (build.snapshotDependencies().length > 0) {
+            for (Integer id : build.snapshotDependencies())
+                snapshotDependencies.addAll(getSnapshotDependencies(ignitedTeamcity, id));
+        }
 
-        return teamcity.getConfigurations(key).getBuilds();
-    }
+        snapshotDependencies.add(build);
 
+        return snapshotDependencies;
+    }
     /**
      * Builds without status "Success".
      */
-    private List<BuildRef> getBuildsWithProblems(List<BuildRef> builds){
+    private List<FatBuildCompacted> getBuildsWithProblems(List<FatBuildCompacted> builds) {
         return builds.stream()
-            .filter(b -> !b.isSuccess())
+            .filter(b -> b.status() != strIds.get(STATUS_SUCCESS))
             .collect(Collectors.toList());
     }
 
-    /**
-     * @param buildTypeId Build type id (if null - for all problems).
-     */
-    private Stream<ProblemOccurrence> getProblemsStream(String buildTypeId) {
-        if (problemOccurrenceList == null)
-            return Stream.empty();
-
-        return problemOccurrenceList.stream()
-            .filter(Objects::nonNull)
-            .filter(p -> buildTypeId == null || buildTypeId.equals(p.buildRef.buildTypeId));
-    }
-
-    /**
-     * Short build run result (without snapshot-dependencies result).
-     *
-     * @return printable result;
-     */
-    private Map<String, Long> getRes(){
-        return getBuildTypeProblemsCount(null);
-    }
-
-
     /**
      * BuildType problems count (EXECUTION TIMEOUT, JVM CRASH, OOMe, EXIT CODE, TOTAL PROBLEMS COUNT).
-     *
-     * @param buildTypeId Build type id.
      */
-    private Map<String, Long> getBuildTypeProblemsCount(String buildTypeId){
+    private Map<String, Long> getBuildTypeProblemsCount() {
         Map<String, Long> occurrences = new HashMap<>();
 
-        occurrences.put(shortProblemNames.get(ProblemOccurrence.TC_EXECUTION_TIMEOUT),
-            getExecutionTimeoutCount(buildTypeId));
-        occurrences.put(shortProblemNames.get(ProblemOccurrence.TC_JVM_CRASH), getJvmCrashProblemCount(buildTypeId));
-        occurrences.put(shortProblemNames.get(ProblemOccurrence.TC_OOME), getOomeProblemCount(buildTypeId));
-        occurrences.put(shortProblemNames.get(ProblemOccurrence.TC_EXIT_CODE), getExitCodeProblemsCount(buildTypeId));
+        occurrences.put(shortProblemNames.get(TC_EXECUTION_TIMEOUT), getProblemsCount(TC_EXECUTION_TIMEOUT));
+        occurrences.put(shortProblemNames.get(TC_JVM_CRASH), getProblemsCount(TC_JVM_CRASH));
+        occurrences.put(shortProblemNames.get(TC_OOME), getProblemsCount(TC_OOME));
+        occurrences.put(shortProblemNames.get(TC_EXIT_CODE), getProblemsCount(TC_EXIT_CODE));
         occurrences.put(shortProblemNames.get(TOTAL), occurrences.values().stream().mapToLong(Long::longValue).sum());
 
         return occurrences;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java
index 0f22a0e8..0e5126d2 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java
@@ -19,9 +19,7 @@
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Lists;
 import java.io.UncheckedIOException;
-import java.lang.reflect.Array;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -32,26 +30,27 @@
 import java.util.concurrent.Future;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 import javax.servlet.ServletContext;
-import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
 import org.apache.ignite.ci.ITcHelper;
 import org.apache.ignite.ci.ITeamcity;
 import org.apache.ignite.ci.tcbot.chain.BuildChainProcessor;
+import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrence;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrences;
+import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.CtxListener;
 import org.apache.ignite.ci.web.model.current.BuildStatisticsSummary;
-import org.apache.ignite.ci.web.rest.exception.ServiceUnauthorizedException;
 import org.apache.ignite.ci.web.rest.parms.FullQueryParams;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.apache.ignite.ci.tcmodel.hist.BuildRef.STATE_FINISHED;
 
 /**
  * Builds History: includes statistic for every build and merged failed unmuted tests in specified time interval.
@@ -92,25 +91,26 @@
 
     /** */
     public void initialize(ICredentialsProv prov, ServletContext context) {
-        if (!prov.hasAccess(srvId))
-            throw ServiceUnauthorizedException.noCreds(srvId);
+        final IStringCompactor compactor = CtxListener.getInjector(context).getInstance(IStringCompactor.class);
 
         ITcHelper tcHelper = CtxListener.getTcHelper(context);
 
-        IAnalyticsEnabledTeamcity teamcity = tcHelper.server(srvId, prov);
+        ITeamcity teamcity = tcHelper.server(srvId, prov);
 
         ITeamcityIgnitedProvider tcIgnitedProv = CtxListener.getInjector(context)
             .getInstance(ITeamcityIgnitedProvider.class);
 
-        ITeamcityIgnited ignited = tcIgnitedProv.server(srvId, prov);
+        ITeamcityIgnited ignitedTeamcity = tcIgnitedProv.server(srvId, prov);
 
-        int[] finishedBuildsIds = teamcity.getBuildNumbersFromHistory(buildTypeId, branchName,
-            sinceDateFilter, untilDateFilter);
+        List<Integer> finishedBuildsIds = ignitedTeamcity
+            .getFinishedBuildsCompacted(buildTypeId, branchName, sinceDateFilter, untilDateFilter)
+            .stream().mapToInt(BuildRefCompacted::id).boxed()
+            .collect(Collectors.toList());
 
-        Map<Integer, Boolean> buildIdsWithConditions = IntStream.of(finishedBuildsIds)
-            .boxed().collect(Collectors.toMap(v -> v, ignited::buildIsValid,  (e1, e2) -> e1, LinkedHashMap::new));
+        Map<Integer, Boolean> buildIdsWithConditions = finishedBuildsIds.stream()
+            .collect(Collectors.toMap(v -> v, ignitedTeamcity::buildIsValid,  (e1, e2) -> e1, LinkedHashMap::new));
 
-        initStatistics(teamcity, buildIdsWithConditions);
+        initStatistics(compactor, teamcity, ignitedTeamcity, buildIdsWithConditions);
 
         List<Integer> validBuilds = buildIdsWithConditions.keySet()
             .stream()
@@ -130,24 +130,23 @@ public void initialize(ICredentialsProv prov, ServletContext context) {
     }
 
     /** */
-    private void initStatistics(IAnalyticsEnabledTeamcity teamcity, Map<Integer, Boolean> buildIdsWithConditions) {
+    private void initStatistics(IStringCompactor compactor, ITeamcity teamcity, ITeamcityIgnited ignited,
+        Map<Integer, Boolean> buildIdsWithConditions) {
         List<Future<BuildStatisticsSummary>> buildStaticsFutures = new ArrayList<>();
 
         for (int buildId : buildIdsWithConditions.keySet()) {
             Future<BuildStatisticsSummary> buildFuture = CompletableFuture.supplyAsync(() -> {
                 BuildStatisticsSummary buildsStatistic = new BuildStatisticsSummary(buildId);
                 buildsStatistic.isValid = buildIdsWithConditions.get(buildId);
-
-                buildsStatistic.initialize(teamcity);
+                buildsStatistic.initialize(compactor, ignited);
 
                 return buildsStatistic;
-
             }, teamcity.getExecutor());
 
             buildStaticsFutures.add(buildFuture);
         }
 
-        buildStaticsFutures.forEach(new Consumer<Future<BuildStatisticsSummary>>() {
+        buildStaticsFutures.forEach(new Consumer <Future<BuildStatisticsSummary>>() {
             @Override public void accept(Future<BuildStatisticsSummary> v) {
                 try {
                     BuildStatisticsSummary buildsStatistic = v.get();
@@ -191,7 +190,7 @@ private void initStatistics(IAnalyticsEnabledTeamcity teamcity, Map<Integer, Boo
     }
 
     /** */
-    private void initFailedTests(IAnalyticsEnabledTeamcity teamcity, List<Integer> buildIds) {
+    private void initFailedTests(ITeamcity teamcity, List<Integer> buildIds) {
         List<Future<Void>> buildProcessorFutures = new ArrayList<>();
 
         for (int buildId : buildIds) {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java
index e1300c3f..67742fa2 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java
@@ -19,10 +19,11 @@
 
 import com.google.common.collect.BiMap;
 import java.text.ParseException;
+import java.util.Date;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import com.google.inject.Injector;
-import org.apache.ignite.ci.tcbot.condition.BuildCondition;
+import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildCondition;
 import org.apache.ignite.ci.tcbot.chain.BuildChainProcessor;
 import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
 import org.apache.ignite.ci.ITcHelper;
@@ -34,8 +35,6 @@
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.tcmodel.result.tests.TestRef;
-import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
-import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.model.current.BuildStatisticsSummary;
@@ -68,7 +67,6 @@
 public class GetBuildTestFailures {
     public static final String BUILD = "build";
     public static final String TEST_FAILURES_SUMMARY_CACHE_NAME = BUILD + "TestFailuresSummary";
-    public static final String BUILDS_STATISTICS_SUMMARY_CACHE_NAME = BUILD + "sStatisticsSummary";
     @Context
     private ServletContext ctx;
 
@@ -262,7 +260,12 @@ public BuildsHistory getBuildsHistory(
 
         BuildsHistory buildsHist = builder.build();
 
-        buildsHist.initialize(ICredentialsProv.get(req), ctx);
+        final ICredentialsProv prov = ICredentialsProv.get(req);
+
+        if (!prov.hasAccess(srvId))
+            throw ServiceUnauthorizedException.noCreds(srvId);
+
+        buildsHist.initialize(prov, ctx);
 
         return buildsHist;
     }
diff --git a/ignite-tc-helper-web/src/main/webapp/comparison.html b/ignite-tc-helper-web/src/main/webapp/comparison.html
index 1d4c13ce..82cf0968 100644
--- a/ignite-tc-helper-web/src/main/webapp/comparison.html
+++ b/ignite-tc-helper-web/src/main/webapp/comparison.html
@@ -34,7 +34,7 @@
         <td style="text-align: center;" id="info2"></td>
     </tr>
     <tr><td class="field">DURATION</td>
-        <td class="icon"><img id="clickGraphDuration" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphDuration" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="Duration1" data-allow-highlight="true"></td>
         <td class="mmm data 2" id="Duration2" data-allow-highlight="true"></td>
     </tr>
@@ -45,7 +45,7 @@
     </tr><tr></tr>
     <tr><td class="section">TESTS</td><td></td><td class="mmm title 1"></td><td class="mmm title 2"></td></tr>
     <tr><td class="field">COUNT</td>
-        <td class="icon"><img id="clickGraphCount" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphCount" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="Count1" data-allow-highlight="false"></td>
         <td class="mmm data 2" id="Count2" data-allow-highlight="false"></td>
     </tr>
@@ -55,7 +55,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphCount2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">PASSED</td>
-        <td class="icon"><img id="clickGraphPassed" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphPassed" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="Passed1" data-allow-highlight="false"></td>
         <td class="mmm data 2" id="Passed2" data-allow-highlight="false"></td>
     </tr>
@@ -65,7 +65,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphPassed2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">FAILED</td>
-        <td class="icon"><img id="clickGraphFailed" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphFailed" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="Failed1" data-allow-highlight="true"></td>
         <td class="mmm data 2" id="Failed2" data-allow-highlight="true"></td>
     </tr>
@@ -75,7 +75,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphFailed2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">IGNORED</td>
-        <td class="icon"><img id="clickGraphIgnored" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphIgnored" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="Ignored1" data-allow-highlight="false"></td>
         <td class="mmm data 2" id="Ignored2" data-allow-highlight="false"></td>
     </tr>
@@ -85,7 +85,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphIgnored2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">MUTED</td>
-        <td class="icon"><img id="clickGraphMuted" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphMuted" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="Muted1" data-allow-highlight="false"></td>
         <td class="mmm data 2" id="Muted2" data-allow-highlight="false"></td></tr>
     <tr id="showGraphMuted" style="display: none;"><td></td>
@@ -96,7 +96,7 @@
     <tr><td class="section">PROBLEMS</td><td></td><td class="mmm title 1"></td><td class="mmm title 2"></td></tr>
     <tr style="display: none;"><td></td><td></td><td></td></tr>
     <tr><td class="field">TOTAL</td>
-        <td class="icon"><img id="clickGraphTT" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphTT" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="TT1" data-allow-highlight="true"></td>
         <td class="mmm data 2" id="TT2" data-allow-highlight="true"></td></tr>
     <tr id="showGraphTT" style="display: none;"><td></td>
@@ -105,7 +105,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphTT2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">EXECUTION TIMEOUT</td>
-        <td class="icon"><img id="clickGraphET" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphET" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="ET1" data-allow-highlight="true"></td>
         <td class="mmm data 2" id="ET2" data-allow-highlight="true"></td>
     </tr>
@@ -115,7 +115,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphET2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">JVM CRASH</td>
-        <td class="icon"><img id="clickGraphJC" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphJC" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="JC1" data-allow-highlight="true"></td>
         <td class="mmm data 2" id="JC2" data-allow-highlight="true"></td>
     </tr>
@@ -125,7 +125,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphJC2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">OOME</td>
-        <td class="icon"><img id="clickGraphOO" src='/img/browser.png'></td>
+        <td class="icon"></td>
         <td class="mmm data 1" id="OO1" data-allow-highlight="true"></td>
         <td class="mmm data 2" id="OO2" data-allow-highlight="true"></td>
     </tr>
@@ -135,7 +135,7 @@
         <td style="text-align: center;"><svg class="graph 2" id="graphOO2" width="500" height="200"></svg></td>
     </tr>
     <tr><td class="field">EXIT CODE</td>
-        <td class="icon"><img id="clickGraphEC" src='/img/browser.png'></td>
+        <td class="icon"><p class="tooltips"><img id="clickGraphEC" src='/img/browser.png'><span>show graph</span></p></td>
         <td class="mmm data 1" id="EC1" data-allow-highlight="true"></td>
         <td class="mmm data 2" id="EC2" data-allow-highlight="true"></td>
     </tr>
@@ -175,15 +175,10 @@
 
 <div id="version"></div>
 <script>
-    let oneWeekAgo = new Date(),
-        twoWeekAgo = new Date(),
-        invalidInclude = false,
+    let invalidInclude = false,
         markBuildId = 0,
         testsTrigger = false;
 
-    oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
-    twoWeekAgo.setDate(twoWeekAgo.getDate() - 14);
-
     function getDateFewWeeksAgo(numberOfWeeksAgo) {
         let date = new Date();
 
@@ -196,8 +191,8 @@
     /** Structure for storing tests by suites parsed response for every date interval. */
     let mergedTestsResults = {1 : {}, 2 : {} };
 
-    let dateIntervals = {1: {start: moment(oneWeekAgo), end: moment()},
-        2: {start: moment(twoWeekAgo), end: moment(oneWeekAgo)}};
+    let dateIntervals = {1: {start: moment(getDateFewWeeksAgo(1)), end: moment()},
+        2: {start: moment(getDateFewWeeksAgo(2)), end: moment(getDateFewWeeksAgo(1))}};
 
     function showTooltip(message) {
         $("#tooltipText").html(message);
@@ -533,8 +528,11 @@
 
         compareAndHighlight(stat);
 
-        function time(ms){
-            return moment(ms * 1000).utcOffset(0).format("H:mm");
+        function time(s) {
+            let h = parseInt(s / 3600),
+                m = parseInt((s % 3600) / 60);
+
+            return h + ":" + ((m < 10) ? "0" : "") + m;
         }
     }
 
@@ -555,7 +553,7 @@
 
         mergedTestsResults[num] = {};
 
-        let url = 'rest/build/history?sinceDate=' + sinceDate.format("DDMMYYYY") +
+        let url = 'rest/build/history?server=apache&buildType=IgniteTests24Java8_RunAll&sinceDate=' + sinceDate.format("DDMMYYYY") +
             '000001&untilDate=' + untilDate.format("DDMMYYYY") + '235959';
 
         if (!testsTrigger)
@@ -596,7 +594,7 @@
         let anotherNum = (stat.num === 1) ? 2 : 1,
             thisElement = $('#' + stat.name + stat.num),
             anotherElement =  $('#' + stat.name + anotherNum),
-            thisMedian = stat.median;
+            thisMedian = stat.median - ((stat.name === duration) ? stat.median % 60 : 0);
 
         if (thisElement.data('allowHighlight').toString() === "true") {
             let anotherMedian = parseMedian(anotherElement.text());
@@ -613,8 +611,8 @@
     }
 
     $(document).ready(function() {
-        loadData(1, moment(oneWeekAgo), moment(), testsTrigger);
-        loadData(2, moment(twoWeekAgo), moment(oneWeekAgo), testsTrigger);
+        loadData(1, moment(getDateFewWeeksAgo(1)), moment(), testsTrigger);
+        loadData(2, moment(getDateFewWeeksAgo(2)), moment(getDateFewWeeksAgo(1)), testsTrigger);
 
         $.ajax({ url: "rest/branches/version",  success: showVersionInfo, error: showErrInLoadStatus });
     });
diff --git a/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css b/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css
index 309328c6..1c20db8f 100644
--- a/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css
+++ b/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css
@@ -455,3 +455,60 @@ div.tooltip {
  font-size: 48px;
  color: #E60000;
 }
+
+.far.fa-chart-bar, .fas.fa-chart-area, .fas.fa-chart-pie, .fas.fa-angle-double-down {
+ font-size: 20px;
+ color: #12AD5E;
+}
+
+.fas.fa-chart-pie:hover {
+ transform: scale(1.2);
+
+}
+
+.fas.fa-angle-right {
+ font-size: 18px;
+ transform: scale(0.8) translateX(0.3em) translateY(2px);
+ transition: transform .25s;
+ display: inline-block;
+}
+
+.testClass:hover > i {
+ transform: scale(1.2) translateX(0.8em) translateY(1px);
+}
+
+p.tooltips {
+ position: relative;
+ display: inline;
+}
+p.tooltips span {
+ position: absolute;
+ width:100px;
+ color: #FFFFFF;
+ background: #000000;
+ height: 30px;
+ line-height: 30px;
+ text-align: center;
+ visibility: hidden;
+ border-radius: 5px;
+}
+p.tooltips span:after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 100%;
+ margin-top: -8px;
+ width: 0; height: 0;
+ border-right: 8px solid #000000;
+ border-top: 8px solid transparent;
+ border-bottom: 8px solid transparent;
+}
+p:hover.tooltips span {
+ visibility: visible;
+ opacity: 0.8;
+ left: 100%;
+ top: 50%;
+ margin-top: -15px;
+ margin-left: 15px;
+ z-index: 999;
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[hidden email]


With regards,
Apache Git Services