Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/notifications/src/modules/notifications/NotificationQueue.cc @ 7398

Last change on this file since 7398 was 7398, checked in by dafrick, 14 years ago

Done some selective testing and it finally seems to work.

  • Property svn:eol-style set to native
File size: 12.4 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 NotificationQueue.cc
31    @brief Implementation of the NotificationQueue class.
32*/
33
34#include "NotificationQueue.h"
35
36#include <map>
37#include <sstream>
38
39#include "core/CoreIncludes.h"
40#include "core/GUIManager.h"
41#include "core/LuaState.h"
42#include "util/Convert.h"
43#include "Notification.h"
44
45namespace orxonox
46{
47
48    /**
49    @brief
50        Constructor. Creates and initializes the object.
51    */
52    NotificationQueue::NotificationQueue(const std::string& name, const std::string& senders, unsigned int size, unsigned int displayTime)
53    {
54        this->registered_ = false;
55
56        RegisterRootObject(NotificationQueue);
57
58        this->initialize();
59
60        this->setTargets(senders);
61        this->name_ = name;
62        this->maxSize_ = size;
63        this->setDisplayTime(displayTime);
64
65        bool queueRegistered = NotificationManager::getInstance().registerQueue(this);
66        this->registered_ = true;
67        if(!queueRegistered)
68        {
69            this->registered_ = false;
70            COUT(1) << "Error: Notification Queue '" << this->getName() << "' could not be registered." << std::endl;
71            return;
72        }
73
74        this->create();
75       
76        bool listenerRegistered = NotificationManager::getInstance().registerListener(this);
77        if(!listenerRegistered)
78        {
79            this->registered_ = false;
80            NotificationManager::getInstance().unregisterQueue(this);
81            COUT(1) << "Error: Notification Queue '" << this->getName() << "' could not be registered." << std::endl;
82            return;
83        }
84
85        COUT(3) << "NotificationQueue '" << this->getName() << "' created." << std::endl;
86    }
87
88    /**
89    @brief
90        Destructor.
91    */
92    NotificationQueue::~NotificationQueue()
93    {
94        this->targets_.clear();
95
96        if(this->registered_)
97        {
98            this->clear();
99           
100            NotificationManager::getInstance().unregisterListener(this);
101            NotificationManager::getInstance().unregisterQueue(this);
102
103            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() +  "\")");
104        }
105    }
106
107    /**
108    @brief
109        Initializes the object.
110        Registers the object, initializes variables, sets default values and registers the queue with the NotificationManager.
111    */
112    void NotificationQueue::initialize(void)
113    {
114        this->size_ = 0;
115        this->tickTime_ = 0.0;
116    }
117
118    /**
119    @brief
120        Creates the NotificationQueue in lua.
121    */
122    void NotificationQueue::create(void)
123    {
124        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.createQueue(\"" + this->getName() +  "\", " + multi_cast<std::string>(this->getMaxSize()) + ")");
125    }
126
127    /**
128    @brief
129        Updates the queue from time to time.
130    @param dt
131        The time interval that has passed since the last tick.
132    */
133    void NotificationQueue::tick(float dt)
134    {
135        this->tickTime_ += dt; // Add the time interval that has passed to the time counter.
136        if(this->tickTime_ >= 1.0) // If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick.
137        {
138            this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containig the current time.
139
140            std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = this->ordering_.begin();
141            while(it != this->ordering_.upper_bound(&this->timeLimit_)) // Iterate through all elements whose creation time is smaller than the current time minus the display time.
142            {
143                NotificationContainer* temp = *it;
144                it++;
145                this->remove(temp);
146            }
147
148            this->tickTime_ = this->tickTime_ - (int)this->tickTime_; // Reset time counter.
149        }
150    }
151
152    /**
153    @brief
154        Updates the NotificationQueue.
155        Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue.
156    */
157    void NotificationQueue::update(void)
158    {
159        this->clear();
160
161        std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>;
162        if(!NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_)) // Get the Notifications sent in the interval form now to minus the display time.
163        {
164            COUT(1) << "NotificationQueue update failed due to undetermined cause." << std::endl;
165            return;
166        }
167
168        if(!notifications->empty())
169        {
170            for(std::multimap<std::time_t, Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++) // Add all Notifications.
171            {
172                this->push(it->second, it->first);
173            }
174        }
175
176        delete notifications;
177
178        COUT(3) << "NotificationQueue '" << this->getName() << "' updated." << std::endl; //TODO: Level 4.
179    }
180
181    /**
182    @brief
183        Updates the NotificationQueue by adding an new Notification.
184    @param notification
185        Pointer to the Notification.
186    @param time
187        The time the Notification was sent.
188    */
189    void NotificationQueue::update(Notification* notification, const std::time_t & time)
190    {
191        this->push(notification, time);
192
193        COUT(3) << "NotificationQueue '" << this->getName() << "' updated. A new Notification has been added." << std::endl; //TODO: Level 4.
194    }
195
196    /**
197    @brief
198        Adds a Notification to the NotificationQueue.
199        It inserts it into the storage containers, creates a corresponding container and pushes the Notification message to the GUI.
200    @param notification
201        The Notification.
202    @param time
203        The time.
204    */
205    void NotificationQueue::push(Notification* notification, const std::time_t & time)
206    {
207        NotificationContainer* container = new NotificationContainer;
208        container->notification = notification;
209        container->time = time;
210
211        // If the maximum size of the NotificationQueue has been reached the last (least recently added) Notification is removed.
212        if(this->getSize() >= this->getMaxSize())
213            this->pop();
214
215        this->size_++;
216
217        this->ordering_.insert(container);
218        this->notifications_.insert(this->notifications_.begin(), container);
219
220        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.pushNotification(\"" + this->getName() + "\", \"" + notification->getMessage() + "\")");
221    }
222
223    /**
224    @brief
225        Removes the least recently added Notification form the NotificationQueue.
226    */
227    void NotificationQueue::pop(void)
228    {
229        NotificationContainer* container = this->notifications_.back();
230        this->ordering_.erase(container);
231        this->notifications_.pop_back();
232        this->size_--;
233        delete container;
234        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.popNotification(\"" + this->getName() + "\")");
235    }
236
237    /**
238    @brief
239        Removes the Notification that is stored in the input container.
240    @param container
241        The NotificationContainer with the Notification to be removed.
242    */
243    void NotificationQueue::remove(NotificationContainer* container)
244    {
245        std::vector<NotificationContainer*>::iterator it = std::find(this->notifications_.begin(), this->notifications_.end(), container);
246        std::vector<NotificationContainer*>::difference_type index = it - this->notifications_.begin ();
247        this->ordering_.erase(container);
248        this->notifications_.erase(it);
249        this->size_--;
250        delete container;
251        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeNotification(\"" + this->getName() + "\", " + multi_cast<std::string>(index) + ")");
252    }
253
254    /**
255    @brief
256        Clears the queue by removing all Notifications.
257    */
258    void NotificationQueue::clear(void)
259    {
260        this->ordering_.clear();
261        for(std::vector<NotificationContainer*>::iterator it = this->notifications_.begin(); it != this->notifications_.end(); it++)
262            delete *it;
263
264        this->notifications_.clear();
265        this->size_ = 0;
266        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.clearQueue(\"" + this->getName() + "\")");
267    }
268
269    /**
270    @brief
271        Sets the name of the NotificationQueue.
272    @param name
273        The name to be set.
274    @return
275        returns true if successful.
276    */
277    bool NotificationQueue::setName(const std::string& name)
278    {
279        this->name_ = name;
280        return true;
281    }
282
283    /**
284    @brief
285        Sets the maximum number of displayed Notifications.
286    @param size
287        The size to be set.
288    @return
289        Returns true if successful.
290    */
291    void NotificationQueue::setMaxSize(unsigned int size)
292    {
293        if(this->maxSize_ == size)
294            return;
295       
296        this->maxSize_ = size;
297        this->sizeChanged();
298    }
299
300    /**
301    @brief
302        Adjusts the NotificationQueue, when the maximum size has changed.
303    */
304    void NotificationQueue::sizeChanged(void)
305    {
306        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.changeSize(\"" + this->getName() + "\", " + multi_cast<std::string>(this->getSize()) + ")");
307        this->update();
308    }
309
310    /**
311    @brief
312        Sets the maximum number of seconds a Notification is displayed.
313    @param time
314        The number of seconds the Notifications is displayed.
315    @return
316        Returns true if successful.
317    */
318    void NotificationQueue::setDisplayTime(unsigned int time)
319    {
320        if(this->displayTime_ == time)
321            return;
322
323        this->displayTime_ = time;
324
325        if(this->registered_)
326            this->update();
327    }
328
329    /**
330    @brief
331        Produces all targets concatinated as string, with kommas (',') as seperators.
332    @return
333        Returns the targets as a string.
334    */
335    const std::string& NotificationQueue::getTargets(void) const
336    {
337        std::stringstream stream;
338        bool first = true;
339        for(std::set<std::string, NotificationListenerStringCompare>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++) // Iterate through the set of targets.
340        {
341            if(!first)
342                stream << ',';
343            else
344                first = false;
345            stream << *it;
346        }
347
348        return *(new std::string(stream.str()));
349    }
350
351    /**
352    @brief
353        Sets the targets of the queue.
354        The targets are the senders whose Notifications are displayed in this queue.
355    @param targets
356        Accepts a string of targets, each seperated by commas (','), spaces are ignored.
357    @return
358        Returns true if successful.
359    */
360    bool NotificationQueue::setTargets(const std::string & targets)
361    {
362        this->targets_.clear();
363
364        //TODO: Do with SubString.
365        std::string* pTemp;
366        unsigned int index = 0;
367        while(index < targets.size()) // Go through the string, character by character until the end is reached.
368        {
369            pTemp = new std::string();
370            while(index < targets.size() && targets[index] != ',' && targets[index] != ' ')
371            {
372                *pTemp += targets[index];
373                index++;
374            }
375            index++;
376            this->targets_.insert(*pTemp);
377        }
378
379        if(this->registered_)
380        {
381            NotificationManager::getInstance().unregisterListener(this);
382            NotificationManager::getInstance().registerListener(this);
383        }
384
385        return true;
386    }
387
388}
Note: See TracBrowser for help on using the repository browser.