Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/modules/notifications/NotificationManager.cc @ 10407

Last change on this file since 10407 was 10407, checked in by landauf, 9 years ago

moved Scope and ScopedSingletonManager from util to core.
TODO I had to disable two tests in ScopeTest.cc because now that it runs in the core library, there are too many singletons which get loaded in graphics scope (with too many dependencies). this should be fixed

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