1 module des.mc.multitrack.multitracker;
2 
3 import des.mc.multitrack.model;
4 import des.mc.core;
5 
6 import std.algorithm;
7 import std.array;
8 
9 class MultiTracker : Tracker
10 {
11 protected:
12 
13     Tracker[] trackers;
14     UserHandler[] handlers;
15 
16     Heuristic heuristic;
17     Classifier classifier;
18     Complexer complexer;
19     Destributor destributor;
20     MultiTrackerFactory factory;
21 
22 public:
23     this( Tracker[] trs, MultiTrackerFactory gtf )
24     {
25         trackers = trs;
26         setFactory( gtf );
27     }
28 
29     void setTrackers( Tracker[] trs )
30     {
31         trackers = trs;
32     }
33 
34     void setFactory( MultiTrackerFactory gtf )
35     {
36         factory = gtf;
37         heuristic = factory.heuristic;
38         classifier = factory.classifier;
39         complexer = factory.complexer;
40         destributor = factory.destributor;
41     }
42 
43     User[] getUsers()
44     {
45         auto skels = getReadySkeletons();
46         destributeSkeletonsToHandlers( skels );
47         return getRespectableUsers();
48     }
49 
50 protected:
51 
52     Skeleton[] getReadySkeletons()
53     {
54         auto by_trackers = getSkeletonsByTrackers();
55         auto by_users = classifier( by_trackers );
56         return complexer( by_users );
57     }
58 
59     Skeleton[][] getSkeletonsByTrackers()
60     {
61         Skeleton[][] ret;
62         foreach( tracker; trackers )
63             ret ~= array( map!(a=>heuristic(a.skel))(tracker.getUsers()) );
64         return ret;
65     }
66 
67     void destributeSkeletonsToHandlers( Skeleton[] skels )
68     {
69         setHandlersOverdue();
70         auto not_destributed = destributor( handlers, skels );
71         addNewHandlers( not_destributed );
72         cleanUpOverdueHandlers();
73     }
74 
75     void setHandlersOverdue() { foreach( uh; handlers ) uh.setOverdue(); }
76 
77     void addNewHandlers( Skeleton[] skels )
78     {
79         foreach( skel; skels )
80             handlers ~= factory.newUserHandler( User(freeUserId, skel) );
81     }
82 
83     @property size_t freeUserId() { return users_id++; }
84     size_t users_id = 0;
85 
86     void cleanUpOverdueHandlers()
87     {
88         UserHandler[] good;
89         foreach( uh; handlers )
90             if( !uh.isOverdue )
91                 good ~= uh;
92         handlers = good;
93     }
94 
95     User[] getRespectableUsers()
96     {
97         return array( map!(a=>a.user)( filter!(a=>a.respectable)(handlers) ) ).dup;
98     }
99 }