Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 4a77ce73

Přidáno uživatelem Ondřej Váně před asi 4 roky(ů)

Long or non existant feedback loops

Zobrazit rozdíly:

src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/detecting/detectors/LongOrNonExistentFeedbackLoopsDetectorImpl.java
9 9
import org.slf4j.Logger;
10 10
import org.slf4j.LoggerFactory;
11 11

  
12
import java.util.HashMap;
12
import java.math.BigDecimal;
13
import java.sql.Date;
14
import java.util.ArrayList;
13 15
import java.util.List;
14 16
import java.util.Map;
15 17

  
......
31 33
    /**
32 34
     * Settings
33 35
     */
34
    private final float DIVISION_LONG_OR_NON_FEEDBACK_ITERATIONS = (float) 1/3;
36
    private final float DIVISION_LONG_OR_NON_FEEDBACK_ITERATIONS = (float) 1 / 3;
35 37

  
36 38
    /* Settings */
37 39
    private final int MINIMUM_NUMBER_OF_WIKI_PAGES = 1;
......
49 51

  
50 52
    /**
51 53
     * Postup detekce:
52
     *  A)
53
     *      1) najít všechny aktivity, které by mohli indikovat schůzku se zákazníkem
54
     *      2) udělat join na iterace
55
     *      3) v ideálním případě by měla mít každá iterace jeden nalezený issue
56
     *      4) pokud nebude nalezen žádný iisue, tak to znamená že tým nezaznamenává schůzky do úkolů => je nutné ještě prověřit wiki stránky
57
     *      5) zkusit nalézt všechny wiki stránky, které by mohly souviset s demem
58
     *      6) dle datumu úpravy udělat join na iterace (jedna wiki více schůzek)
59
     *      7) v ideálním případě by měla mít opět každá iterace jeden záznam
60
     *      8) dle prahových hodnot vyhodnotit výsledky
54
     * A)
55
     * 1) najít všechny aktivity, které by mohli představovat zákaznické demo (název bude obsahovat substring)
56
     * 2) zjistit průměrnou délku iterací
57
     * 3) zjistit počet iterací
58
     * 4) nejprve porovnat s počtem iterací => iterace a nalezené aktivity by se měly ideálně rovnat (mohou být menší i větší ale né o moc menší)
59
     * 5) u každých dvou po sobě jdoucích aktivitách udělat rozdíl datumů a porovnat s průměrnou délkou iterace => rozdíl by se neměl moc lišit od průěrné délky iterace
60
     * 6) pokud u bodu 4) dojde k detekci máleho počtu nalezených aktivit (tým nedělá aktivity na schůzky a může zaznamenávat pouze do wiki)
61
     * 7) najít všechny wiki stránky a udělat join kdy se měnily (může být použita jedná stránka pro více schůzek) s příslušným názvem
62
     * 8) udělat group podle dne
61 63
     *
62 64
     * @param project            analyzovaný project
63 65
     * @param databaseConnection databázové připojení
......
66 68
     */
67 69
    @Override
