123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- /****************************************************************************
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011-2012 cocos2d-x.org
- Copyright (c) 2013-2014 Chukong Technologies Inc.
- http://www.cocos2d-x.org
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- /**
- * Minimum priority level for user scheduling.
- * @constant
- * @type Number
- */
- cc.PRIORITY_NON_SYSTEM = cc.PRIORITY_SYSTEM + 1;
- //data structures
- /**
- * A list double-linked list used for "updates with priority"
- * @Class
- * @name cc.ListEntry
- * @param {cc.ListEntry} prev
- * @param {cc.ListEntry} next
- * @param {cc.Class} target not retained (retained by hashUpdateEntry)
- * @param {Number} priority
- * @param {Boolean} paused
- * @param {Boolean} markedForDeletion selector will no longer be called and entry will be removed at end of the next tick
- */
- cc.ListEntry = function (prev, next, target, priority, paused, markedForDeletion) {
- this.prev = prev;
- this.next = next;
- this.target = target;
- this.priority = priority;
- this.paused = paused;
- this.markedForDeletion = markedForDeletion;
- };
- /**
- * A update entry list
- * @Class
- * @name cc.HashUpdateEntry
- * @param {cc.ListEntry} list Which list does it belong to ?
- * @param {cc.ListEntry} entry entry in the list
- * @param {cc.Class} target hash key (retained)
- * @param {Array} hh
- */
- cc.HashUpdateEntry = function (list, entry, target, hh) {
- this.list = list;
- this.entry = entry;
- this.target = target;
- this.hh = hh;
- };
- //
- /**
- * Hash Element used for "selectors with interval"
- * @Class
- * @param {Array} timers
- * @param {cc.Class} target hash key (retained)
- * @param {Number} timerIndex
- * @param {cc.Timer} currentTimer
- * @param {Boolean} currentTimerSalvaged
- * @param {Boolean} paused
- * @param {Array} hh
- */
- cc.HashTimerEntry = function (timers, target, timerIndex, currentTimer, currentTimerSalvaged, paused, hh) {
- var _t = this;
- _t.timers = timers;
- _t.target = target;
- _t.timerIndex = timerIndex;
- _t.currentTimer = currentTimer;
- _t.currentTimerSalvaged = currentTimerSalvaged;
- _t.paused = paused;
- _t.hh = hh;
- };
- /**
- * Light weight timer
- * @class
- * @extends cc.Class
- */
- cc.Timer = cc.Class.extend(/** @lends cc.Timer# */{
- _interval:0.0,
- _callback:null,//is called _callback before
- _target:null,//target of _callback
- _elapsed:0.0,
- _runForever:false,
- _useDelay:false,
- _timesExecuted:0,
- _repeat:0, //0 = once, 1 is 2 x executed
- _delay:0,
- /**
- * @return {Number} returns interval of timer
- */
- getInterval : function(){return this._interval;},
- /**
- * @param {Number} interval set interval in seconds
- */
- setInterval : function(interval){this._interval = interval;},
- /**
- * @return {String|function} returns callback
- */
- getCallback : function(){return this._callback},
- /**
- * cc.Timer's Constructor
- * Constructor of cc.Timer
- * @param {cc.Class} target target
- * @param {String|function} callback Selector
- * @param {Number} [interval=0] second
- * @param {Number} [repeat=cc.REPEAT_FOREVER] repeat times
- * @param {Number} [delay=0] delay
- */
- ctor:function (target, callback, interval, repeat, delay) {
- var self = this;
- self._target = target;
- self._callback = callback;
- self._elapsed = -1;
- self._interval = interval || 0;
- self._delay = delay || 0;
- self._useDelay = self._delay > 0;
- self._repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
- self._runForever = (self._repeat == cc.REPEAT_FOREVER);
- },
- _doCallback:function(){
- var self = this;
- if (typeof(self._callback) == "string")
- self._target[self._callback](self._elapsed);
- else // if (typeof(this._callback) == "function") {
- self._callback.call(self._target, self._elapsed);
- },
- /**
- * triggers the timer
- * @param {Number} dt delta time
- */
- update:function (dt) {
- var self = this;
- if (self._elapsed == -1) {
- self._elapsed = 0;
- self._timesExecuted = 0;
- } else {
- var locTarget = self._target, locCallback = self._callback;
- self._elapsed += dt;//standard timer usage
- if (self._runForever && !self._useDelay) {
- if (self._elapsed >= self._interval) {
- if (locTarget && locCallback)
- self._doCallback();
- self._elapsed = 0;
- }
- } else {
- //advanced usage
- if (self._useDelay) {
- if (self._elapsed >= self._delay) {
- if (locTarget && locCallback)
- self._doCallback();
- self._elapsed = self._elapsed - self._delay;
- self._timesExecuted += 1;
- self._useDelay = false;
- }
- } else {
- if (self._elapsed >= self._interval) {
- if (locTarget && locCallback)
- self._doCallback();
- self._elapsed = 0;
- self._timesExecuted += 1;
- }
- }
- if (self._timesExecuted > self._repeat)
- cc.director.getScheduler().unscheduleCallbackForTarget(locTarget, locCallback);
- }
- }
- }
- });
- /**
- * <p>
- * Scheduler is responsible of triggering the scheduled callbacks.<br/>
- * You should not use NSTimer. Instead use this class.<br/>
- * <br/>
- * There are 2 different types of callbacks (selectors):<br/>
- * - update callback: the 'update' callback will be called every frame. You can customize the priority.<br/>
- * - custom callback: A custom callback will be called every frame, or with a custom interval of time<br/>
- * <br/>
- * The 'custom selectors' should be avoided when possible. It is faster, and consumes less memory to use the 'update callback'. *
- * </p>
- * @class
- * @extends cc.Class
- *
- * @example
- * //register a schedule to scheduler
- * cc.director.getScheduler().scheduleSelector(callback, this, interval, !this._isRunning);
- */
- cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
- _timeScale:1.0,
- _updates : null, //_updates[0] list of priority < 0, _updates[1] list of priority == 0, _updates[2] list of priority > 0,
- _hashForUpdates:null, // hash used to fetch quickly the list entries for pause,delete,etc
- _arrayForUpdates:null,
- _hashForTimers:null, //Used for "selectors with interval"
- _arrayForTimes:null,
- _currentTarget:null,
- _currentTargetSalvaged:false,
- _updateHashLocked:false, //If true unschedule will not remove anything from a hash. Elements will only be marked for deletion.
- ctor:function () {
- var self = this;
- self._timeScale = 1.0;
- self._updates = [[], [], []];
- self._hashForUpdates = {};
- self._arrayForUpdates = [];
- self._hashForTimers = {};
- self._arrayForTimers = [];
- self._currentTarget = null;
- self._currentTargetSalvaged = false;
- self._updateHashLocked = false;
- },
- //-----------------------private method----------------------
- _removeHashElement:function (element) {
- delete this._hashForTimers[element.target.__instanceId];
- cc.arrayRemoveObject(this._arrayForTimers, element);
- element.Timer = null;
- element.target = null;
- element = null;
- },
- _removeUpdateFromHash:function (entry) {
- var self = this, element = self._hashForUpdates[entry.target.__instanceId];
- if (element) {
- //list entry
- cc.arrayRemoveObject(element.list, element.entry);
- delete self._hashForUpdates[element.target.__instanceId];
- cc.arrayRemoveObject(self._arrayForUpdates, element);
- element.entry = null;
- //hash entry
- element.target = null;
- }
- },
- _priorityIn:function (ppList, target, priority, paused) {
- var self = this, listElement = new cc.ListEntry(null, null, target, priority, paused, false);
- // empey list ?
- if (!ppList) {
- ppList = [];
- ppList.push(listElement);
- } else {
- var index2Insert = ppList.length - 1;
- for(var i = 0; i <= index2Insert; i++){
- if (priority < ppList[i].priority) {
- index2Insert = i;
- break;
- }
- }
- ppList.splice(i, 0, listElement);
- }
- //update hash entry for quick access
- var hashElement = new cc.HashUpdateEntry(ppList, listElement, target, null);
- self._arrayForUpdates.push(hashElement);
- self._hashForUpdates[target.__instanceId] = hashElement;
- return ppList;
- },
- _appendIn:function (ppList, target, paused) {
- var self = this, listElement = new cc.ListEntry(null, null, target, 0, paused, false);
- ppList.push(listElement);
- //update hash entry for quicker access
- var hashElement = new cc.HashUpdateEntry(ppList, listElement, target, null);
- self._arrayForUpdates.push(hashElement);
- self._hashForUpdates[target.__instanceId] = hashElement;
- },
- //-----------------------public method-------------------------
- /**
- * <p>
- * Modifies the time of all scheduled callbacks.<br/>
- * You can use this property to create a 'slow motion' or 'fast forward' effect.<br/>
- * Default is 1.0. To create a 'slow motion' effect, use values below 1.0.<br/>
- * To create a 'fast forward' effect, use values higher than 1.0.<br/>
- * @warning It will affect EVERY scheduled selector / action.
- * </p>
- * @param {Number} timeScale
- */
- setTimeScale:function (timeScale) {
- this._timeScale = timeScale;
- },
- /**
- * Returns time scale of scheduler
- * @return {Number}
- */
- getTimeScale:function () {
- return this._timeScale;
- },
- /**
- * 'update' the scheduler. (You should NEVER call this method, unless you know what you are doing.)
- * @param {Number} dt delta time
- */
- update:function (dt) {
- var self = this;
- var locUpdates = self._updates, locArrayForTimers = self._arrayForTimers;
- var tmpEntry, elt, i, li;
- self._updateHashLocked = true;
- if (this._timeScale != 1.0) {
- dt *= this._timeScale;
- }
- for(i = 0, li = locUpdates.length; i < li && i >= 0; i++){
- var update = self._updates[i];
- for(var j = 0, lj = update.length; j < lj; j++){
- tmpEntry = update[j];
- if ((!tmpEntry.paused) && (!tmpEntry.markedForDeletion)) tmpEntry.target.update(dt);
- }
- }
- //Interate all over the custom callbacks
- for(i = 0, li = locArrayForTimers.length; i < li; i++){
- elt = locArrayForTimers[i];
- if(!elt) break;
- self._currentTarget = elt;
- self._currentTargetSalvaged = false;
- if (!elt.paused) {
- // The 'timers' array may change while inside this loop
- for (elt.timerIndex = 0; elt.timerIndex < elt.timers.length; elt.timerIndex++) {
- elt.currentTimer = elt.timers[elt.timerIndex];
- elt.currentTimerSalvaged = false;
- elt.currentTimer.update(dt);
- elt.currentTimer = null;
- }
- }
- if ((self._currentTargetSalvaged) && (elt.timers.length == 0)){
- self._removeHashElement(elt);
- i--;
- }
- }
- for(i = 0, li = locUpdates.length; i < li; i++){
- var update = self._updates[i];
- for(var j = 0, lj = update.length; j < lj; ){
- tmpEntry = update[j];
- if(!tmpEntry) break;
- if (tmpEntry.markedForDeletion) self._removeUpdateFromHash(tmpEntry);
- else j++;
- }
- }
- self._updateHashLocked = false;
- self._currentTarget = null;
- },
- /**
- * <p>
- * The scheduled method will be called every 'interval' seconds.</br>
- * If paused is YES, then it won't be called until it is resumed.<br/>
- * If 'interval' is 0, it will be called every frame, but if so, it recommended to use 'scheduleUpdateForTarget:' instead.<br/>
- * If the callback function is already scheduled, then only the interval parameter will be updated without re-scheduling it again.<br/>
- * repeat let the action be repeated repeat + 1 times, use cc.REPEAT_FOREVER to let the action run continuously<br/>
- * delay is the amount of time the action will wait before it'll start<br/>
- * </p>
- * @param {cc.Class} target
- * @param {function} callback_fn
- * @param {Number} interval
- * @param {Number} repeat
- * @param {Number} delay
- * @param {Boolean} paused
- * @example
- * //register a schedule to scheduler
- * cc.director.getScheduler().scheduleCallbackForTarget(this, function, interval, repeat, delay, !this._isRunning );
- */
- scheduleCallbackForTarget:function (target, callback_fn, interval, repeat, delay, paused) {
- cc.assert(callback_fn, cc._LogInfos.Scheduler_scheduleCallbackForTarget_2);
- cc.assert(target, cc._LogInfos.Scheduler_scheduleCallbackForTarget_3);
- // default arguments
- interval = interval || 0;
- repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
- delay = delay || 0;
- paused = paused || false;
- var self = this, timer;
- var element = self._hashForTimers[target.__instanceId];
- if (!element) {
- // Is this the 1st element ? Then set the pause level to all the callback_fns of this target
- element = new cc.HashTimerEntry(null, target, 0, null, null, paused, null);
- self._arrayForTimers.push(element);
- self._hashForTimers[target.__instanceId] = element;
- }
- if (element.timers == null) {
- element.timers = [];
- } else {
- for (var i = 0; i < element.timers.length; i++) {
- timer = element.timers[i];
- if (callback_fn == timer._callback) {
- cc.log(cc._LogInfos.Scheduler_scheduleCallbackForTarget, timer.getInterval().toFixed(4), interval.toFixed(4));
- timer._interval = interval;
- return;
- }
- }
- }
- timer = new cc.Timer(target, callback_fn, interval, repeat, delay);
- element.timers.push(timer);
- },
- /**
- * <p>
- * Schedules the 'update' callback_fn for a given target with a given priority.<br/>
- * The 'update' callback_fn will be called every frame.<br/>
- * The lower the priority, the earlier it is called.
- * </p>
- * @param {cc.Class} target
- * @param {Number} priority
- * @param {Boolean} paused
- * @example
- * //register this object to scheduler
- * cc.director.getScheduler().scheduleUpdateForTarget(this, priority, !this._isRunning );
- */
- scheduleUpdateForTarget:function (target, priority, paused) {
- if(target === null)
- return;
- var self = this, locUpdates = self._updates;
- var hashElement = self._hashForUpdates[target.__instanceId];
- if (hashElement) {
- // TODO: check if priority has changed!
- hashElement.entry.markedForDeletion = false;
- return;
- }
- // most of the updates are going to be 0, that's way there
- // is an special list for updates with priority 0
- if (priority == 0) {
- self._appendIn(locUpdates[1], target, paused);
- } else if (priority < 0) {
- locUpdates[0] = self._priorityIn(locUpdates[0], target, priority, paused);
- } else {
- // priority > 0
- locUpdates[2] = self._priorityIn(locUpdates[2], target, priority, paused);
- }
- },
- /**
- * <p>
- * Unschedule a callback function for a given target.<br/>
- * If you want to unschedule the "update", use unscheudleUpdateForTarget.
- * </p>
- * @param {cc.Class} target
- * @param {function} callback_fn
- * @example
- * //unschedule a callback of target
- * cc.director.getScheduler().unscheduleCallbackForTarget(function, this);
- */
- unscheduleCallbackForTarget:function (target, callback_fn) {
- // explicity handle nil arguments when removing an object
- if ((target == null) || (callback_fn == null)) {
- return;
- }
- var self = this, element = self._hashForTimers[target.__instanceId];
- if (element) {
- var timers = element.timers;
- for(var i = 0, li = timers.length; i < li; i++){
- var timer = timers[i];
- if (callback_fn == timer._callback) {
- if ((timer == element.currentTimer) && (!element.currentTimerSalvaged)) {
- element.currentTimerSalvaged = true;
- }
- timers.splice(i, 1)
- //update timerIndex in case we are in tick;, looping over the actions
- if (element.timerIndex >= i) {
- element.timerIndex--;
- }
- if (timers.length == 0) {
- if (self._currentTarget == element) {
- self._currentTargetSalvaged = true;
- } else {
- self._removeHashElement(element);
- }
- }
- return;
- }
- }
- }
- },
- /**
- * Unschedules the update callback function for a given target
- * @param {cc.Class} target
- * @example
- * //unschedules the "update" method.
- * cc.director.getScheduler().unscheduleUpdateForTarget(this);
- */
- unscheduleUpdateForTarget:function (target) {
- if (target == null) {
- return;
- }
- var self = this, element = self._hashForUpdates[target.__instanceId];
- if (element != null) {
- if (self._updateHashLocked) {
- element.entry.markedForDeletion = true;
- } else {
- self._removeUpdateFromHash(element.entry);
- }
- }
- },
- /**
- * Unschedules all function callbacks for a given target. This also includes the "update" callback function.
- * @param {cc.Class} target
- */
- unscheduleAllCallbacksForTarget:function (target) {
- //explicit NULL handling
- if (target == null) {
- return;
- }
- var self = this, element = self._hashForTimers[target.__instanceId];
- if (element) {
- var timers = element.timers;
- if ((!element.currentTimerSalvaged) && (timers.indexOf(element.currentTimer) >= 0)) {
- element.currentTimerSalvaged = true;
- }
- timers.length = 0;
- if (self._currentTarget == element) {
- self._currentTargetSalvaged = true;
- } else {
- self._removeHashElement(element);
- }
- }
- // update callback
- self.unscheduleUpdateForTarget(target);
- },
- /**
- * <p>
- * Unschedules all function callbacks from all targets. <br/>
- * You should NEVER call this method, unless you know what you are doing.
- * </p>
- */
- unscheduleAllCallbacks:function () {
- this.unscheduleAllCallbacksWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
- },
- /**
- * <p>
- * Unschedules all function callbacks from all targets with a minimum priority.<br/>
- * You should only call this with kCCPriorityNonSystemMin or higher.
- * </p>
- * @param {Number} minPriority
- */
- unscheduleAllCallbacksWithMinPriority:function (minPriority) {
- // Custom Selectors
- var self = this, locArrayForTimers = self._arrayForTimers, locUpdates = self._updates;
- for(var i = 0, li = locArrayForTimers.length; i < li; i++){
- // element may be removed in unscheduleAllCallbacksForTarget
- self.unscheduleAllCallbacksForTarget(locArrayForTimers[i].target);
- }
- for(var i = 2; i >= 0; i--){
- if((i == 1 && minPriority > 0) || (i == 0 && minPriority >= 0)) continue;
- var updates = locUpdates[i];
- for(var j = 0, lj = updates.length; j < lj; j++){
- self.unscheduleUpdateForTarget(updates[j].target);
- }
- }
- },
- /**
- * <p>
- * Pause all selectors from all targets.<br/>
- * You should NEVER call this method, unless you know what you are doing.
- * </p>
- */
- pauseAllTargets:function () {
- return this.pauseAllTargetsWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
- },
- /**
- * Pause all selectors from all targets with a minimum priority. <br/>
- * You should only call this with kCCPriorityNonSystemMin or higher.
- * @param {Number} minPriority
- */
- pauseAllTargetsWithMinPriority:function (minPriority) {
- var idsWithSelectors = [];
- var self = this, element, locArrayForTimers = self._arrayForTimers, locUpdates = self._updates;
- // Custom Selectors
- for(var i = 0, li = locArrayForTimers.length; i < li; i++){
- element = locArrayForTimers[i];
- if (element) {
- element.paused = true;
- idsWithSelectors.push(element.target);
- }
- }
- for(var i = 0, li = locUpdates.length; i < li; i++){
- var updates = locUpdates[i];
- for(var j = 0, lj = updates.length; j < lj; j++){
- element = updates[j];
- if (element) {
- element.paused = true;
- idsWithSelectors.push(element.target);
- }
- }
- }
- return idsWithSelectors;
- },
- /**
- * Resume selectors on a set of targets.<br/>
- * This can be useful for undoing a call to pauseAllCallbacks.
- * @param {Array} targetsToResume
- */
- resumeTargets:function (targetsToResume) {
- if (!targetsToResume)
- return;
- for (var i = 0; i < targetsToResume.length; i++) {
- this.resumeTarget(targetsToResume[i]);
- }
- },
- /**
- * <p>
- * Pauses the target.<br/>
- * All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.<br/>
- * If the target is not present, nothing happens.
- * </p>
- * @param {cc.Class} target
- */
- pauseTarget:function (target) {
- cc.assert(target, cc._LogInfos.Scheduler_pauseTarget);
- //customer selectors
- var self = this, element = self._hashForTimers[target.__instanceId];
- if (element) {
- element.paused = true;
- }
- //update callback
- var elementUpdate = self._hashForUpdates[target.__instanceId];
- if (elementUpdate) {
- elementUpdate.entry.paused = true;
- }
- },
- /**
- * Resumes the target.<br/>
- * The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again.<br/>
- * If the target is not present, nothing happens.
- * @param {cc.Class} target
- */
- resumeTarget:function (target) {
- cc.assert(target, cc._LogInfos.Scheduler_resumeTarget);
- // custom selectors
- var self = this, element = self._hashForTimers[target.__instanceId];
- if (element) {
- element.paused = false;
- }
- //update callback
- var elementUpdate = self._hashForUpdates[target.__instanceId];
- if (elementUpdate) {
- elementUpdate.entry.paused = false;
- }
- },
- /**
- * Returns whether or not the target is paused
- * @param {cc.Class} target
- * @return {Boolean}
- */
- isTargetPaused:function (target) {
- cc.assert(target, cc._LogInfos.Scheduler_isTargetPaused);
- // Custom selectors
- var element = this._hashForTimers[target.__instanceId];
- if (element) {
- return element.paused;
- }
- return false;
- }
- });
- /**
- * Priority level reserved for system services.
- * @constant
- * @type Number
- */
- cc.Scheduler.PRIORITY_SYSTEM = (-2147483647 - 1);
|