Ignore:
Timestamp:
02/28/14 15:09:12 (10 years ago)
Author:
pharms
Message:
  • added possibility to calculate metrics for tasks and added the first metrics
Location:
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInfo.java

    r1287 r1423  
    1515package de.ugoe.cs.autoquest.tasktrees.treeimpl; 
    1616 
     17import java.util.ArrayList; 
     18import java.util.HashMap; 
     19 
    1720import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
    1821import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo; 
     22import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric; 
    1923 
    2024/** 
     
    4145     */ 
    4246    private ITask task; 
    43  
    44     /** 
    45      * <p> 
    46      * the number of occurrences of this task 
    47      * </p> 
    48      */ 
    49     private int count; 
     47     
     48    /** 
     49     * <p> 
     50     * all available measures for the task 
     51     * </p> 
     52     */ 
     53    private ArrayList<Measure> measures = new ArrayList<Measure>(); 
    5054 
    5155    /** 
     
    6973 
    7074    /* (non-Javadoc) 
    71      * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getCount() 
    72      */ 
    73     @Override 
    74     public int getCount() { 
    75         return count; 
     75     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasures() 
     76     */ 
     77    @Override 
     78    public IMeasure[] getMeasures() { 
     79        measures.trimToSize(); 
     80        return measures.toArray(new IMeasure[measures.size()]); 
     81    } 
     82 
     83    /* (non-Javadoc) 
     84     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java.lang.String) 
     85     */ 
     86    @Override 
     87    public int getMeasureValue(TaskMetric metric) { 
     88        Measure measure = getMeasure(metric); 
     89         
     90        if (measure == null) { 
     91            throw new IllegalArgumentException("unknown metric " + metric); 
     92        } 
     93         
     94        return measure.getValue(); 
     95    } 
     96 
     97    /* (non-Javadoc) 
     98     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java.lang.String, de.ugoe.cs.autoquest.tasktrees.treeifc.ITask) 
     99     */ 
     100    @Override 
     101    public int getMeasureValue(TaskMetric metric, ITask context) { 
     102        Measure measure = getMeasure(metric); 
     103         
     104        if (measure == null) { 
     105            throw new IllegalArgumentException("unknown metric " + metric); 
     106        } 
     107         
     108        return measure.getValue(context); 
    76109    } 
    77110 
     
    86119    /** 
    87120     * <p> 
    88      * used to increase the counter of occurrences of this task by one 
    89      * </p> 
    90      */ 
    91     void increaseCount() { 
    92         count++; 
    93     } 
     121     * must be called to indicate that a new new measures for the provided metric are about to 
     122     * be calculated and added. 
     123     * </p> 
     124     * 
     125     * @param metric the metric for which measures are about to be provided 
     126     */ 
     127    void addMeasure(TaskMetric metric) { 
     128        Measure measure = getMeasure(metric); 
     129         
     130        if (measure != null) { 
     131            throw new IllegalArgumentException("measure for metric " + metric + " already exists."); 
     132        } 
     133         
     134        measure = new Measure(metric); 
     135        measures.add(measure); 
     136    } 
     137 
     138    /** 
     139     * <p> 
     140     * sets a specific value for a measure of a specific metric in the provided context of the task 
     141     * </p> 
     142     *  
     143     * @param metric  the metric to which the value belongs 
     144     * @param context the context of the task in which the measure was recorded 
     145     * @param value   the value of the measure 
     146     */ 
     147    void setCount(TaskMetric metric, ITask context, int value) { 
     148        Measure measure = getMeasure(metric); 
     149         
     150        if (measure == null) { 
     151            throw new IllegalArgumentException("unknown metric. Please create a measure " + 
     152                                               "for the metric before using it."); 
     153        } 
     154         
     155        measure.set(context, value); 
     156    } 
     157 
     158    /** 
     159     * <p> 
     160     * increases a specific value for a measure of a specific metric in the provided context of the 
     161     * task 
     162     * </p> 
     163     *  
     164     * @param metric    the metric to which the value belongs 
     165     * @param context   the context of the task in which the measure was recorded 
     166     * @param increment the increment to be added to the value of the measure 
     167     */ 
     168    void increaseCount(TaskMetric metric, ITask context, int increment) { 
     169        Measure measure = getMeasure(metric); 
     170         
     171        if (measure == null) { 
     172            throw new IllegalArgumentException("unknown metric. Please create a measure " + 
     173                                               "for the metric before using it."); 
     174        } 
     175         
     176        measure.increase(context, increment); 
     177    } 
     178 
     179    /** 
     180     * <p> 
     181     * convenience method to internally determine the measure for a specific metric 
     182     * </p> 
     183     */ 
     184    private Measure getMeasure(TaskMetric metric) { 
     185        for (Measure candidate : measures) { 
     186            if (candidate.getMetric().equals(metric)) { 
     187                return candidate; 
     188            } 
     189        } 
     190         
     191        return null; 
     192    } 
     193 
     194    /** 
     195     * <p> 
     196     * implementation for the measure interface of the task info interface. Does nothing fancy 
     197     * except implementing the interface 
     198     * </p> 
     199     *  
     200     * @author Patrick Harms 
     201     */ 
     202    private static class Measure implements IMeasure { 
     203 
     204        /** 
     205         * <p> 
     206         * the metric to which the measure belongs 
     207         * </p> 
     208         */ 
     209        private TaskMetric metric; 
     210         
     211        /** 
     212         * <p> 
     213         * the observed values for the difference contexts of the task 
     214         * </p> 
     215         */ 
     216        private HashMap<ITask, Integer> values; 
     217         
     218        /** 
     219         * <p> 
     220         * the context free value of the measure independent of the task context 
     221         * </p> 
     222         */ 
     223        private int contextFreeValue = 0; 
     224         
     225        /** 
     226         * <p> 
     227         * initializes the measure with a specific metric 
     228         * </p> 
     229         */ 
     230        private Measure(TaskMetric metric) { 
     231            super(); 
     232            this.metric = metric; 
     233        } 
     234 
     235        /* (non-Javadoc) 
     236         * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getMetric() 
     237         */ 
     238        @Override 
     239        public TaskMetric getMetric() { 
     240            return metric; 
     241        } 
     242 
     243        /* (non-Javadoc) 
     244         * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue() 
     245         */ 
     246        @Override 
     247        public int getValue() { 
     248            return contextFreeValue; 
     249        } 
     250 
     251        /* (non-Javadoc) 
     252         * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue(de.ugoe.cs.autoquest.tasktrees.treeifc.ITask) 
     253         */ 
     254        @Override 
     255        public int getValue(ITask context) { 
     256            if ((context != null) && (values != null)) { 
     257                Integer currentValue = values.get(context); 
     258                 
     259                if (currentValue != null) { 
     260                    return currentValue; 
     261                } 
     262            } 
     263             
     264            return Integer.MIN_VALUE; 
     265        } 
     266 
     267        /** 
     268         * <p> 
     269         * sets the value of the measure context free as well as specific to the provided context 
     270         * </p> 
     271         */ 
     272        private void set(ITask context, int value) { 
     273            contextFreeValue = value; 
     274             
     275            if (context != null) { 
     276                if (values == null) { 
     277                    values = new HashMap<ITask, Integer>(); 
     278                } 
     279                 
     280                values.put(context, value); 
     281            } 
     282        } 
     283 
     284        /** 
     285         * <p> 
     286         * increases the value of the measure context free as well as specific to the provided 
     287         * context according to the provided increment 
     288         * </p> 
     289         */ 
     290        private void increase(ITask context, int increment) { 
     291            contextFreeValue += increment; 
     292             
     293            if (context != null) { 
     294                if (values == null) { 
     295                    values = new HashMap<ITask, Integer>(); 
     296                } 
     297                 
     298                Integer currentValue = values.get(context); 
     299                 
     300                if (currentValue == null) { 
     301                    currentValue = 0; 
     302                } 
     303                 
     304                values.put(context, currentValue + increment); 
     305            } 
     306        } 
     307 
     308    } 
     309 
    94310} 
  • trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskModel.java

    r1287 r1423  
    2121import java.util.Map; 
    2222 
     23import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
     24import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 
     25import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration; 
     26import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance; 
     27import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship; 
     28import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional; 
     29import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance; 
     30import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection; 
     31import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance; 
     32import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship; 
    2333import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; 
    2434import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 
     
    2737import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo; 
    2838import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 
     39import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric; 
    2940 
    3041/** 
    3142 * <p> 
    3243 * this is the default implementation of the interface {@link ITaskModel}. It 
    33  * does not do anything fancy except implementing the interface. 
     44 * does not do anything fancy except implementing the interface. It also calculates on 
     45 * initialisations the measures for diverse metrics of the task belonging to the model 
    3446 * </p> 
    3547 *  
     
    4456     */ 
    4557    private static final long serialVersionUID = 1L; 
     58     
     59    /** 
     60     * <p> 
     61     * all metrics calculated by this type of task model 
     62     * </p> 
     63     */ 
     64    private static final TaskMetric[] taskMetrics = new TaskMetric[] 
     65        { TaskMetric.COUNT, 
     66          TaskMetric.DEPTH, 
     67          TaskMetric.EVENT_COVERAGE, 
     68          TaskMetric.EVENT_COVERAGE_RATIO }; 
    4669 
    4770    /** 
     
    5477    /** 
    5578     * <p> 
    56      * the tasks contained in the user session belonging to the model as well as statistical infos 
    57      * about them 
    58      * </p> 
    59      */ 
    60     private Map<ITask, TaskInfo> taskMap = new HashMap<ITask, TaskInfo>(); 
    61  
     79     * index for effectively accessing the model and calculating statistics about it 
     80     * </p> 
     81     */ 
     82    private transient TaskModelIndex index = null; 
     83     
    6284    /** 
    6385     * <p> 
     
    7395         
    7496        this.userSessions = userSessions; 
    75          
    76         for (IUserSession session : this.userSessions) { 
    77             for (ITaskInstance taskInstance : session) { 
    78                 addTasksToMap(taskInstance); 
    79             } 
    80         } 
    8197    } 
    8298 
     
    87103    @Override 
    88104    public List<IUserSession> getUserSessions() { 
     105        ensureInitialized(); 
    89106        return Collections.unmodifiableList(userSessions); 
    90107    } 
     
    96113    @Override 
    97114    public Collection<ITask> getTasks() { 
    98         return Collections.unmodifiableCollection(taskMap.keySet()); 
     115        ensureInitialized(); 
     116        return Collections.unmodifiableCollection(index.taskMap.keySet()); 
    99117    } 
    100118 
     
    105123    @Override 
    106124    public ITaskInfo getTaskInfo(ITask task) { 
    107         return taskMap.get(task); 
    108     } 
     125        ensureInitialized(); 
     126        return index.taskMap.get(task); 
     127    } 
     128 
     129    /* (non-Javadoc) 
     130     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getAllMetrics() 
     131     */ 
     132    @Override 
     133    public TaskMetric[] getAllMetrics() { 
     134        return taskMetrics; 
     135    } 
     136 
    109137 
    110138    /* (non-Javadoc) 
     
    116144    } 
    117145 
    118  
    119     /** 
    120      * <p> 
    121      * internal convenience method to recursively add the tasks of a task instance and its 
    122      * children to the task model 
    123      * </p> 
    124      * 
    125      * @param taskInstance the task instance of which the tasks shall be added 
    126      */ 
    127     private void addTasksToMap(ITaskInstance taskInstance) { 
    128         addTaskToMap(taskInstance.getTask()); 
    129          
    130         if (taskInstance instanceof ITaskInstanceList) { 
    131             for (ITaskInstance child : (ITaskInstanceList) taskInstance) { 
    132                 addTasksToMap(child); 
    133             } 
    134         } 
    135     } 
    136  
    137      
    138     /** 
    139      * <p> 
    140      * internal convenience method to build the task model during initialization 
    141      * </p> 
    142      */ 
    143     private void addTaskToMap(ITask task) { 
    144         TaskInfo taskInfo = taskMap.get(task); 
    145  
    146         if (taskInfo == null) { 
    147             taskInfo = new TaskInfo(task); 
    148             taskMap.put(task, taskInfo); 
    149         } 
    150  
    151         taskInfo.increaseCount(); 
    152  
    153         /*if (task instanceof IStructuringTemporalRelationship) { 
    154             for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) { 
    155                 addTaskToMap(child); 
    156             } 
    157         } 
    158         else if (task instanceof IMarkingTemporalRelationship) { 
    159             addTaskToMap(((IMarkingTemporalRelationship) task).getMarkedTask()); 
     146    /** 
     147     * <p> 
     148     * internal convenience method that initializes the internal index and calculates all measures 
     149     * for metrics available for the tasks 
     150     * </p> 
     151     */ 
     152    private synchronized void ensureInitialized() { 
     153        if (index == null) { 
     154            index = new TaskModelIndex(); 
     155             
     156            for (IUserSession session : this.userSessions) { 
     157                for (ITaskInstance taskInstance : session) { 
     158                    index.handleTaskInstance(taskInstance, null); 
     159                } 
     160            } 
     161             
     162            // count all events covered 
     163            int allEventsCovered = 0; 
     164            Collection<ITask> tasks = getTasks(); 
     165            for (ITask task : tasks) { 
     166                if (task instanceof IEventTask) { 
     167                    allEventsCovered += task.getInstances().size(); 
     168                } 
     169            } 
     170             
     171            // add some further measures 
     172            for (ITask task : tasks) { 
     173                TaskInfo info = index.taskMap.get(task); 
     174                info.addMeasure(TaskMetric.EVENT_COVERAGE_RATIO); 
     175                 
     176                int coveredEvents = info.getMeasureValue(TaskMetric.EVENT_COVERAGE); 
     177                 
     178                if (allEventsCovered > 0) { 
     179                    info.setCount(TaskMetric.EVENT_COVERAGE_RATIO, null, 
     180                                  ((coveredEvents * 1000) / allEventsCovered)); 
     181                } 
     182            } 
     183             
     184            //index.dumpToCSV(System.out); 
     185            /*try { 
     186                OutputStream stream = new FileOutputStream(new File("tasks.csv")); 
     187                index.dumpToCSV(new PrintStream(stream)); 
     188                stream.close(); 
     189            } 
     190            catch (FileNotFoundException e) { 
     191                e.printStackTrace(); 
     192            }*/ 
     193        } 
     194         
     195    } 
     196 
     197    /** 
     198     * <p> 
     199     * the index of task infos used internally. The index is created once and while that filled 
     200     * with task infos for each observed task containing all measures for metrics belonging 
     201     * to the tasks.  
     202     * </p> 
     203     *  
     204     * @author Patrick Harms 
     205     */ 
     206    private static class TaskModelIndex { 
     207 
     208        /** 
     209         * <p> 
     210         * the tasks contained in the user session belonging to the model as well as statistical 
     211         * infos about them 
     212         * </p> 
     213         */ 
     214        private Map<ITask, TaskInfo> taskMap = new HashMap<ITask, TaskInfo>(); 
     215 
     216        /** 
     217         * <p> 
     218         * called on initialization to fill the index with infos about the given task instance 
     219         * as well as to calculate the appropriate metrics 
     220         * </p> 
     221         */ 
     222        private int[] handleTaskInstance(ITaskInstance taskInstance, ITask context) { 
     223            int eventTaskInstancesCovered = 0; 
     224            int depth = 0; 
     225             
     226            if (taskInstance instanceof ITaskInstanceList) { 
     227                for (ITaskInstance child : (ITaskInstanceList) taskInstance) { 
     228                    int[] measures = handleTaskInstance(child, taskInstance.getTask()); 
     229                    eventTaskInstancesCovered += measures[0]; 
     230                    depth = Math.max(depth, measures[1]); 
     231                } 
     232                 
     233                if ((((ITaskInstanceList) taskInstance).size() == 0) && 
     234                    (taskInstance instanceof IIterationInstance)) 
     235                { 
     236                    // ensure also empty task infos for unselected variants 
     237                    ensureTaskInfo(((IIteration) taskInstance.getTask()).getMarkedTask(), context); 
     238                } 
     239            } 
     240            else if (taskInstance instanceof ISelectionInstance) { 
     241                ITaskInstance child = ((ISelectionInstance) taskInstance).getChild(); 
     242                int[] measures = handleTaskInstance(child, taskInstance.getTask()); 
     243                eventTaskInstancesCovered += measures[0]; 
     244                depth = Math.max(depth, measures[1]); 
     245                 
     246                // ensure also empty task infos for unselected variants 
     247                for (ITask otherChildTask : ((ISelection) taskInstance.getTask()).getChildren()) { 
     248                    ensureTaskInfo(otherChildTask, context); 
     249                } 
     250            } 
     251            else if (taskInstance instanceof IOptionalInstance) { 
     252                ITaskInstance child = ((IOptionalInstance) taskInstance).getChild(); 
     253                if (child != null) { 
     254                    int[] measures = handleTaskInstance(child, taskInstance.getTask()); 
     255                    eventTaskInstancesCovered += measures[0]; 
     256                    depth = Math.max(depth, measures[1]); 
     257                } 
     258                else { 
     259                    // ensure also empty task infos for unselected variants 
     260                    ensureTaskInfo(((IOptional) taskInstance.getTask()).getMarkedTask(), context); 
     261                } 
     262            } 
     263            else if (taskInstance instanceof IEventTaskInstance) { 
     264                eventTaskInstancesCovered = 1; 
     265            } 
     266             
     267            depth++; 
     268             
     269            ensureTaskInfo(taskInstance.getTask(), context, eventTaskInstancesCovered, depth); 
     270             
     271            return new int[] { eventTaskInstancesCovered, depth }; 
     272        } 
     273         
     274        /** 
     275         * <p> 
     276         * internal convenience method to build the task model during initialization 
     277         * </p> 
     278         */ 
     279        private void ensureTaskInfo(ITask task, ITask context) { 
     280            ensureTaskInfo(task, context, 0, 0); 
     281             
     282            if (task instanceof IStructuringTemporalRelationship) { 
     283                for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) { 
     284                    ensureTaskInfo(child, task); 
     285                } 
     286            } 
     287            else if (task instanceof IMarkingTemporalRelationship) { 
     288                ensureTaskInfo(((IMarkingTemporalRelationship) task).getMarkedTask(), task); 
     289            } 
     290         
     291        } 
     292         
     293        /** 
     294         * <p> 
     295         * internal convenience method to build the task model during initialization. Adds a new 
     296         * task info object to the map for the provided task and fills it with measures. If there 
     297         * are already some task infos for the task, the contained measures are updated according 
     298         * to the parameters. 
     299         * </p> 
     300         */ 
     301        private void ensureTaskInfo(ITask task, 
     302                                    ITask context, 
     303                                    int   eventTaskInstancesCovered, 
     304                                    int   depth) 
     305        { 
     306            TaskInfo taskInfo = taskMap.get(task); 
     307 
     308            if (taskInfo == null) { 
     309                taskInfo = new TaskInfo(task); 
     310                taskInfo.addMeasure(TaskMetric.COUNT); 
     311                taskInfo.addMeasure(TaskMetric.EVENT_COVERAGE); 
     312                taskInfo.addMeasure(TaskMetric.DEPTH); 
     313                taskMap.put(task, taskInfo); 
     314                 
     315                taskInfo.setCount(TaskMetric.DEPTH, null, getDepth(task)); 
     316            } 
     317 
     318            taskInfo.increaseCount(TaskMetric.COUNT, context, 1); 
     319            taskInfo.increaseCount(TaskMetric.EVENT_COVERAGE, context, eventTaskInstancesCovered); 
     320 
     321            taskInfo.setCount(TaskMetric.DEPTH, context, depth); 
     322        } 
     323 
     324        /** 
     325         * <p> 
     326         * internal convenience method to calculate the maximum depth of a task 
     327         * </p> 
     328         */ 
     329        private int getDepth(ITask task) { 
     330            if (task instanceof IMarkingTemporalRelationship) { 
     331                return getDepth(((IMarkingTemporalRelationship) task).getMarkedTask()) + 1; 
     332            } 
     333            else if (task instanceof IStructuringTemporalRelationship) { 
     334                int maxDepth = 0; 
     335                 
     336                for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) { 
     337                    maxDepth = Math.max(maxDepth, getDepth(child)); 
     338                } 
     339                 
     340                return maxDepth + 1; 
     341            } 
     342            else { 
     343                // event tasks 
     344                return 1; 
     345            } 
     346        } 
     347 
     348        /** 
     349         * 
     350         */ 
     351        /*private void dumpToCSV(PrintStream out) { 
     352            out.println("taskid;depth;count;eventcoverage;eventcoverageratio"); 
     353             
     354            for (Map.Entry<ITask, TaskInfo> entry : taskMap.entrySet()) { 
     355                out.print(entry.getKey().getId()); 
     356                out.print(';'); 
     357                out.print(entry.getValue().getMeasureValue(TaskMetric.DEPTH)); 
     358                out.print(';'); 
     359                out.print(entry.getValue().getMeasureValue(TaskMetric.COUNT)); 
     360                out.print(';'); 
     361                out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE)); 
     362                out.print(';'); 
     363                out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO)); 
     364                out.println(); 
     365            } 
    160366        }*/ 
    161     } 
     367 
     368    } 
     369 
    162370 
    163371} 
Note: See TracChangeset for help on using the changeset viewer.