68 70
    public QueryResultItem analyze(Project project, DatabaseConnection databaseConnection, List<String> queries) {
69
        Long totalNumberIterations = 0L;
70
        Map<String, Integer> iterationsResults = new HashMap<>();
71
        long totalNumberIterations = 0;
72
        int averageIterationLength = 0;
73
        int numberOfIterationsWitchContainsAtLeastOneActivityForFeedback = 0;
74
        List<Date> feedbackActivityEndDates = new ArrayList<>();
75
        Date projectStartDate = null;
76
        Date projectEndDate = null;
71 77

  
72 78
        List<List<Map<String, Object>>> resultSets = databaseConnection.executeQueriesWithMultipleResults(project, queries);
73 79
        for (int i = 0; i < resultSets.size(); i++) {
74 80
            List<Map<String, Object>> rs = resultSets.get(i);
75 81

  
76
            if (i == 0) {
77
                totalNumberIterations = (Long) rs.get(0).get("numberOfIterations");
78
            }
82
            switch (i) {
83
                case 0:
84
                    totalNumberIterations = (long) rs.get(0).get("numberOfIterations");
85
                    break;
86
                case 1:
87
                    averageIterationLength = ((BigDecimal) rs.get(0).get("averageIterationLength")).intValue();
88
                    break;
89
                case 2:
90
                    if (rs.size() != 0) {
91
                        numberOfIterationsWitchContainsAtLeastOneActivityForFeedback = ((Long) rs.get(0).get("totalCountOfIterationsWithFeedbackActivity")).intValue();
92
                    }
93
                    break;
94
                case 3:
95
                    Date activityEndDate;
96
                    for (Map<String, Object> map : rs) {
97
                        activityEndDate = (Date) map.get("endDate");
98
                        feedbackActivityEndDates.add(activityEndDate);
99
                    }
100
                    break;
101
                case 4:
102
                    projectStartDate = (Date) rs.get(0).get("startDate");
103
                    break;
104
                case 5:
105
                    projectEndDate = (Date) rs.get(0).get("endDate");
106
                    break;
107
                default:
79 108

  
80
            if (i == 1) {
81
                String iterationName;
82
                for (Map<String, Object> map : rs) {
83
                    iterationName = (String) map.get("iterationName");
84
                    iterationsResults.put(iterationName, 1);
85
                }
86 109
            }
87 110
        }
88
        int minFeedbackLimit =  totalNumberIterations.intValue() - Math.round(totalNumberIterations * DIVISION_LONG_OR_NON_FEEDBACK_ITERATIONS);
89 111

  
90
        List<ResultDetail> resultDetails = Utils.createResultDetailsList(
91
                new ResultDetail("Project id", project.getId().toString()));
112
        double halfNumberOfIterations = totalNumberIterations / 2.0;
113

  
114
        // pokud je počet iterací, které obsahují alespoň jednu aktivitu s feedbackem, tak je to ideální případ
115
        if (totalNumberIterations <= numberOfIterationsWitchContainsAtLeastOneActivityForFeedback) {
116
            List<ResultDetail> resultDetails = Utils.createResultDetailsList(
117
                    new ResultDetail("Number of iterations", Long.toString(totalNumberIterations)),
118
                    new ResultDetail("Number of iterations with feedback loops", Integer.toString(numberOfIterationsWitchContainsAtLeastOneActivityForFeedback)),
119
                    new ResultDetail("Conclusion", "In each iteration is at least one activity that represents feedback loop"));
120

  
121

  
122
            return new QueryResultItem(this.antiPattern, false, resultDetails);
123

  
124
            // pokud alespoň v polovině iteracích došlo ke kontaktu se zákazníkem => zkontrolovat rozestupy
125
        } else if (feedbackActivityEndDates.size() > halfNumberOfIterations) {
126

  
127
            Date firstDate = projectStartDate;
128
            Date secondDate = null;
129

  
130
            for (Date feedbackActivityDate : feedbackActivityEndDates) {
131
                secondDate = feedbackActivityDate;
132
                long daysBetween = Utils.daysBetween(firstDate, secondDate);
133
                firstDate = secondDate;
92 134

  
93
        if ((totalNumberIterations.intValue() != iterationsResults.size())) {
94
            if (totalNumberIterations - iterationsResults.size() > minFeedbackLimit) {
95
                return new QueryResultItem(this.antiPattern, true , resultDetails);
96
            } else {
97
                return new QueryResultItem(this.antiPattern, false , resultDetails);
135
                if (daysBetween >= 2 * averageIterationLength) {
136
                    List<ResultDetail> resultDetails = Utils.createResultDetailsList(
137
                            new ResultDetail("Days between", Long.toString(daysBetween)),
138
                            new ResultDetail("Average iteration length", Integer.toString(averageIterationLength)),
139
                            new ResultDetail("Conclusion", "Customer feedback loop is too long"));
98 140

  
141

  
142
                    return new QueryResultItem(this.antiPattern, true, resultDetails);
143
                }
99 144
            }
145

  
146
            // rozestupy feedbacků jsou ok
147
            List<ResultDetail> resultDetails = Utils.createResultDetailsList(
148
                    new ResultDetail("Average iteration length", Integer.toString(averageIterationLength)),
149
                    new ResultDetail("Conclusion", "Customer feedback has been detected and there is not too much gap between them"));
150

  
151

  
152
            return new QueryResultItem(this.antiPattern, false, resultDetails);
153

  
154
            // bylo nalezeno příliš málo aktivit => zkusit se podívat ve wiki stránkách
100 155
        } else {
101
            return new QueryResultItem(this.antiPattern, false , resultDetails);
156
            // TODO udělat analýzu WIKI stránek
102 157
        }
158

  
159
        List<ResultDetail> resultDetails = Utils.createResultDetailsList(
160
                new ResultDetail("Project id", project.getId().toString()));
161

  
162
        return new QueryResultItem(this.antiPattern, true, resultDetails);
103 163
    }
104 164
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/utils/Utils.java
11 11
import java.time.temporal.ChronoUnit;
12 12
import java.util.ArrayList;
13 13
import java.util.Arrays;
14
import java.util.LinkedList;
15 14
import java.util.List;
16 15

  
17 16
public class Utils {
src/main/resources/queries/long_or_non_existent_feedback_loops.sql
20 20
set @projectId = ?;
21 21
/* Number of iterations for given project */
22 22
select COUNT(id) as 'numberOfIterations' from iteration where superProjectId = @projectId;
23
/* Select all iteration with detected retrospective activities */
24
select  iterationName as 'iterationName', count(name) as 'numberOfIssues' from workunitview where projectId = @projectId and (name like "%schůz%zákazník%" OR name like "%předvedení%zákazník%" OR name LIKE "%zákazn%demo%" OR name like "%schůz%zadavat%" OR name like "%inform%schůz%") group by iterationName;
25
/* Look up for wiki pages */
26

  
23
/* Average iteration length */
24
select avg(abs(dateDiff(iteration.endDate, iteration.startDate))) as 'averageIterationLength' from iteration where superProjectId = @projectId;
25
/* Select number of iterations which contains at least one feedback activity */
26
select count(*) over () as 'totalCountOfIterationsWithFeedbackActivity' from workunitview as wuv where wuv.projectId = @projectId and (wuv.name like "%schůz%zákazník%" OR wuv.name like "%předvedení%zákazník%" OR wuv.name LIKE "%zákazn%demo%" OR wuv.name like "%schůz%zadavat%" OR wuv.name like "%inform%schůz%") group by wuv.iterationName order by wuv.activityEndDate;
27
/* Select all activities for feedback loop with last modified date as end date */
28
select wuv.id, wuv.iterationName, wuv.name, cast(max(fieldchangeview.created) as date) as 'endDate' from workunitview as wuv inner join fieldchangeview on wuv.id = fieldchangeview.itemId where wuv.projectId = @projectId and (wuv.name like "%schůz%zákazník%" OR wuv.name like "%předvedení%zákazník%" OR wuv.name LIKE "%zákazn%demo%" OR wuv.name like "%schůz%zadavat%" OR wuv.name like "%inform%schůz%" OR wuv.name like "%zákazn%" OR wuv.name like "%zadavatel%") GROUP by id order by fieldchangeview.created;
29
/* Get project start date */
30
select startDate as 'projectStartDate' from iteration where superProjectId = @projectId order by startDate limit 1;
31
/* Get project end date */
32
select endDate as 'projectEndDate' from iteration where superProjectId = @projectId order by endDate desc limit 1;
33
/* Select all wiki pages that can be notes about feedback loop */

Také k dispozici: Unified diff