source: trunk/autoquest-plugin-genericevents/src/main/java/de/ugoe/cs/autoquest/plugin/genericevents/commands/CMDexportSogouQTaskTrees.java @ 2153

Last change on this file since 2153 was 2153, checked in by pharms, 7 years ago
  • Property svn:mime-type set to text/plain
File size: 20.0 KB
Line 
1//   Copyright 2015 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.plugin.genericevents.commands;
16
17import java.io.File;
18import java.io.FileOutputStream;
19import java.io.IOException;
20import java.io.PrintStream;
21import java.util.ArrayList;
22import java.util.Collection;
23import java.util.LinkedList;
24import java.util.List;
25import java.util.ListIterator;
26
27import de.ugoe.cs.autoquest.CommandHelpers;
28import de.ugoe.cs.autoquest.eventcore.Event;
29import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
30import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskTraversingVisitor;
31import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
32import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
33import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
34import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
35import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
36import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
37import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
38import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
39import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
40import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
41import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
42import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric;
43import de.ugoe.cs.util.console.Command;
44import de.ugoe.cs.util.console.Console;
45import de.ugoe.cs.util.console.GlobalDataContainer;
46
47/**
48 * <p>
49 * TODO comment
50 * </p>
51 *
52 * @author Patrick Harms
53 */
54public class CMDexportSogouQTaskTrees implements Command {
55
56    /* (non-Javadoc)
57     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
58     */
59    @Override
60    public void run(List<Object> parameters) {
61        String taskTreeName = null;
62        String path = null;
63        String numberStr = null;
64        boolean withTimestamp = false;
65       
66        try {
67            for (int i = 0; i < parameters.size(); i++) {
68                String parameter = (String) parameters.get(i);
69                if (!parameter.startsWith("-")) {
70                    if (taskTreeName == null) {
71                        taskTreeName = parameter;
72                    }
73                    else if (path == null) {
74                        path = parameter;
75                    }
76                    else if (numberStr == null) {
77                        numberStr = parameter;
78                    }
79                    else {
80                        throw new IllegalArgumentException("unrecognized parameter: " + parameter);
81                    }
82                }
83                else {
84                    if ("-withTimestamp".equals(parameter)) {
85                        withTimestamp = true;
86                    }
87                    else {
88                        throw new IllegalArgumentException("unrecognized parameter: " + parameter);
89                    }
90                }
91            }
92        }
93        catch (IllegalArgumentException e) {
94            throw e;
95        }
96        catch (Exception e) {
97            throw new IllegalArgumentException("could not process parameters", e);
98        }
99       
100        if (path == null) {
101            throw new IllegalArgumentException("no path to directory provided");
102        }
103       
104        if (taskTreeName == null) {
105            throw new IllegalArgumentException("no task tree specified");
106        }
107       
108        if (numberStr == null) {
109            throw new IllegalArgumentException("no number of tasks to be exported provided");
110        }
111       
112        int tasksToExport;
113        try{
114            tasksToExport = Integer.parseInt(numberStr);
115        }
116        catch (Exception e) {
117            throw new IllegalArgumentException("invalid number of tasks to be exported: " +
118                                               numberStr, e);
119        }
120
121        File directory = new File(path);
122        if (!directory.isDirectory()) {
123            Console.printerrln(path + " is not a directory");
124            return;
125        }
126        if (directory.exists() && (directory.list().length > 0)) {
127            Console.printerrln(path + " is not empty");
128            return;
129        }
130
131        Object dataObject = GlobalDataContainer.getInstance().getData(taskTreeName);
132        if (dataObject == null) {
133            CommandHelpers.objectNotFoundMessage(taskTreeName);
134            return;
135        }
136        if (!(dataObject instanceof ITaskModel)) {
137            CommandHelpers.objectNotType(taskTreeName, "ITaskTree");
138            return;
139        }
140
141        ITaskModel taskModel = (ITaskModel) dataObject;
142       
143        LinkedList<ISequence> sequencesToExport =
144            determineSequencesToExport(tasksToExport, taskModel);
145       
146        int index = 1;
147        int width = Integer.toString(tasksToExport).length();
148        for (ISequence sequence : sequencesToExport) {
149            export(String.format("%0" + width + "d", index++),
150                   sequence, taskModel, directory, withTimestamp);
151        }
152    }
153
154    /**
155     * <p>
156     * TODO: comment
157     * </p>
158     *
159     * @param tasksToExport
160     * @param taskModel
161     * @return
162     */
163    private LinkedList<ISequence> determineSequencesToExport(int        tasksToExport,
164                                                             ITaskModel taskModel)
165    {
166        LinkedList<ISequence> sequencesToExport = new LinkedList<>();
167       
168        for (ITask task : taskModel.getTasks()) {
169            if (task instanceof ISequence) {
170                int coverage =
171                    taskModel.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE);
172               
173                boolean inserted = false;
174                ListIterator<ISequence> it = sequencesToExport.listIterator();
175               
176                while (it.hasNext()) {
177                    ISequence candidate = it.next();
178                    int candidateCoverage =
179                        taskModel.getTaskInfo(candidate).getMeasureValue(TaskMetric.EVENT_COVERAGE);
180                   
181                    if (coverage > candidateCoverage) {
182                        it.previous();
183                        it.add((ISequence) task);
184                        inserted = true;
185                        break;
186                    }
187                }
188               
189                if (!inserted) {
190                    sequencesToExport.add((ISequence) task);
191                }
192               
193                while (sequencesToExport.size() > tasksToExport) {
194                    sequencesToExport.removeLast();
195                }
196            }
197        }
198       
199        return sequencesToExport;
200    }
201
202    /**
203     * <p>
204     * TODO: comment
205     * </p>
206     *
207     * @param index
208     * @param sequence
209     * @param path
210     * @param withTimestamp
211     */
212    private void export(String     folderPrefix,
213                        ISequence  sequence,
214                        ITaskModel taskModel,
215                        File       directory,
216                        boolean    withTimestamp)
217    {
218        File exportDirectory = new File(directory, folderPrefix + "_pattern" + sequence.getId());
219       
220        if (exportDirectory.exists()) {
221            throw new IllegalArgumentException(exportDirectory + " already exists");
222        }
223        else {
224            exportDirectory.mkdirs();
225        }
226       
227        createPatternFile(sequence, taskModel, withTimestamp, exportDirectory);
228        createSessionFiles(sequence, taskModel, withTimestamp, exportDirectory);
229       
230        Console.println("exported " + sequence);
231    }
232
233    /**
234     * <p>
235     * TODO: comment
236     * </p>
237     *
238     * @param sequence
239     * @param taskModel
240     * @param withTimestamp
241     * @param exportDirectory
242     */
243    private void createPatternFile(ISequence  sequence,
244                                   ITaskModel taskModel,
245                                   boolean    withTimestamp,
246                                   File       exportDirectory)
247    {
248        // write the pattern file
249        File patternFile = new File(exportDirectory, "patternDetails.txt");
250        PrintStream out = null;
251        try {
252            out = new PrintStream(new FileOutputStream(patternFile));
253            out.println("########################################################################");
254            out.println("# Pattern");
255            out.println("########################################################################");
256            out.println();
257            dumpSequence(sequence, out);
258            out.println();
259           
260            out.println("########################################################################");
261            out.println("# Statistics");
262            out.println("########################################################################");
263            out.println();
264            int value = taskModel.getTaskInfo(sequence).getMeasureValue(TaskMetric.COUNT);
265            out.println("         count: " + TaskMetric.COUNT.formatValue(value));
266            value = taskModel.getTaskInfo(sequence).getMeasureValue(TaskMetric.EVENT_COVERAGE);
267            out.println("      coverage: " + TaskMetric.EVENT_COVERAGE.formatValue(value));
268            value = taskModel.getTaskInfo(sequence).getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO);
269            out.println("coverage ratio: " + TaskMetric.EVENT_COVERAGE_RATIO.formatValue(value));
270           
271            if (withTimestamp) {
272                long averageTimeBetweenEvents = getAverageTimeBetweenEvents(sequence);
273               
274                out.println("\naverage event time interval: " + averageTimeBetweenEvents + "ms");
275            }
276           
277            out.println();
278            out.println();
279            out.println("########################################################################");
280            out.println("# Execution variants");
281            out.println("########################################################################");
282            out.println();
283           
284            int index = 1;
285            for (Collection<ITaskInstance> variant : sequence.getExecutionVariants()) {
286                dumpExecutionVariant(index++, variant.size(), variant.iterator().next(), out);
287                out.println();
288            }
289        }
290        catch (IOException e) {
291            throw new IllegalArgumentException("could not write into file " + patternFile);
292        }
293        finally {
294            if (out != null) {
295                try {
296                    out.close();
297                }
298                catch (Exception e) {
299                    // ignore
300                }
301            }
302        }
303    }
304
305    /**
306     * <p>
307     * TODO: comment
308     * </p>
309     *
310     * @param sequence
311     * @return
312     */
313    private long getAverageTimeBetweenEvents(ISequence sequence) {
314        int intervalCount = 0;
315        long cummulativeTime = 0;
316        for (ITaskInstance instance : sequence.getInstances()) {
317            final List<Long> timestamps = new ArrayList<>();
318            instance.accept(new DefaultTaskInstanceTraversingVisitor() {
319                @Override
320                public void visit(IEventTaskInstance eventTaskInstance) {
321                    timestamps.add(eventTaskInstance.getEvent().getTimestamp());
322                }
323            });
324           
325            for (int i = 1; i < timestamps.size(); i++) {
326                cummulativeTime += timestamps.get(i) - timestamps.get(i - 1);
327                intervalCount++;
328            }
329        }
330       
331        return (cummulativeTime / intervalCount);
332    }
333
334    /**
335     * <p>
336     * TODO: comment
337     * </p>
338     *
339     * @param sequence
340     * @param stream
341     */
342    private void dumpSequence(ISequence sequence, final PrintStream stream) {
343        final String[] indent = new String[1];
344        indent[0] = "";
345       
346        sequence.accept(new DefaultTaskTraversingVisitor() {
347            @Override
348            public void visit(IEventTask eventTask) {
349                stream.print(indent[0]);
350                stream.println(eventTask.toString());
351            }
352
353            @Override
354            public void visit(IStructuringTemporalRelationship relationship) {
355                stream.print(indent[0]);
356                stream.print(relationship.toString());
357                stream.println(" {");
358                String indentBefore = indent[0];
359                indent[0] = indentBefore + "  ";
360                super.visit(relationship);
361                indent[0] = indentBefore;
362                stream.print(indent[0]);
363                stream.println("}");
364            }
365
366            @Override
367            public void visit(IMarkingTemporalRelationship relationship) {
368                stream.print(indent[0]);
369                stream.print(relationship.toString());
370                stream.println(" {");
371                String indentBefore = indent[0];
372                indent[0] = indentBefore + "  ";
373                super.visit(relationship);
374                indent[0] = indentBefore;
375                stream.print(indent[0]);
376                stream.println("}");
377            }
378        });
379    }
380
381    /**
382     *
383     */
384    private void dumpExecutionVariant(int               variantIndex,
385                                      int               count,
386                                      ITaskInstance     instance,
387                                      final PrintStream stream)
388    {
389        stream.println("\nVariant " + variantIndex + " (executed " + count + " times)\n");
390        final String[] indent = new String[1];
391        indent[0] = "  ";
392       
393        instance.accept(new DefaultTaskInstanceTraversingVisitor() {
394            @Override
395            public void visit(IEventTaskInstance eventTaskInstance) {
396                stream.print(indent[0]);
397                stream.println(eventTaskInstance.toString());
398            }
399
400            @Override
401            public void visit(ITaskInstanceList taskInstanceList) {
402                stream.print(indent[0]);
403                stream.print(taskInstanceList.toString());
404                stream.println(" {");
405                String indentBefore = indent[0];
406                indent[0] = indentBefore + "  ";
407                super.visit(taskInstanceList);
408                indent[0] = indentBefore;
409                stream.print(indent[0]);
410                stream.println("}");
411            }
412        });
413    }
414
415
416    /**
417     * <p>
418     * TODO: comment
419     * </p>
420     *
421     * @param instance
422     * @param taskModel
423     */
424    private void createSessionFiles(final ISequence  sequence,
425                                    final ITaskModel taskModel,
426                                    final boolean    withTimestamp,
427                                    final File       exportDirectory)
428    {
429        final File sessionsDirectory = new File(exportDirectory, "sessions");
430       
431        if (sessionsDirectory.exists()) {
432            throw new IllegalArgumentException(sessionsDirectory + " already exists");
433        }
434        else {
435            sessionsDirectory.mkdirs();
436        }
437
438        for (IUserSession session : taskModel.getUserSessions()) {
439            for (ITaskInstance instance : session) {
440                instance.accept(new DefaultTaskInstanceTraversingVisitor() {
441                    @Override
442                    public void visit(ISequenceInstance sequenceInstance) {
443                        if (sequence == sequenceInstance.getTask()) {
444                            createSessionFile(sequenceInstance, withTimestamp, sessionsDirectory);
445                        }
446                        super.visit(sequenceInstance);
447                    }
448                });
449            }
450        }
451    }
452
453
454    /**
455     * <p>
456     * TODO: comment
457     * </p>
458     *
459     * @param instance
460     * @param taskModel
461     */
462    private void createSessionFile(final ISequenceInstance instance,
463                                   final boolean           withTimestamp,
464                                   final File              exportDirectory)
465    {
466        // write the session file
467        final String userId = getUserOf(instance, exportDirectory);
468       
469        final File sessionsDirectory = new File(exportDirectory, userId);
470       
471        if (!sessionsDirectory.exists()) {
472            sessionsDirectory.mkdirs();
473        }
474
475        File sessionFile;
476       
477        // a user may have many sessions, search for the next id of it.
478        int index = 0;
479       
480        do {
481            sessionFile = new File
482                (sessionsDirectory, "session_" + String.format("%09d", ++index) + ".txt");
483        }
484        while (sessionFile.exists());
485       
486        PrintStream out = null;
487        try {
488            out = new PrintStream(new FileOutputStream(sessionFile));
489            final PrintStream finalOut = out;
490           
491            instance.accept(new DefaultTaskInstanceTraversingVisitor() {
492                @Override
493                public void visit(IEventTaskInstance eventTaskInstance) {
494                    Event event = eventTaskInstance.getEvent();
495                   
496                    if (withTimestamp) {
497                        finalOut.print(event.getTimestamp());
498                        finalOut.print("\t");
499                    }
500                   
501                    finalOut.print(userId);
502                    finalOut.print("\t");
503                   
504                    finalOut.print(event.getParameter("query"));
505                    finalOut.print("\t");
506                   
507                    finalOut.print(event.getParameter("selectedResultPage"));
508                    finalOut.print(" ");
509                   
510                    finalOut.print(event.getParameter("selectedResultIndex"));
511                    finalOut.print("\t");
512                   
513                    finalOut.println(event.getParameter("selectedResult"));
514                }
515            });
516           
517        }
518        catch (IOException e) {
519            throw new IllegalArgumentException("could not write into file " + sessionFile);
520        }
521        finally {
522            if (out != null) {
523                try {
524                    out.close();
525                }
526                catch (Exception e) {
527                    // ignore
528                }
529            }
530        }
531    }
532   
533    /**
534     * <p>
535     * TODO: comment
536     * </p>
537     *
538     * @param instance
539     * @return
540     */
541    private String getUserOf(ISequenceInstance instance, final File exportDirectory) {
542        final String[] result = new String[1];
543       
544        instance.accept(new DefaultTaskInstanceTraversingVisitor() {
545            @Override
546            public void visit(IEventTaskInstance eventTaskInstance) {
547                if (result[0] == null) {
548                    result[0] = eventTaskInstance.getEvent().getParameter("userId");
549                }
550            }
551            @Override
552            public void visit(ITaskInstanceList taskInstanceList) {
553                if (result[0] == null) {
554                    super.visit(taskInstanceList);
555                }
556            }
557        });
558       
559        if (result[0] == null) {
560            // no user id stored with events --> generate generic unused one
561            File sessionFile = null;
562            int index = 0;
563           
564            do {
565                sessionFile = new File
566                    (exportDirectory, "session_" + String.format("%09d", ++index) + ".txt");
567            }
568            while (sessionFile.exists());
569           
570            result[0] = String.format("%09d", index);
571        }
572       
573        return result[0];
574    }
575
576    /* (non-Javadoc)
577     * @see de.ugoe.cs.util.console.Command#help()
578     */
579    @Override
580    public String help() {
581        return "exportSogouQTaskTrees <tasktree> <directory> <numberOfTasksToExport> " +
582            "{-withTimestamp}";
583    }
584
585}
Note: See TracBrowser for help on using the repository browser.