(function(){
"use strict";
/*jshint: validthis true*/
KC3StrategyTabs.overlodger = new KC3StrategyTab("overlodger");
/* Local Variables
------------------------------------------------ */
var
ctx = this,
CONST = {
ratingMagnitude: 5, /* Maximum magnitude */
ratingOffset : +5, /* Base offset magnitude */
ratingHScore : 0.2, /* Half of the score */
materialPeak : function(i){return [ 20000, 20000, 20000, 10000][i];},
consumePeak : function(i){return [ 50, 30, 20, 10][i];},
resourcePeak : function(i){return this[[(i>=4) ? 'consume' : 'material','Peak'].join('')](i%4); },
dayScaleCoef : function(d){
return Math.pow(1+(Math.log(d)/Math.log(7)),2);
},
},
iconData = ["fuel","ammo","steel","bauxite","ibuild","bucket","devmat","screws"],
tDurEnum = {
0:['Time' ,1,'Whole' , 0],
1:['Date' ,1,'Daily' , 1],
2:['Week' ,1,'Weekly' , 3],
4:['Month',1,'Monthly', 15],
8:['Year' ,1,'Yearly' , 60]
},
tShutsuEnum = [
['Any' ,'norq',false],
['Basic','rqbs',false],
['Extra','rqex', true],
['Event','rqev', true],
],
tEventEnum = {
// Key Name Clear AlClr
'0':['All Sortie' ,false,false],
'1':['Clear Stage' ,false,false],
'-1':['Extra Stage' , true,false],
'2':['Clear Event' , true, true],
'-2':['Extra Event' , true, true],
'3':['All Basic Runs',false,false],
'-3':['All Extra Runs', true,false],
},
dataType = [
// Apply grouping
['sortie','pvp' ,'exped' ,'quest' ,'akashi' ,'regen' ,'useitem'],
['crship','critem','dsship','dsitem','remodel','rmditem','lbas' ],
['overall']
],
dataScale = [
1.0, 4.0, 2.5, 2.0, 2.5,25.0, 3.0,
1.0, 2.0, 4.0, 4.0, 4.0, 2.0, 1.0,
],
mapWorldDesc = function(map_id){
var
mapLocal = {
string: ["Naval Base","Southwestern","Northern","Western","Southern","Central"]
.map(function(str){return [str,'Area'].join(' ');}),
value : [ 1,undefined]
},
mapEvent = {
string: ["Winter","Spring","Summer","Fall"],
value : [21,2013]
},
mapDesc;
mapDesc = (function(array_data,array_index){
var
entryLimit = array_data.string.length,
selectedIndex = (array_index - array_data.value[0]);
return [
array_data.string.slice( selectedIndex % entryLimit ).shift(),
array_data.value[1] + parseInt(selectedIndex / entryLimit,10)
].filter(function(str){return str;}).join(' ');
})((map_id < 10) ? mapLocal : mapEvent,map_id);
return [Number(map_id).toDigits(2), mapDesc ].join(': ');
},
mapBuffer = {},
allBuffer = [],
sortieCache = (function(){
function KC3SortieCacheMapInfo(){}
return new KC3SortieCacheMapInfo();
})(),
ledgerCache = (function(){
function KC3LedgerCacheMapInfo(){}
return new KC3LedgerCacheMapInfo();
})(),
lookupBound = [-Infinity,+Infinity],
polarityRating = [0,0],
dateFormatYMDH = "yyyy-mm-dd'T'HH:00:00",
bufferCancel = false,
baseContext;
$.extend(this,Object.freeze(CONST));
/* Page definition
------------------------------------------------ */
KC3StrategyTabs.overlodger.definition = {
tabSelf: KC3StrategyTabs.overlodger,
timeRange: {
/*
0 - whole
1 - day
2 - week
4 - month
8 - year
*/
duration: 1,
/*
true - looks 1 time scale behind
false - looks around current time scale
*/
scope: true,
rate: 1,
/* Convention (defined later)
0 - Standard Convention : 0 AM start of a day, Sunday start of a week
1 - Tanaka Convention : 5 AM start of a quest day, Monday start of a quest week
TODO: not sure to put this or not.
*/
convention: null,
},
sortie: (function(){
function KC3LedgerSortieConfig(){
/*
1 - Basic Sortie
2 - Extra Sortie
3 - Event Sortie
*/
var f,w,m,p;
Object.defineProperties(this,{
Filter: {
get: function( ){return f || 0;},
set: function(x){f = Math.max(0,Math.min( 3,Number(x) || 0)); this.World = null;}
},
World : {
get: function( ){return w || 0;},
set: function(x){w = Math.max(0,Math.min(99,Number(x) || 0)); this.Map = null;}
},
Map : {
get: function( ){return m || 0;},
set: function(x){m = Math.max(0,Math.min( 9,Number(x) || 0)); this.Period= null;}
},
Period: {
get: function( ){return p || 0;},
set: function(x){p = (isFinite(x) && !isNaN(x) && Number(x) || 0);}
}
});
}
return new KC3LedgerSortieConfig();
})(),
filter: {},
dataBuffer: {},
totalBuffer: [],
flatBuffer: [],
sortieBuffer: {},
sortieRange: {},
wholeSortieFilter: (function(){
var
cacheKeyFX = [0,0,0,0,0],
cacheKeyMD = [0,0,0,0,0],
funcac = {},lctx;
var
emptyLedger = ['first','clear','last'].reduce(function(objk,itky){
objk[itky] = NaN; return objk;
},{}),
rangeNullFil = function(dt,id){
return dt || cr[id]; };
function cache(x,f,w,m,p,r) {
// x - ledger id
// f - filter
// w - world id
// m - map id
// p - period code
// r - result
var k = [x,f,w,m,p].map(Number).join('-');
return (typeof funcac[k] !== 'boolean') ? (
(typeof r == 'boolean') ? (funcac[k] = r) : (undefined)
) : (funcac[k]);
}
var retfun = function(key,data,index,array){
var self = this;
if(self != lctx){lctx = self;}
if(this.timeRange.duration){
return true;
} else {
/* Sortie Filter
Filter
0 - all sortie
1 - basic non-EO sortie
map to match: World 1-9, Map 1-4
2 - basic EO-only sortie
map to match: World 1-9, Map 5-9
period match: Monthly
3 - event sortie
map to match: World 10-99, Map 1-9
period match: Eventual State (8 state)
World
0 - does no filtering
Map
0 - does no filtering
EO Period
0 - does no filtering
N - apply on specific month
Event Period
0 - does no filtering
1 - start sortie until clear the map
2 - start sortie until clear the event
3 - only sortie
*/
cacheKeyFX[0] = data.id;
(function(){
cacheKeyFX[1] = this.Filter;
cacheKeyFX[2] = this.World;
cacheKeyFX[3] = this.Map;
cacheKeyFX[4] = this.Period;
}).call(this.sortie);
var
cacheD = cache.apply(null,cacheKeyFX),
sortieD = $.extend([],(key !== 'sortie') ? null : this.sortieBuffer[data.opt]),
rqMapBound = [[ 1, 9],[ 1, 4]],
rqMapMatch = false,
rqBoundMatch = false,
rqMonthMatch = false,
rqEventMatch = false;
if(typeof cacheD == 'boolean') { return cacheD; }
switch(this.sortie.Filter){
case 0:
return true;
case 1:
rqMapMatch = true;
rqBoundMatch = true;
break;
case 2:
rqMapBound[1]= [ 5, 9];
rqMapMatch = true;
rqBoundMatch = true;
rqMonthMatch = true;
break;
case 3:
rqMapBound[0]= [10,99];
rqMapBound[1]= [ 0, 9];
rqMapMatch = (this.sortie.Period % 3 === 0);
rqBoundMatch = true;
rqEventMatch = true;
break;
}
if(rqMapMatch && !sortieD.length) return false;
var
chkBound = (
!rqBoundMatch || (
sortieD.every(function(mapCode,bIdx){ return mapCode ? (0).inside.apply(mapCode,rqMapBound[bIdx]) : true; })
)
),
chkWorld = (
!rqMapMatch || (
(!this.sortie.World || sortieD[0] == this.sortie.World) &&
(!this.sortie.Map || sortieD[1] == this.sortie.Map )
)
),
chkMonth = (
!rqMonthMatch || (
!this.sortie.Period || (function(cDate,mnhour){
var mxhour = Math.hrdInt('floor',(new Date(mnhour * 3600000)).shiftMonth(0,true)/3.6,6,1);
return Math.hrdInt('floor',cDate/3.6,3,1).inside(mnhour,mxhour);
}).call(null,sortieD.time,this.sortie.Period)
)
),
chkEvent = (
!rqEventMatch || (function(ledger_type){
var
rs = false,
cr = [0,Infinity,Infinity,0],
sr = [0,Infinity,Infinity,0],
er = [0,Infinity,Infinity,0],
lt = parseInt(Math.abs (ledger_type),10),
gs = Math.sign(ledger_type),
fi = {w:self.sortie.World,m:self.sortie.Map},
qf = function filter(ary,fun){
switch(Math.sign(ledger_type)){
case 1:
return ary.slice(0,2);
case -1:
return ary.slice(1,3);
default:
return [ary[0],ary[2]];
}
},
rg = function(x,i){switch(Math.sign(ledger_type)){
case 1: return (i <= 1); // F C //
case -1: return (i >= 1); // C L X //
default: return (i % 2 === 0); // F L //
}},
sortieFil = function(x,i){
switch(Math.sign(ledger_type)){
case 1: return x <= this[1];
case -1: return x > this[1];
default: return true;
}
};
cacheKeyMD[0] = cacheKeyFX[0];
cacheKeyMD[1] = cacheKeyFX[1];
cacheKeyMD[4] = cacheKeyFX[4];
try {
var
wa = (fi.w ? [fi.w] : Object.keys(ledgerCache)),
ret = !lt,
wr;
while(!ret && wa.length) {
wr = wa.shift();
var
sw = ledgerCache[wr] || emptyLedger,
cret = false,
sc,rgrt;
cacheKeyMD[2] = Number(wr);
er[0] = sw.first || cr[0];
er[1] = sw.clear || cr[1];
er[2] = sw.last || cr[2];
if(data.id < er[0] || data.id > er[2]) { ret = false; continue; }
switch(lt % 3) {
/* logic :
// 1 -
// 0-0 => World Num iteration (n^2)
// 31-1,31-2,...,31-7,32-1,32-2,...,32-5,etc.
// M-0 => Fixed World iteration (n)
// 31-1,31-2,...,31-7.
// M-N => Single-range iteration (1)
// 2 -
// 0-0 => World Num iteration (n)
// 31-0,32-0,...,etc.
// M-0 => Single-range iteration (1)
// 31-0
// M-N => Reduced Scope iteration (1)
// 3 - only allow sortie ID inside specified range (FC/CLX ranges)
*/
case 1:
var
ma = ((fi.w && fi.m) ? [fi.m] : Object.keys(sw)),
nm;
while(!cret && ma.length) {
nm = ma.shift();
cacheKeyMD[3] = Number(nm);
cacheD = cache.apply(null,cacheKeyMD);
if(typeof cacheD == 'boolean') { cret |= cacheD; continue; }
sc = sw[nm];
sr[0] = sc.first || cr[0];
sr[1] = sc.clear || sc.last || cr[1];
sr[2] = sc.last || cr[2];
switch(Math.sign(ledger_type)){
case 1:
rgrt = (0).inside.apply(data.id,sr.slice(0,2));
break;
case -1:
rgrt = (0).inside.apply(data.id,sr.slice(1,3));
break;
default:
rgrt = (0).inside.call (data.id,sr[0],sr[2]);
break;
}
cret |= cache.apply(null, cacheKeyMD.concat( rgrt ) );
}
break;
case 2:
cacheKeyMD[3] = Number(fi.m);
cacheD = cache.apply(null,cacheKeyMD);
if(typeof cacheD == 'boolean') { cret |= cacheD; continue; }
sc = sw[fi.m];
sr[0] = sc.first || cr[0];
sr[1] = sw.clear || sw.last || cr[1];
sr[2] = sw.last || cr[2];
switch(Math.sign(ledger_type)){
case 1:
rgrt = (0).inside.apply(data.id,sr.slice(0,2));
break;
case -1:
rgrt = (0).inside.apply(data.id,sr.slice(1,3));
break;
default:
rgrt = (0).inside.call (data.id,sr[0],sr[2]);
break;
}
cret |= cache.apply(null, cacheKeyMD.concat( rgrt ) );
break;
default:
cacheKeyMD[3] = Number(fi.m);
cacheD = cache.apply(null,cacheKeyMD);
if(typeof cacheD == 'boolean') { cret |= cacheD; continue; }
sc = sortieCache[wr][fi.m];
sr = sortieCache[wr].rangeE(Math.sign(ledger_type),fi.m);
var sf;
sf = activeSelf.sortieRange[wr+fi.m];
sf = sf.filter(sortieFil,sr[1]);
rgrt = sf.indexOf(data.opt)>=0;
cret |= cache.apply(null, cacheKeyMD.concat( rgrt ) );
break;
}
ret |= cret;
}
return ret;
} catch (e) {
console.error(e); // Accessing non exists ledger data
return false;
}
})(this.sortie.Period)
);
return chkBound && chkWorld && chkMonth && chkEvent;
}
};
return $.extend(retfun,{cache:funcac});
})(),
dataRating: 0,
/* INIT
Prepares all data needed
---------------------------------*/
init :function(){
var self = this;
baseContext = ".tab_overlodger";
dataType.reduce(function(x,y){return x.concat(y);}).forEach(function(filterKey){
self.filter[filterKey] =
(typeof self.filter[filterKey] != 'boolean') || self.filter[filterKey];
self.dataBuffer[filterKey] = [];
});
Object.defineProperties(this.timeRange,{
convention:{
get: function(){ ConfigManager.load(); return Number(ConfigManager.ledger_convention) || 0; },
set: function(value){ ConfigManager.ledger_convention = isFinite(value) && value || 0; ConfigManager.save(); }
},
});
Object.defineProperties(this.sortieBuffer,{
length:{ get: function(){return Object.keys(this).length; } },
});
refreshCurrentBuffer.call(self);
},
/* EXECUTE
Places data onto the interface
---------------------------------*/
execute :function(){
var
self = this,
mdb = localStorage.getObject('maps');
if (typeof mdb == "undefined" || mdb === null) {
return false;
}
// Refresh Map Data Buffer
$.each(mapBuffer,function(k,v){ delete mapBuffer[k]; });
$.each(sortieCache,function(k,v){ delete sortieCache[k]; });
$.each(ledgerCache,function(k,v){ delete ledgerCache[k]; });
mapBuffer[0] = 0;
Object.keys(mdb)
.map(function(mapKey){ return /m(\d+)(\d)/.exec(mapKey); })
.filter(function(mapData){ return mapData; })
.map(function(mapData){ return mapData.slice(1); })
.sort(function(lhs,rhs){
return Array.apply(null,lhs)
.map(function(x,ind){ return Math.sign(lhs[ind] - rhs[ind]); })
.reduce(function(preComp,curComp){ return preComp || curComp; },0);
})
.forEach(function(mapData){
var
wr = mapData[0],
nm = mapData[1],
md = mdb[['m'].concat(mapData).join('')];
mapBuffer[wr] = Math.max(mapBuffer[wr] || 1,nm);
if(md.stat) {
var
worldData = (sortieCache[wr] = $.extend(new KC3SortieCacheMapWorld(),sortieCache[wr])),
wmapData = (worldData[nm] = new KC3SortieCacheMapSpec()),
lwd = (ledgerCache[wr] = $.extend(new KC3LedgerCacheMapWorld(),ledgerCache[wr])),
lmd = (lwd[nm] = new KC3LedgerCacheMapSpec());
wmapData.clear = md.stat.onClear;
worldData.clear = (typeof(worldData.onClear) == 'undefined' ? true : worldData.clear) && md.stat.onClear;
Object.defineProperties(wmapData,{
sortieFirst: { get: function(){ return Number((self.sortieRange[[wr,nm].join('')] || [null]).slice( 0).shift()); } },
sortieLast : { get: function(){ return Number((self.sortieRange[[wr,nm].join('')] || [null]).slice(-1).shift()); } },
ledgerFirst: { get: function(){
var self = this;
return (activeSelf.dataBuffer.sortie.slice().reverse().find(function(x){
return Number(x.opt).inside(self.sortieFirst,self.sortieLast);
})||{id:null}).id;
} },
ledgerClear: { get: function(){
return (activeSelf.dataBuffer.sortie.slice().reverse().find(function(x){ return wmapData.clear == x.opt;
})||{id:null}).id;
} },
ledgerLast : { get: function(){
var self = this;
return (activeSelf.dataBuffer.sortie.slice().reverse().find(function(x){return self.sortieLast && (Number(x.opt) >= self.sortieLast);})||{id:null}).id;
} },
rangeSFCF : { get: function(){return Range(this.sortieFirst || 0,this.sortieClear || this.sortieLast || 0,1,1); } },
rangeSCLX : { get: function(){return Range(this.sortieClear || this.sortieLast || 0,this.sortieLast || 0,0,1); } },
rangeSFLF : { get: function(){return Range(this.sortieFirst || 0,this.sortieLast || 0,0,1); } },
});
Object.defineProperties(worldData,{
sortieFirst: { get: function(){ return this[1].sortieFirst; } },
sortieLast : { get: function(){
var nonEmptySortie = 0;
try { while( this[++nonEmptySortie].sortieLast ) {} } catch (e) {}
try { return this[--nonEmptySortie].sortieLast; } catch (e) { return 0; }
} },
ledgerFirst: { get: function(){ return this[1].ledgerFirst; } },
ledgerClear: { get: function(){
var nonClearLedger = 0;
try { while( this[++nonClearLedger].ledgerClear ) {} } catch (e) { --nonClearLedger; }
try { return this[nonClearLedger].ledgerClear; } catch (e) { return null; }
} },
ledgerLast : { get: function(){
var nonEmptyLedger = 0;
try { while( this[++nonEmptyLedger].ledgerLast ) {} } catch (e) {}
try { return this[--nonEmptyLedger].ledgerLast; } catch (e) { return null; }
} },
0 : { get: function(){ return this; } },
rangeSFCF : { get: function(){return Range(this.sortieFirst || 0,this.sortieClear || this.sortieLast || 0,1,1); } },
rangeSCLX : { get: function(){return Range(this.sortieClear || this.sortieLast || 0,this.sortieLast || 0,0,1); } },
rangeSFLF : { get: function(){return Range(this.sortieFirst || 0,this.sortieLast || 0,0,1); } },
rangeE : { value: function(tp,nm){switch(tp){
case 1: return this.rangeEFCF(nm);
case -1: return this.rangeECLX(nm);
default: return this.rangeEFLF(nm);
}} },
rangeEFCF : { value: function(nm){return Range(this[nm].sortieFirst || 0,this.sortieClear || this.sortieLast || 0,1,1); } },
rangeECLX : { value: function(nm){return Range(this.sortieClear || this.sortieLast || 0,this.sortieLast || 0,0,1); } },
rangeEFLF : { value: function(nm){return Range(this[nm].sortieFirst || 0,this.sortieLast || 0,0,1); } },
langeSFCF : { get: function(){return Range(this.ledgerFirst || 0,this.ledgerClear || this.ledgerLast || 0,1,1); } },
langeSCLX : { get: function(){return Range(this.ledgerClear || this.ledgerLast || 0,this.ledgerLast || 0,0,1); } },
langeSFLF : { get: function(){return Range(this.ledgerFirst || 0,this.ledgerLast || 0,0,1); } },
langeE : { value: function(tp,nm){switch(tp){
case 1: return this.langeEFCF(nm);
case -1: return this.langeECLX(nm);
default: return this.langeEFLF(nm);
}} },
langeEFCF : { value: function(nm){return Range(this[nm].ledgerFirst || 0,this.ledgerClear || this.ledgerLast || 0,1,1); } },
langeECLX : { value: function(nm){return Range(this.ledgerClear || this.ledgerLast || 0,this.ledgerLast || 0,0,1); } },
langeEFLF : { value: function(nm){return Range(this[nm].ledgerFirst || 0,this.ledgerLast || 0,0,1); } },
});
Object.defineProperties(lmd,{
range : {value:function( t ){
return Range.apply(null,[this.first,this.clear || this.last,this.last,0].filter(function(x,i){switch(Number(t)){
case 1: return (i <= 1); // F C //
case 2: return (i >= 1); // C L X //
default: return (i % 2 === 0); // F L //
}}));
}},
inside: {value:function(a,b){ return Number(a) && (0).inside.apply(Number(a),this.range(b));}},
first : {get :function( ){ return wmapData.ledgerFirst; }},
clear : {get :function( ){ return wmapData.ledgerClear; }},
last : {get :function( ){ return wmapData.ledgerLast; }},
});
Object.defineProperties(lwd,{
0 : {get :function( ){ return this; }},
range : {value:function( t ){ return Object.keys(this).reduce(function(tary,nkey){
tary.push(this[nkey].range(t)); return tary; }.bind(this),[]); }},
inside: {value:function(a,b){ return Object.keys(this).some(function(k){
return this[k].inside(a,b); }.bind(this)); }},
find : {value:function(a,b){ return Object.keys(this).find(function(k){
return this[k].inside(a,b); }.bind(this))||null; }},
first : {get :function( ){ return worldData.ledgerFirst; }},
clear : {get :function( ){ return worldData.ledgerClear; }},
last : {get :function( ){ return worldData.ledgerLast; }},
});
}
});
console.log(sortieCache,ledgerCache);
$.each(mapBuffer,function(k,v){
mapBuffer[k] = v = Object.freeze(
Object.defineProperties(new KC3PrimitiveWrapper(),{
toString: { value: String.prototype.toString.bind( Number(k) ? mapWorldDesc(k) : "All worlds" ) },
valueOf : { value: Number.prototype.valueOf.bind( v ) }
})
);
});
// Factory cloning
$.each(tDurEnum,function(k,v){
var fTypeBox = $(".factory .base-radio",baseContext).clone()
.removeClass('base-radio').addClass('filterType');
$("input",fTypeBox).attr('name','range-type').val(parseInt(k,10));
$(".filterText",fTypeBox).text(KC3Meta.term('LodgerTime' + v[2]));
fTypeBox.insertBefore(".filterRangeLen");
});
$.each(iconData,function(k,v){
var
targetBox = $(".factory .lodger-data .materials",baseContext),
mDataBox = $(".factory .material.base-material",baseContext).clone();
$("img",mDataBox).attr('src',['../../../../assets/img/client/',v,'.png'].join(''));
mDataBox
.addClass([v,k < 4 ? 'rsc' : 'csm'].join(' '))
.removeClass('base-material')
.insertBefore($(".clear",targetBox));
});
$.each(self.filter,function(k,v){
var notWholeItem = (k!=='overall');
// Filter Checklist
if(notWholeItem) {
var
fDataBox = $(".factory .filterData",baseContext).clone(),
tgElm = [".filter_data",['DB','MS'][
dataType
.map(function(filterKey,index){ return (filterKey.indexOf(k) >= 0) ? index : undefined; })
.filter(function(udfFlag){ return typeof udfFlag == 'number'; })
.pop()
]].join('');
$('input',fDataBox).prop('checked',v).data('ref',k);
$('.filterText',fDataBox).text(KC3Meta.term('Lodger' + (function trickProperCase(str){
return str.slice(0,1).toUpperCase() + str.slice(1).toLowerCase();
})(k)));
fDataBox.appendTo(tgElm);
}
// Rating Data
var
ratingBox = $(".factory .lodger-data",baseContext).clone();
ratingBox.addClass(k).appendTo($(".lodger-statistics",baseContext)).hide();
});
$.each(tShutsuEnum,function(k,v){
var fTypeBox;
// Sortie Group Filter
fTypeBox = $(".factory .base-radio",baseContext).clone()
.removeClass('base-radio').addClass('filterSType');
$("input",fTypeBox)
.attr('name','sortie-scope').val(k)
.data('addition',v[1]);
$(".filterText",fTypeBox).text(v[0]);
fTypeBox.insertBefore($(".filterMapTypes > .clear",baseContext));
// Sortie Period Filter
if(v[2]) {
fTypeBox = $("").addClass(['period',v[0]].join(''));
fTypeBox.appendTo(".filterMapPeriod");
}
});
// Generate Map World List
$.each(mapBuffer,function(k,v){
var
mapDataBuffer = localStorage.getObject('maps'),
is = Object.defineProperties({},{
wildCard: { get: function(){ return !Number(k); } },
eventMap: { get: function(){ return this.wildCard || k >= 10; } },
basicMap: { get: function(){ return this.wildCard || k < 10; } },
basicEO : { value: function(m){ return this.basicMap && m > 4; } },
lockEO : { get: function(){ return !this.wildCard && this.basicMap && v <= 4; } }
}),
map = Object.defineProperties({},{
count : { get: function(){ return Number(v); } },
clear : { get: function(){
return Object.keys(mapDataBuffer)
.filter(function(MapCode){ return (/m(\d+)(\d)/.exec(MapCode) || "0")[1] == k; })
.map(function(MapCode){ return mapDataBuffer[MapCode].clear; })
.filter(function(MapState){ return MapState; }).length;
} },
total : { get: function(){
return Object.keys(KC3Meta._edges).filter(function(MapCode){
return MapCode.indexOf("World "+k+"-")+1;
}).length;
} },
AC : { get: function(){ return is.eventMap && this.clear >= this.total; } }
});
/* Sortie Option Structure
Mode 0 =>
W[0-0][0-9] M[1-4] P[N/A]
Mode 1 =>
W[0-0][0-9] M[5-9] P[YYYYMM]
YYYYMM : 4-digit year + 2-digit month
Mode 2 =>
W[1-9][0-9] M[1-9] P[0-5]
Period : (up to 10 defineable condition)
- Start of the map
- Start of event
- Cleared the map (GREAT DESTR)
- Cleared the event (FINAL DANSE)
- Post clearing the map (EXTRA STAGE)
- Post clearing the event (EXTRA DANSE)
*/
var elm = $("");
$(elm).attr('value',k).text(v)
.data('length',v)
.data('clr-map', map.clear )
.data('max-map', map.total )
.addClass("sortieWorld")
.addClass(is.basicMap ? "basic" : "")
.addClass(is.eventMap ? "event" : "")
.addClass(is.lockEO ? "no-extra" : "")
.addClass((function(){
try { return !ledgerCache[Number(k)].first; } catch(e) { return true; }
})() ? "no-ledger" : "")
.addClass(map.AC ? "all-clear" : "");
$(elm).appendTo( $(".filterMapWorld select",baseContext) );
});
// Generate Map Num List (y: coz not using it)
Array.apply(null,{length:10}).forEach(function(unused_var,x){
var elm = $("");
$(elm).attr('value',x).text(x || "All").hide()
.addClass("sortieMap")
.addClass(x > 4 ? "extra" : "basic");
$(elm).appendTo( $(".filterMapNum select",baseContext) );
});
// Generate Map Period List (Only applicable to non-basic)
$.each(tEventEnum,function(i,d){
var elm = $("");
$(elm).attr('value',i).text(d[0])
.addClass("sortieMoment")
.addClass(d[1] && "requireClear")
.addClass(d[2] && "requireAllClear");
$(elm).appendTo( $(".filterMapPeriod .periodEvent",baseContext) );
});
// Reinitialize input
$(".filterBoxes .filterType input[type=radio]",baseContext).each(function(i,x){
$(this).prop('checked',JSON.parse($(this).val()) == self.timeRange.duration);
});
$(".filterBoxes .filterScope input[type=radio]",baseContext).each(function(i,x){
$(this).prop('checked',JSON.parse($(this).val()) == self.timeRange.scope);
});
$(".filterBoxes .filterRangeLen input",baseContext).each(function(i,x){
$(this).val(self.timeRange.rate);
});
$(".filterBoxes .filterSType input[type=radio]",baseContext).on('reinit',function(){
$(this).prop('checked',JSON.parse($(this).val()) == self.sortie.Filter);
}).trigger('reinit');
// Input Limiter
$("input",baseContext).each(function(i,x){
$(this).data('prev',$(this).val());
}).on('change',function(e){
// Inverts for every invalid input
var valid;
$(this).data('valid',valid = this.checkValidity());
if(valid) {
$(this).data('prev',$(this).val());
} else {
$(this).val($(this).data('prev'));
}
return valid;
});
// ASYNC EVENT HANDLER
(function AsyncHandler(){
try {
var threads = $.extend([],{
watchThread:function(name){
var ctr = $.Deferred();
var time = Date.now();
ctr.always(function(){
time = Date.now() - time;
}).done(function(){
console.log('Execution',name,'Completed in ',time,'ms');
}).fail(function(){
console.error('Execution',name,'Failed after',time,'ms');
}).progress(function(x){
console.info('Execution',name,'still ongoing after',Date.now() - time,'ms on milestone:',x);
});
this.push(ctr);
return ctr;
},
unwatchThread:function(data){
switch(typeof data){
case 'number':
case 'string': data = this[parseInt(data,10)]; break;
case 'object': break;
default: data = null;
}
var rmv = this.indexOf(data);
if(rmv+1) { this.splice(rmv,1); }
}
});
// ASYNC == Refresh Sortie Data Buffer
(function AsyncSDBuff(thr){
var sbf = Object.keys(this.sortieBuffer);
KC3Database.get_sortie_maps( [ sbf.slice(-1).shift(),Infinity ],
(function(newBuffer){
try {
var oldBufferLen = this.sortieBuffer.length || 0;
console.log("Extending map buffer from",oldBufferLen,"by",newBuffer.length);
$.extend(this.sortieBuffer,newBuffer);
$.each(this.sortieRange,function(k,v){
(self.sortieRange[k] = self.sortieRange[k] || []).splice(0);
});
Object.keys(this.sortieBuffer).forEach(function(sortieID){
var
sortieData = self.sortieBuffer[sortieID],
sortieKey = [sortieData[0],sortieData[1]].join(''),
sortieAry = (self.sortieRange[sortieKey] = (self.sortieRange[sortieKey] || []));
sortieAry.push(sortieID);
});
$.each(this.sortieRange,function(k,v){
var wr = /(\d+)(\d)/.exec(k)[1];
if(!self.sortieRange[wr+'0']){
Object.defineProperty(self.sortieRange,wr+'0',{
get: (function(){
var cache={len:[],data:[]};
function getlength(){
var c = 0;
for(var kk in self.sortieRange){ c += /(\d+)(\d)/.exec(kk)[1] == wr; }
return c;
}
function getwhole(){
if(
cache.len.length == getlength() &&
cache.len.every(function(itmlen,idx){return itmlen == self.sortieRange[wr+(idx+1)].length;})
) {
} else {
cache.len.splice(0);
cache.data.splice(0);
for(var kk in self.sortieRange){
var rg = /(\d+)(\d)/.exec(kk);
var ii = rg[2] - 1;
if(rg[1] == wr)
cache.len[ii] = [].push.apply(cache.data,self.sortieRange[kk]);
}
}
return cache.data;
}
$.extend(getwhole,{cache:cache});
return getwhole;
}).call(self.sortieRange),
});
}
});
thr.resolve(newBuffer.length);
} catch (e) {
thr.reject(e);
}
}).bind(this)
);
}).call(this,threads.watchThread('SDBuff'));
// ASYNC == Specify Boundary
(function AsyncBound(thr){
var
maximumLookout = Date.now(),
dateTimeInputs = $("input[type=datetime-local]",baseContext),
scaleRadioInput = $(".filterType input[type=radio]",baseContext);
dateTimeInputs.prop('disabled',true);
scaleRadioInput
.parent().css('visibility','hidden').end()
.prop('disabled',true);
KC3Database.get_lodger_bound(function(furthestBound){
var minDate = new (Date.bind.apply(Date,[null].concat([furthestBound].filter(function(data){
return (
(typeof data == 'number' || (typeof data == 'object' && data instanceof Number && Number(data))) &&
isFinite(data) && !isNaN(data)
);
}))))();
try {
dateTimeInputs.each(function(idx,elm){
$(elm)
.attr('min',minDate.format(dateFormatYMDH))
.attr('step',3600);
if(elm.name == 'range-source'){
$(elm).prop('disabled',false).val(dateFormat(maximumLookout,dateFormatYMDH)).trigger('change');
} else {
$(elm).data('disable-lock',true);
}
});
var totalDays = Math.hrdInt('floor',(maximumLookout - minDate)/86.4,6,1);
scaleRadioInput.each(function(idx,elm){
var
requiredDays = tDurEnum[parseInt($(this).val(),10)][3],
satisfied = totalDays >= requiredDays;
$(elm)
.data('disable-lock',!satisfied)
.parent().css('visibility',satisfied ? 'visible' : 'hidden').end();
});
// Configure EO Period
(function(){
var dr = [minDate,maximumLookout].map(function(dt){
return new Date(Math.qckInt('floor',dt/3.6,6)*3.6);
}), eb;
eb = $("");
eb.text( "All EO" );
eb.val ( 0 );
eb.appendTo(".periodExtra");
while(dr[0] < dr[1]) {
eb = $("");
eb.text( dr[0].format("mmmm yyyy") );
eb.val ( Math.hrdInt('floor',Date.parse(dr[0].format("mmmm yyyy"))/3.6,6,1) - (new Date()).getTimezoneOffset()/60 );
eb.appendTo(".periodExtra");
dr[0].shiftMonth(0,true);
}
}).call(this);
thr.resolve(maximumLookout - minDate);
} catch (e) {
thr.reject(e);
}
});
}).call(this,threads.watchThread('SortieBound'));
// ASYNC == Fetch Available Data
(function AsyncFetch(thr){
// totalBuffer is ordered by id desc
var latestItem = this.totalBuffer[0] || {};
// Fetch new buffer
KC3Database.get_lodger_data(
Range(latestItem.id || 0,Infinity,0,1),
function(newBuffer){
// Process here
var newTotalBuffer = [];
try {
for(var index in newBuffer) { // tested and faster than those forEach :joy:
var
newData = newBuffer[index],
givenType = /([a-z]+)(\d*)/.exec(newData.type),
givenAry = self.dataBuffer[givenType[1]],
newItem = new KC3LedgerBuffer(
newData.id,
newData.hour,
newData.data,
givenType[1],
dataScale[Object.keys(self.dataBuffer).indexOf(givenType[1])],
givenType[2]
);
//[givenAry,self.totalBuffer].forEach(function(bufferArray){
// if(bufferArray.every(function(buffer){
// return !buffer.equals(newItem);
// }))
// bufferArray.push(newItem);
//});
givenAry.push(newItem);
newTotalBuffer.push(newItem);
}
[].unshift.apply(self.totalBuffer,newTotalBuffer);
} catch (e) {
console.error(e.stack);
} finally {
bufferCancel = false;
thr.resolve(newBuffer.length);
}
}
);
}).call(this,threads.watchThread('CollectBuffer'));
$.when.apply(null,threads).then(function(){
console.info.apply(console,["Async Completed"].concat([].slice.apply(arguments)));
// Finalize
refreshCurrentBuffer.call(self);
$(".filterRefresh",baseContext).trigger('click');
},function(e){
console.error("Thread Execution Failed",e);
});
} catch (e) {
throw e;
}
}).call(this);
/* LISTENER CONFIGURATION */
// Initialize Maximum on Date Input Fields
$("input[type=datetime-local]",baseContext)
.attr('max',(new Date()).format(dateFormatYMDH))
.on('change',function(){
if(this.name == 'range-source' && $(this).data('valid')){
$('input[name=range-maximum]',baseContext).val(
calculateMaximumBacklookup(self.timeRange,this.valueAsNumber).format(dateFormatYMDH,true)
);
}
});
// Time Range Listener
$(".filterType input[type=radio]",baseContext)
.on('click',function(){
var oldDur = self.timeRange.duration;
self.timeRange.duration = JSON.parse($(this).val());
switch(self.timeRange.duration) {
case 0:
if(oldDur != self.timeRange.duration) {
$('button,input,select,option',baseContext).prop('disabled',true);
self.resetBuffer();
}
break;
case 1:
$(".filterRangeLen input").prop('max',364);
break;
case 2:
$(".filterRangeLen input").prop('max',52);
break;
case 4:
$(".filterRangeLen input").prop('max',11);
break;
case 8:
$(".filterRangeLen input").prop('max',1);
break;
}
self.sortie.Filter = !self.timeRange.duration && self.sortie.Filter;
$(".filterBoxes .filterSType input[type=radio]",baseContext).trigger('reinit');
$(".filterRangeLen input",baseContext)
.val(Math.min($(".filterRangeLen input",baseContext).prop('max'),$(".filterRangeLen input").val()))
.trigger('change');
$(".filterDate input",baseContext).trigger('change');
$("input:not([readonly]),button:not(.filterRefresh)",$(".filter_reset",baseContext))
.data('disable-lock',!self.timeRange.duration);
$(".filterRefresh",baseContext).trigger('click');
});
$(".filterRangeLen input[type=number]",baseContext)
.on('input keyup',function(){
$(this).trigger('change');
self.timeRange.rate = JSON.parse($(this).val());
$(".filterDate input",baseContext).trigger('change');
});
// Time Scope Listener
$(".filterScope input[type=radio]",baseContext)
.on('click',function(){
self.timeRange.scope = JSON.parse($(this).val());
$(".filterDate input",baseContext).trigger('change');
$(".filterRefresh",baseContext).trigger('click');
});
// Data Filter Handler
$(".filterData input[type=checkbox]",baseContext)
.on('click',function(){
self.filter[$(this).data('ref')] = $(this).prop('checked');
refreshCurrentBuffer.call(self);
self.refreshList();
});
// Time Step / Button Handler
$(".filterNavigate",baseContext)
.on('click',function(){
var
targetItem = $("input[name=range-source][type=datetime-local]",baseContext),
valBound = ['min','max'].map(function(prop){ return new Date(targetItem.prop(prop)); });
var nextStep;
if(self.timeRange.scope) {
var stepLength = parseInt($(this).data('step')) * targetItem.prop('step') * 1000;
nextStep = targetItem.prop('valueAsNumber') + stepLength;
} else {
var
durDat= tDurEnum[self.timeRange.duration],
cDate = new Date(targetItem.prop('valueAsNumber')),
args = [parseInt($(this).data('step')),false,null];
if(durDat[0] == 'Week') {
args.unshift('Sunday',0);
}
cDate[['shift',durDat[0]].join('')].apply(cDate,args);
nextStep = cDate.shiftDate(0,1,{Hours:-1}).getTime();
}
nextStep = Math.max(valBound[0],Math.min(valBound[1],nextStep));
var newVal = dateFormat(nextStep,dateFormatYMDH,true);
if(newVal !== targetItem.val()) {
targetItem.val(newVal).trigger('change');
$(".filterRefresh",baseContext).trigger('click');
}
});
// Sortie Grouping Handler
$(".filterSType input[type=radio]",baseContext)
.on('click',function(){
var allClass = tShutsuEnum.map(function(enm){return enm[1];})
.filter(function(cls){return cls;})
.join(' ');
self.sortie.Filter = $(this).val();
$(".filterRefresh").trigger('refresh');
$(this).parent().parent().parent()
.removeClass(allClass).addClass($(this).data('addition'))
.removeClass('crok crng acok acng');
/*
var
invokeEvent = (self.sortie.Filter == 3),
requireEO = (self.sortie.Filter == 2);
$("option.sortieWorld",baseContext).each(function(idx,elm){
$(elm)[ (
!(requireEO && $(elm).hasClass('no-extra')) &&
!($(elm).hasClass('event')^invokeEvent)
)?'show':'hide' ]();
});
/* */
$(".filterRefresh",baseContext).trigger('click');
});
// Sortie World Filter Handler
$(".filterMapWorld select",baseContext).on('change',function(){
var
mapSel = $(this.selectedOptions),
mapClr = mapSel.data('clr-map'),
mapMax = mapSel.data('max-map'),
mapLen = mapSel.data('length'),
allClearFlag = mapSel.is(".all-clear"),
invokeEvent = (self.sortie.Filter == 3),
lockExtra = (self.sortie.Filter == 1);
self.sortie.World = $(this).val();
$(this).parent().parent().parent()
.removeClass('crok crng acok acng').addClass(allClearFlag ? 'acok' : 'acng');
$(".filterMapNum",baseContext)
.find('select')
.prop('selectedIndex',0)
.prop('disabled',!$(this).prop('selectedIndex'))
.data('disable-lock',!$(this).prop('selectedIndex'))
.addClass('map-clear')
.end()
.find('option').each(function(idx,elm){
$(elm).removeClass('map-clear')
.addClass(idx<=mapClr ? 'map-clear' : '')
[(idx<=Math.min(mapLen,mapMax))?'show':'hide']();
})
.end();
$(".filterRefresh").trigger('refresh');
});
// Sortie Specific Map Filter Handler
$(".filterMapNum select",baseContext).on('change',function(){
var clearFlag = $(this.selectedOptions).is(".map-clear");
$(this).removeClass('map-clear')
.addClass(clearFlag ? "map-clear" : "")
.parent().parent().parent()
.removeClass('crok crng')
.addClass(clearFlag ? 'crok' : 'crng');
self.sortie.Map = $(this).val();
$(".filterRefresh").trigger('refresh');
});
// Sortie Period Filter Handler
$(".filterMapPeriod select",baseContext).on('change',function(){
self.sortie.Period = $(this).val();
});
// Filter Group Handler
$(".filterGroup",baseContext).on('refresh',function(event){
var
elm = this,
state = Object.keys(tDurEnum).every(function(durKey){
var
k = ['duration',durKey].join(''),
d = self.timeRange.duration,
c = $(elm).data(k);
try {
c = JSON.parse(c);
return !((d == durKey) ^ c);
} catch (e) {
return true;
}
});
$(this)[state ? 'show' : 'hide']();
});
// Data Refresh Handler
$(".filterRefresh",baseContext)
.on('enable-flag',function(){
bufferCancel = false;
$("button,input,select,option",baseContext).each(function(idx,elm){
$(elm).prop('disabled',$(elm).data('disable-lock') || false);
});
})
.on('refresh',function(){
$(".filterMapWorld select",baseContext)
.prop('disabled',!self.sortie.Filter).data('disable-lock',!self.sortie.Filter)
.val(self.sortie.World);
$(".filterMapNum select",baseContext)
.prop('disabled',!self.sortie.World).data('disable-lock',!self.sortie.World)
.val(self.sortie.Map);
$(".filterMapPeriod select",baseContext)
.prop('disabled',self.sortie.Filter<=1).data('disable-lock',self.sortie.Filter<=1)
.each(function(i,elm){
$(elm).val(self.sortie.Period);
$(elm).prop('selectedIndex',$(elm).prop('selectedIndex')>-1 ? $(elm).prop('selectedIndex') : 0);
});
})
.on('click',function(){
$('button,input,select,option',baseContext).prop('disabled',true);
$(".loading").show();
var time = Date.now();
self.resetBuffer();
$(".filterGroup",baseContext).trigger('refresh');
$(this).trigger('refresh');
time = Date.now() - time;
$(".loading").hide();
//console.info("Refresh done in",time,"msec");
});
},
refreshList :function(){
var
self = this,
timeRangeAry = [lookupDays()];
$(".lodger-header",baseContext).text(
[1,2].reduce(function(str,key,ind){
return str.replace('%DATE' + key,dateFormat(lookupBound[ind] * 3600000,'ddd yyyy-mm-dd HH:' + ['00','59'][ind]));
},KC3Meta.term('LodgerLabel'))
);
$.each(self.dataBuffer,function(k,v){
var wholeData = (k==='overall');
if((!self.filter[k] && !wholeData) || (
(Range(1,2).inside(self.sortie.Filter) || (self.sortie.Filter == 3 && self.sortie.Period % 3 === 0)) && (k!=='sortie')
)) {
$(".lodger-data." + k,$(".lodger-statistics",baseContext)).hide(100);
return true;
}
var
availData = v.filter(function(buff){return self.flatBuffer.indexOf(buff) >= 0;}),
baseName = $(".filterData",baseContext).filter(function(i,x){
return $("input",x).data('ref') == k;
}).find(".filterText").text() || KC3Meta.term('Lodger'+k),
matrSum = [0,0,0,0,0,0,0,0],
rating = {
box : $(".lodger-data." + k,".lodger-statistics"),
val : availData.length ? calculateRating.apply(null,timeRangeAry.concat(availData)) : NaN
};
if(wholeData){
matrSum = self.flatBuffer.reduce(function(pre,cur){
return pre.map(function(cval,cind){ return cval + Number(cur.matr[cind]); });
},matrSum);
rating.val = self.dataRating;
} else if(isNaN(rating.val)){
rating.val = CONST.ratingOffset;
} else {
matrSum = availData.reduce(function(pre,cur){
return pre.map(function(cval,cind){ return cval + cur.matr[cind]; });
},matrSum);
}
rating.OK = rating.val / 2;
rating.NG = CONST.ratingMagnitude - rating.OK;
rating.NG *= 100/CONST.ratingMagnitude;
rating.OK *= 100/CONST.ratingMagnitude;
rating.excess = Math.max(rating.NG,rating.OK)>100;
var
normalizedMagnitude = Math.max(-CONST.ratingMagnitude,
Math.min(CONST.ratingMagnitude,rating.val - CONST.ratingOffset)
),
normalizedRating = Math.qckInt('ceil',normalizedMagnitude,2,false,true),
ratingCond = (rating.val < CONST.ratingOffset) ? 'NG' : 'OK',
texifyRating = Math.qckInt('ceil',Math.abs(normalizedMagnitude),0);
rating.box
.find('.bar.NG,.bar.OK').each(function(idx,elm){
// For every NG/OK bar, put their bar value
// Don't forget to mark excessive values
var selfRating = rating[elm.className.split(' ')[1]];
$(elm).css('width',Math.min(selfRating,100) + '%')
.removeClass('over')
.addClass(selfRating > 100 ? 'over' : '');
}).end()
.find('.info')
.attr('title',KC3Meta.term(['LodgeRating',ratingCond,texifyRating].join('')))
.find('.rating')
.removeClass('NG OK over')
.addClass((rating.val != CONST.ratingOffset) ? (ratingCond) : '')
.addClass(rating.excess ? 'over' : '')
.data('val',normalizedMagnitude + CONST.ratingOffset)
.text((normalizedRating + CONST.ratingOffset).toFixed(2))
.end()
.find('.type').text(baseName).end()
.end()
.find('.materials .material').each(function(idx,elm){
var
matrVal = matrSum[idx],
matrScl = (dataScale[Object.keys(self.dataBuffer).indexOf( k )] || 0) / (ctx.dayScaleCoef( timeRangeAry[0] )),
matrOvr = Math.abs(matrVal) > 99999,
matrExc = Math.abs(matrVal * matrScl && !matrOvr) > ctx.resourcePeak(idx),
matrHlf = Math.abs(matrVal * matrScl && !(matrOvr || matrExc)) > (ctx.resourcePeak(idx) * ctx.ratingHScore);
$(elm).removeClass('half full over OK NG')
.addClass((matrOvr && 'over') || (matrExc && 'full') || (matrHlf && 'half') || "")
.addClass(Math.abs(parseInt(matrVal,10)) > 0 ? (Math.sign(matrVal) >= 0 ? 'OK' : 'NG') : '')
.attr('data-actual-value',matrVal);
$("span",elm).text(matrOvr ? matrVal.shorten() : matrVal);
}).end()
.show(100);
}.bind(ctx));
$(".filterRefresh",baseContext).trigger('enable-flag');
},
resetBuffer :function(){
var self = this;
if(bufferCancel){
console.error("Rejected attempt to modify the locked buffer, please wait gently.");
return false;
}
lookupBound = Array.apply(null,$('input[type=datetime-local]',baseContext)
.map(function(i,x){return x.valueAsNumber;})).reverse();
bufferCancel = true;
switch(true){
case(!this.timeRange.duration):
lookupBound[0] = -Infinity;
lookupBound[1] = +Infinity;
break;
case(!this.timeRange.scope):
var
args = [this.timeRange.rate],
next = new Date(lookupBound[0]);
if(this.timeRange.duration & 2)
args.unshift(null,1);
lookupBound[1] = next[['shift',tDurEnum[this.timeRange.duration][0]].join('')]
.apply(next,args)
.getTime() - 1;
break;
default:
break;
}
var GMT = (new Date()).getTimezoneOffset() * 60000;
// Convert UnixTimestamp into UnixHour
lookupBound.push.apply(lookupBound,
lookupBound.splice(0)
.map(function(x,i){ return Math.hrdInt('floor',(x + GMT)/3.6,6,1); }
)
);
var dupeBuffer = this.totalBuffer.slice();
var oldCmp = lookupBound.slice();
var lookupCheck = (function(){
var rangeCache = Range.apply(null,oldCmp);
function fnLookupCheck(buf,i){return rangeCache.inside(buf.hour); }
return fnLookupCheck;
}).call(this);
for(var i in lookupBound) {
dupeBuffer.reverse();
lookupBound[i] = (dupeBuffer.find( lookupCheck ) || {hour:lookupBound[i]}).hour;
}
refreshCurrentBuffer.call(this);
this.refreshList();
}
};
/* Local/Inner class KC3Buffer
----------------------------------------------- */
var
KC3LedgerBuffer = (function(){
function KC3LedgerBuffer(id,hour,matr,kind,mult,optional) {
/*jshint: validthis true*/
if(this instanceof KC3LedgerBuffer){
if(!Range(4,6).inside(arguments.length)){
var
kn = ['id','hour','matr','kind','mult','optional','overflow'],
at = [].map.call(arguments,function(v,i){
var type = typeof(v);
switch(type){
case('number'):
type = (parseInt(v,10) == v) ? 'int' : 'float';
break;
case('string'):
type = (v.length != 1) ? 'string' : 'char';
break;
case('object'):
type = (v.constructor.name || "(anonymous function)");
type = type + (typeof v.length == 'number' ? JSON.stringify([v.length]) : '');
break;
}
return [type,kn[i>6 ? 6 : i]].join(' ');
}).slice(0,7);
throw new RangeError([
"Constructor form:\t KC3LodgerBuffer(int id,int hour,int[8] matr,string kind[,float mult=1[,variant optional]])",
"Requested form:\t KC3LodgerBuffer("+at+")"
].join('\n'));
}else{
matr = matr.map(function(x){return parseInt(x,10) || 0;});
mult = Math.max(0,(!parseFloat(mult) || isNaN(mult) || !isFinite(mult) || Math.sign(mult) < 0) ? 1 : mult);
Object.defineProperties(this,{
id :{value:id },
hour:{value:hour },
matr:{value:matr },
kind:{value:kind },
mult:{value:mult },
opt :{value:optional},
toString:{value:this.toString.bind(this,this)},
equals :{value:this.equals .bind(this,this)},
rating :{get: this.rating .bind(this,this)},
bRating :{get: this.bRating .bind(this,this)},
});
Object.seal(this);
}
}else{
throw new TypeError('Requires instantiation from KC3Buffer class!');
}
}
Object.defineProperties(KC3LedgerBuffer.prototype,{
toString: { value: Function.prototype.apply.bind(function(){
var self = this;
if(typeof self == 'undefined' || self == KC3LodgerBuffer.prototype) {
return "KC3Buffer {Prototype}";
} else {
return [
"KC3Buffer #",self.id,
["(",self.opt,")"].filter(function(){return typeof self.opt != 'undefined';}).join(''),
" @",self.hour,
" [",self.matr.join(),"]"
].join('');
}
}) },
equals : { value: Function.prototype.apply.bind(function(other){
var self = this;
return [self,other].reduce(function(precVal,varData){
return precVal && (typeof varData == 'object') && (varData instanceof KC3LodgerBuffer);
},true) && (Object.keys(self)).map(function(key){
var pt = self[key];
switch(typeof pt){
case 'object':
return JSON.stringify(self[key]) == JSON.stringify(other[key]);
default:
return self[key] == other[key];
}
});
}) },
bRating : { value: Function.prototype.apply.bind(function(){
var
self = this,
halfRate = 1 / Math.log2(1/CONST.ratingHScore),
aRating = this.matr.reduce(function(tRate,cMat,mInd){
return tRate + Math.min(2,
Math.pow( Math.abs(cMat * self.mult / CONST.resourcePeak(mInd) ), halfRate )
)*Math.sign(cMat);
},0)/8;
return aRating;
}) },
rating : { value: Function.prototype.apply.bind(function(){
return Math.min(Math.abs(this.bRating),1) * Math.sign(this.bRating) * 1.25 * CONST.ratingMagnitude + CONST.ratingOffset;
}) }
});
KC3LedgerBuffer.toString = String.prototype.toString.bind("function KC3Buffer(id,hour,material[,coefficient[,optional]])");
Object.defineProperty(KC3LedgerBuffer,'toString',{});
return KC3LedgerBuffer;
})(),
KC3PrimitiveWrapper = (function(){
function KC3PrimitiveWrapper(){}
Object.defineProperties( KC3PrimitiveWrapper, {
name: { value: "KC3 Wrapper" },
toString: { value: String.prototype.toString.bind("function Primitive Wrapper (){}") },
});
return KC3PrimitiveWrapper;
})(),
KC3SortieCacheMapWorld = (function(){ return function KC3SortieCacheMapWorld(){}; })(),
KC3SortieCacheMapSpec = (function(){ return function KC3SortieCacheMapSpec (){}; })(),
KC3LedgerCacheMapWorld = (function(){ return function KC3LedgerCacheMapWorld(){}; })(),
KC3LedgerCacheMapSpec = (function(){ return function KC3LedgerCacheMapSpec (){}; })();
/* Local Function
----------------------------------------------- */
function refreshCurrentBuffer(){
// This is a private function for the lodger tab itself though.
/*jshint validthis: true*/
if(this !== activeTab.definition) {
return false;
}
var
self = this,
fun = self.wholeSortieFilter;
var d,i,a,t,pr;
allBuffer.splice(0);
t = Date.now();
pr = (self.sortie.Filter == 3 && self.sortie.World) ? sortieCache[self.sortie.World].langeE(Math.sign(self.sortie.Period),self.sortie.Map) : Range();
for(i=0,a=this.totalBuffer;i 10000) {
// console.error("Operation timeout after executing",i+1,"data");
// break;
//}
d = a[i];
if( self.filter[d.kind] &&
Range.apply(null,lookupBound).inside(d.hour) &&
(self.sortie.World <= 10 || pr.inside(d.id)) &&
((typeof fun !== 'function') || fun.call(self,d.kind,d,i,a))
)
allBuffer.push(d);
if(i%500==499 && (Date.now - t > 300)) {
console.info("Milestone",i+1,"check after",Date.now() - t,"msec");
}
}
this.flatBuffer = Object.freeze(allBuffer.sort(function(x,y){return x.hour - y.hour;}).slice(0));
this.dataRating = calculateRating.apply(null,[lookupDays()].concat(allBuffer));
return true;
}
function calculateMaximumBacklookup(timeRange,givenDate){
// Initialize Required Variables
var
targetDate = new Date(givenDate),
durData = tDurEnum[timeRange.duration],
durKey = durData[0],
rCoef = durData[1];
timeRange = JSON.parse(JSON.stringify(timeRange));
/* How backlookup works:
Scope/Duration
LookBHD/Day - starts from specified date for N day backwards
bhd(2015-12-12 04:00,1) --> (2015-12-11 04:00)
bhd(2015-12-12 04:00,2) --> (2015-12-10 04:00)
LookARD/Day - looks 24*N hours around current day
ard(2015-12-12 04:00,1) --> (2015-12-12 00:00)
ard(2015-12-12 23:00,1) --> (2015-12-12 00:00)
ard(2015-12-12 23:00,2) --> (2015-12-11 00:00)
ard(2015-12-12 23:00,4) --> (2015-12-09 00:00)
Any/Week - 7x effectivity of Any/Day (1 week, 2 weeks, etc.)
Any/Whole - starts from specified date till nullity
In concept:
LookBHD/Look Behind - looks out the exact given duration from specified time
> Day : looks up 24 hours
> Week : looks up 168 hours
> Month: looks up the same date of previous month (leap year is exception!)
> Year : looks up the same month of previous year
LookARD/Look Around - looks out from the beginning of the