Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/notifications/NotificationManager.cc @ 8706

Last change on this file since 8706 was 8706, checked in by dafrick, 13 years ago

Merging presentation branch back into trunk.
There are many new features and also a lot of other changes and bugfixes, if you want to know, digg through the svn log.
Not everything is yet working as it should, but it should be fairly stable. If you habe any bug reports, just send me an email.

  • Property svn:eol-style set to native
File size: 17.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file NotificationManager.cc
31    @brief Implementation of the NotificationManager class.
32*/
33
34#include "NotificationManager.h"
35
36#include "core/command/ConsoleCommand.h"
37#include "core/CoreIncludes.h"
38#include "core/LuaState.h"
39#include "util/ScopedSingletonManager.h"
40
41#include "interfaces/NotificationListener.h"
42
43#include "NotificationQueue.h"
44#include "NotificationQueueCEGUI.h"
45
46namespace orxonox
47{
48
49    ManageScopedSingleton(NotificationManager, ScopeID::Root, false);
50
51    /**
52    @brief
53        Constructor. Registers the Object.
54    */
55    NotificationManager::NotificationManager()
56    {
57        RegisterRootObject(NotificationManager);
58
59        COUT(3) << "NotificatioManager created." << std::endl;
60    }
61
62    /**
63    @brief
64        Destructor.
65    */
66    NotificationManager::~NotificationManager()
67    {
68        // Destroys all Notifications.
69        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it!= this->allNotificationsList_.end(); it++)
70            it->second->destroy();
71        this->allNotificationsList_.clear();
72
73        COUT(3) << "NotificationManager destroyed." << std::endl;
74    }
75
76    /**
77    @brief
78        Is called before the object is destroyed.
79    */
80    void NotificationManager::preDestroy(void)
81    {
82        // Destroys all NotificationQueues that have been registered with the NotificationManager.
83        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin();
84        while(it != this->queues_.end())
85        {
86            it->second->destroy();
87            it = this->queues_.begin();
88        }
89
90        this->queues_.clear();
91    }
92
93    /**
94    @brief
95        Creates and registers a Notification with the input message from the input sender.
96        This is called by the NotificationListener, whenever a new notification arrives.
97    @param message
98        The message of the new Notification.
99    @param sender
100        The name of the entity (of the collective) that sent the new Notification.
101    @param type
102        The type of the new Notification.
103    @return
104        Returns true if successful.
105    */
106    bool NotificationManager::registerNotification(const std::string& message, const std::string& sender, notificationMessageType::Value type)
107    {
108        // TODO: Do something with the type.
109        Notification* notification = new Notification(message, sender, type);
110        return this->registerNotification(notification);
111    }
112
113    /**
114    @brief
115        Executes the input command from the input sender.
116        This is called by the NotificationListener, whenever a new command arrives.
117    @param command
118        The command to be executed,
119    @param sender
120        The The name of the entity (of the collective) that sent the command.
121    @return
122        Returns true if the command was successfully executed.
123    */
124    bool NotificationManager::executeCommand(notificationCommand::Value command, const std::string& sender)
125    {
126        bool commandExecuted = false;
127        if(command == notificationCommand::clear)
128        {
129            if(this->commandClear(sender))
130                commandExecuted = true;
131        }
132
133        if(commandExecuted)
134            COUT(3) << "Notification command \"" << NotificationListener::command2Str(command) << "\" executed." << endl;
135
136        return commandExecuted;
137    }
138
139    /**
140    @brief
141        The clear command. Clears all NotificationQueues that have its sender as a target.
142    @param sender
143        The sender of the clear command.
144    @return
145        Returns true if the command was successfully executed by at least one NotificationQueue, false if it was not executed.
146    */
147    bool NotificationManager::commandClear(const std::string& sender)
148    {
149        bool all = (sender == NotificationListener::ALL);
150        bool executed = false;
151        // Clear all NotificationQueues that have the input sender as target.
152        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); it++) // Iterate through all NotificationQueues.
153        {
154            const std::set<std::string>& set = it->second->getTargetsSet();
155            // If either the sender is 'all', the NotificationQueue has as target all or the NotificationQueue has the input sender as a target.
156            if(all || set.find(NotificationListener::ALL) != set.end() || set.find(sender) != set.end())
157                executed = it->second->tidy() || executed;
158        }
159
160        return executed;
161    }
162   
163    /**
164    @brief
165        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationQueues associated with its sender.
166    @param notification
167        The Notification to be registered.
168    @return
169        Returns true if successful.
170    */
171    bool NotificationManager::registerNotification(Notification* notification)
172    {
173        assert(notification);
174
175        std::time_t time = std::time(0); // Get current time.
176
177        // Add the Notification to the list that holds all Notifications.
178        this->allNotificationsList_.insert(std::pair<std::time_t, Notification*>(time, notification));
179
180        if(notification->getSender() == NotificationListener::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
181            return true;
182
183        // If all are the sender, then the Notifications is added to every NotificationQueue.
184        bool all = (notification->getSender() == NotificationListener::ALL);
185
186        // Insert the Notification in all NotificationQueues that have its sender as target.
187        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); it++) // Iterate through all NotificationQueues.
188        {
189            const std::set<std::string>& set = it->second->getTargetsSet();
190            bool bAll = set.find(NotificationListener::ALL) != set.end();
191            // If either the Notification has as sender 'all', the NotificationQueue displays all Notifications or the NotificationQueue has the sender of the Notification as target.
192            if(all || bAll || set.find(notification->getSender()) != set.end())
193            {
194                if(!bAll)
195                    this->notificationLists_[it->second->getName()]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the notifications list of the current NotificationQueue.
196                it->second->update(notification, time); // Update the NotificationQueue.
197            }
198        }
199
200        COUT(4) << "Notification (&" << notification << ") registered with the NotificationManager." << std::endl;
201
202        return true;
203    }
204
205    /**
206    @brief
207        Unregisters a Notification within the NotificationManager for a given NotificationQueue.
208    @param notification
209        A pointer to the Notification to be unregistered.
210    @param queue
211        A pointer to the NotificationQueue the Notification is unregistered for.
212    */
213    void NotificationManager::unregisterNotification(Notification* notification, NotificationQueue* queue)
214    {
215        assert(notification);
216        assert(queue);
217
218        // Remove the Notification from the list of Notifications of the input NotificationQueue.
219        this->removeNotification(notification, *(this->notificationLists_.find(queue->getName())->second));
220
221        COUT(4) << "Notification (&" << notification << ") unregistered with the NotificationManager from NotificationQueue " << queue->getName() << "." << std::endl;
222    }
223
224    /**
225    @brief
226        Helper method that removes an input Notification form an input map.
227    @param notification
228        A pointer to the Notification to be removed.
229    @param map
230        The map the Notification should be removed from.
231    @return
232        Returns true if successful.
233    */
234    bool NotificationManager::removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map)
235    {
236        // Iterates through all items in the map until the Notification is found.
237        //TODO: Do more efficiently?
238        for(std::multimap<std::time_t, Notification*>::iterator it = map.begin(); it != map.end(); it++)
239        {
240            if(it->second == notification)
241            {
242                map.erase(it);
243                return true;
244            }
245        }
246        return false;
247    }
248
249    /**
250    @brief
251        Fetches the Notifications for a specific NotificationQueue in a specified timeframe and stores them in the input map.
252    @param queue
253        The NotificationQueue the Notifications are fetched for.
254    @param map
255        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
256    @param timeFrameStart
257        The start time of the timeframe.
258    @param timeFrameEnd
259        The end time of the timeframe.
260    @return
261        Returns true if successful.
262    */
263    void NotificationManager::getNotifications(NotificationQueue* queue, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
264    {
265        assert(queue);
266        assert(map);
267
268        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
269
270        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
271        // Iterators pointing to the bounds specified by the specified start and end times of the time frame.
272        itLowest = notifications->lower_bound(timeFrameStart);
273        itHighest = notifications->upper_bound(timeFrameEnd);
274
275        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time frame to the end of it.
276            map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
277    }
278
279    /**
280    @brief
281        Fetches the newest Notifications for a specific NotificationQueue and stores them in the input map.
282    @param queue
283        The NotificationQueue the Notifications are fetched for.
284    @param map
285        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
286    @param numberOfNotifications
287        The number of newest Notifications to be got.
288    @return
289        Returns true if successful.
290    */
291    void NotificationManager::getNewestNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int numberOfNotifications)
292    {
293        assert(queue);
294        assert(map);
295
296        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
297
298        if(!notifications->empty()) // If the list of Notifications is not empty.
299        {
300            std::multimap<std::time_t,Notification*>::iterator it = notifications->end();
301            for(int i = 0; i < numberOfNotifications; i++) // Iterate through the Notifications from the newest until we have the specified number of notifications.
302            {
303                it--;
304                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
305                if(it == notifications->begin())
306                    break;
307            }
308        }
309    }
310
311    /**
312    @brief
313        Registers a NotificationQueue.
314        This makes sure that the NotificationQueue can be accessed through lua by name. It also makes sure that the NotificationQueue is destroyed upon destruction of the NotificationManager.
315    @param queue
316        A pointer to the NotificationQueue to be registered.
317    @return
318        Returns true if successful. If e.g. the a NotificationQueue with that name already exists this returns false.
319    */
320    bool NotificationManager::registerQueue(NotificationQueue* queue)
321    {
322        assert(queue);
323
324        // If the NotificationQueue is already registered.
325        if(this->queues_.find(queue->getName()) != this->queues_.end())
326            return false;
327
328        this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)); // Add the NotificationQueue to the list of NotificationQueues.
329
330        const std::set<std::string>& set = queue->getTargetsSet();
331
332        // If all senders are the target of the NotificationQueue, then the list of Notifications for that specific NotificationQueue is the same as the list of all Notifications.
333        bool bAll = set.find(NotificationListener::ALL) != set.end();
334        std::multimap<std::time_t, Notification*>* map = NULL;
335        if(bAll)
336            this->notificationLists_[queue->getName()] = &this->allNotificationsList_;
337        // Else a new list (resp. multimap) is created and added to the list of Notification lists for NotificationQueues.
338        else
339        {
340            this->notificationLists_[queue->getName()] = new std::multimap<std::time_t, Notification*>;
341            map = this->notificationLists_[queue->getName()];
342        }
343
344        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationQueue.
345        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
346        {
347            if(!bAll && set.find(it->second->getSender()) != set.end()) // Checks whether the listener has the sender of the current Notification as target.
348                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second));
349        }
350
351        queue->update(); // Update the queue.
352       
353        COUT(4) << "NotificationQueue '" << queue->getName() << "' registered with the NotificationManager." << std::endl;
354        return true;
355    }
356
357    /**
358    @brief
359        Unregisters a NotificationQueue.
360    @param queue
361        A pointer to the NotificationQueue to be unregistered.
362    */
363    void NotificationManager::unregisterQueue(NotificationQueue* queue)
364    {
365        assert(queue);
366
367        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(queue->getName())->second;
368
369        // If the map is not the map of all Notifications, make sure all Notifications are unregistered.
370        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
371        if(map != &this->allNotificationsList_)
372        {
373            while(it != map->end())
374            {
375                this->unregisterNotification(it->second, queue);
376                it = map->begin();
377            }
378            delete map;
379        }
380
381        // Remove the NotificationQueue from the list of NotificationQueues.
382        this->queues_.erase(queue->getName());
383        // Remove the Notifications list that was associated with the input NotificationQueue.
384        this->notificationLists_.erase(queue->getName());
385       
386        COUT(4) << "NotificationQueue '" << queue->getName() << "' unregistered with the NotificationManager." << std::endl;
387    }
388
389    /**
390    @brief
391        Get the NotificationQueue with the input name.
392    @param name
393        The name of the NotificationQueue.
394    @return
395        Returns a pointer to the NotificationQueue with the input name. Returns NULL if no NotificationQueue with such a name exists.
396    */
397    NotificationQueue* NotificationManager::getQueue(const std::string & name)
398    {
399        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
400        // Returns NULL if no such NotificationQueue exists.
401        if(it == this->queues_.end())
402            return NULL;
403
404        return (*it).second;
405    }
406
407    /**
408    @brief
409        Loads all the NotificationQueues that should exist.
410    */
411    void NotificationManager::loadQueues(void)
412    {
413        /*NotificationQueueCEGUI* allQueue = new NotificationQueueCEGUI("all");
414        allQueue->setDisplaySize(Vector2(0.5, 0));
415        allQueue->setPosition(Vector4(0.0, 10, 0.3, 0));
416
417        NotificationQueueCEGUI* infoQueue = new NotificationQueueCEGUI("info", "gameinfo", 1, -1);
418        infoQueue->setPosition(Vector4(0.2, 0, 0.8, 0));
419        infoQueue->setFontSize(24);
420        infoQueue->setFontColor(Vector4(1.0, 1.0, 0.0, 0.8));
421        infoQueue->setAlignment("HorzCentred");
422        infoQueue->setDisplaySize(Vector2(0.6, 0.0));*/
423    }
424
425    // Notification class
426
427    /**
428    @brief
429        Constructor. Creates a Notification with the input message and sender.
430    @param message
431        The message of the Notification.
432    @param sender
433        The sender of the Notification.
434    @param type
435
436    */
437    Notification::Notification(const std::string& message, const std::string& sender, notificationMessageType::Value type)
438    {
439        this->initialize();
440        this->message_ = message;
441        this->sender_ = sender;
442        this->type_ = type;
443    }
444
445    /**
446    @brief
447        Destructor.
448    */
449    Notification::~Notification()
450    {
451
452    }
453
454    /**
455    @brief
456        Registers the object and sets some default values.
457    */
458    void Notification::initialize(void)
459    {
460        this->message_.clear();
461        this->sender_ = NotificationListener::NONE;
462    }
463
464}
Note: See TracBrowser for help on using the repository browser.