<commit_before>/* RemodelDb.js

   Everything related to ship remodels

*/
(function() {
    "use strict";

    window.RemodelDb = {
        _db: null,
        // NOTE: masterData on init is optional
        // as long as pre-processed data has been saved in localStorage
        init: function(masterData) {
            // load stored db if any
            if (typeof localStorage.remodelDb !== 'undefined')
                this._db = JSON.parse( localStorage.remodelDb );

            if (masterData && this.requireUpdate(masterData)) {
                try {
                    var db = this.mkDb(masterData);
                    localStorage.remodelDb = JSON.stringify(db);
                    this._db = db;
                    console.log("RemodelDb: database updated");
                } catch (e) {
                    console.error("RemodelDb:",e);
                }
            } else {
                console.log("RemodelDb: no update required");
            }

            if (! this._db) {
                console.warn("RemodelDb: database unavailable, need to re-initialize with master data");
            }
        },
        // compare master data against _db (could be null)
        // if this function returns true, then we need to perform a db update
        requireUpdate: function(masterData) {
            if (!this._db)
                return true;
            if (this._db.shipCount !== masterData.api_mst_ship.length ||
                this._db.upgradeCount !== masterData.api_mst_shipupgrade.length)
                return true;
            return false;
        },
        // according to the following doc:
        // https://github.com/andanteyk/ElectronicObserver/blob/d28e1d904521ea60b25c15010d06f130ae36dc62/ElectronicObserver/Other/Information/kcmemo.md#%E6%94%B9%E8%A3%85%E6%99%82%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E9%96%8B%E7%99%BA%E8%B3%87%E6%9D%90
        calcDevMat: function(steel) {
            return (steel < 4500) ? 0
                : ( steel < 5500) ? 10
                : ( steel < 6500) ? 15
                : 20;
        },
        mkDb: function(masterData) {
            var self = this;
            // step 1: collect remodel info
            /*
               remodelInfo[ shipId  ] =
                 { ship_id_from: Int
                 , ship_id_to: Int
                 , level: Int
                 , steel: Int
                 , ammo: Int
                 , catapult: Int
                 , blueprint: Int
                 , devmat: Int
                 }
             */
            var remodelInfo = {};
            // all ship Ids (except abyssals)
            var shipIds = [];
            // all ship Ids that appears in x.aftershipid
            // stored as a set.
            var shipDstIds = {};

            $.each(masterData.api_mst_ship, function(i,x){
                if (x.api_id >= 500)
                    return;
                shipIds.push( x.api_id );
                var shipId_to = parseInt(x.api_aftershipid,10) || 0;
                if (shipId_to === 0)
                    return;

                shipDstIds[shipId_to] = true;
                var remodel =
                    { ship_id_from: x.api_id,
                      ship_id_to: shipId_to,
                      level: x.api_afterlv,
                      // yes, this is steel
                      steel: x.api_afterfuel,
                      ammo: x.api_afterbull,
                      // these fields are unknown for now
                      catapult: 0,
                      blueprint: 0,
                      devmat: 0
                    };

                remodel.devmat = self.calcDevMat(remodel.steel);
                remodelInfo[x.api_id] = remodel;

            });

            function id2name(id) {
                return KC3Meta.shipName( KC3Master.ship(id).api_name );
            }

            $.each(masterData.api_mst_shipupgrade, function(i,x) {
                if (x.api_current_ship_id === 0)
                    return;
                var remodel = remodelInfo[x.api_current_ship_id];
                console.assert(
                    remodel.ship_id_to === x.api_id,
                    "data inconsistent:"+x.api_id);
                remodel.catapult = x.api_catapult_count;
                remodel.blueprint = x.api_drawing_count;
                remodelInfo[x.api_current_ship_id] = remodel;
            });

            // step 2: get all original ship ids
            // an original ship can only remodel into other ships
            // but is never a remodel target
            var originalShipIds = [];
            $.each( shipIds, function(i,x) {
                if (!shipDstIds[x])
                    originalShipIds.push(x);
            });

            /*
               remodelGroups[ originalShipId  ] =
                 { origin: shipId
                 // circular-remodels are all considered final forms
                 , final_forms: [shipId]
                 // all forms of one kanmusu
                 , group: [shipId]
                 }
             */
            var remodelGroups = {};
            // reverse from shipId to orginal
            var originOf = {};

            $.each( originalShipIds, function(i, x) {
                var group = [x];
                var cur = x;
                while (typeof remodelInfo[cur] !== 'undefined' &&
                       group.indexOf(remodelInfo[cur].ship_id_to) === -1) {
                    cur = remodelInfo[cur].ship_id_to;
                    group.push( cur );
                }

                cur = group[group.length-1];
                var final_forms = [ cur ];
                while (typeof remodelInfo[cur] !== 'undefined' &&
                       final_forms.indexOf(remodelInfo[cur].ship_id_to) === -1) {
                    cur = remodelInfo[cur].ship_id_to;
                    final_forms.push( cur );
                }

                remodelGroups[x] =
                    { origin: x,
                      group: group,
                      final_forms: final_forms,
                    };

                $.each(group, function(j,y) {
                    originOf[y] = x;
                });
            });

            return { remodelInfo: remodelInfo,
                     remodelGroups: remodelGroups,
                     originOf: originOf,
                     // this 2 numbers are "checksum"s, if master data does not change
                     // on this 2 numbers, we don't recompute
                     shipCount: masterData.api_mst_ship.length,
                     upgradeCount: masterData.api_mst_shipupgrade.length
                   };
        },
        // return root ship in this ships's remodel chain
        originOf: function(shipId) {
            return this._db.originOf[shipId];
        },
        // return remodel info, including cost and required level
        remodelInfo: function(shipId) {
            return this._db.remodelInfo[shipId];
        },
        // return all ships in ship's remodel chain
        // in other words, all ships that considered "same" kanmusu
        remodelGroup: function(shipId) {
            var oid = this.originOf(shipId);
            return oid?this._db.remodelGroups[oid].group:false;
        },
        // get final forms / remodels of one ship,
        // cyclic remodels are all considered final
        finalForms: function(shipId) {
            var oid = this.originOf(shipId);
            return oid?this._db.remodelGroups[oid].final_forms:false;
        },
        // check if one ship is in her final form
        isFinalForm: function(shipId) {
            var ff = this.finalForms(shipId);
            return ff ? ff.indexOf(shipId) !== -1 : false;
        },
        // return ship id of the previous form.
        // if the ship is already in original form, "false" will be returned
        // this relation is not circular - tracing from final form using "previousForm"
        // will not result in infinite loop.
        previousForm: function(shipId) {
            if (shipId === this.originOf(shipId))
                return false;
            var group = this.remodelGroup(shipId)
            var curInd = group.indexOf(shipId);
            console.assert(
                curInd > 0, 
                "previousForm: querying on original form?" );
            return group[curInd-1];
        }
    };
})();
<commit_msg>build fix<commit_after>/* RemodelDb.js

   Everything related to ship remodels

*/
(function() {
    "use strict";

    window.RemodelDb = {
        _db: null,
        // NOTE: masterData on init is optional
        // as long as pre-processed data has been saved in localStorage
        init: function(masterData) {
            // load stored db if any
            if (typeof localStorage.remodelDb !== 'undefined')
                this._db = JSON.parse( localStorage.remodelDb );

            if (masterData && this.requireUpdate(masterData)) {
                try {
                    var db = this.mkDb(masterData);
                    localStorage.remodelDb = JSON.stringify(db);
                    this._db = db;
                    console.log("RemodelDb: database updated");
                } catch (e) {
                    console.error("RemodelDb:",e);
                }
            } else {
                console.log("RemodelDb: no update required");
            }

            if (! this._db) {
                console.warn("RemodelDb: database unavailable, need to re-initialize with master data");
            }
        },
        // compare master data against _db (could be null)
        // if this function returns true, then we need to perform a db update
        requireUpdate: function(masterData) {
            if (!this._db)
                return true;
            if (this._db.shipCount !== masterData.api_mst_ship.length ||
                this._db.upgradeCount !== masterData.api_mst_shipupgrade.length)
                return true;
            return false;
        },
        // according to the following doc:
        // https://github.com/andanteyk/ElectronicObserver/blob/d28e1d904521ea60b25c15010d06f130ae36dc62/ElectronicObserver/Other/Information/kcmemo.md#%E6%94%B9%E8%A3%85%E6%99%82%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E9%96%8B%E7%99%BA%E8%B3%87%E6%9D%90
        calcDevMat: function(steel) {
            return (steel < 4500) ? 0
                : ( steel < 5500) ? 10
                : ( steel < 6500) ? 15
                : 20;
        },
        mkDb: function(masterData) {
            var self = this;
            // step 1: collect remodel info
            /*
               remodelInfo[ shipId  ] =
                 { ship_id_from: Int
                 , ship_id_to: Int
                 , level: Int
                 , steel: Int
                 , ammo: Int
                 , catapult: Int
                 , blueprint: Int
                 , devmat: Int
                 }
             */
            var remodelInfo = {};
            // all ship Ids (except abyssals)
            var shipIds = [];
            // all ship Ids that appears in x.aftershipid
            // stored as a set.
            var shipDstIds = {};

            $.each(masterData.api_mst_ship, function(i,x){
                if (x.api_id >= 500)
                    return;
                shipIds.push( x.api_id );
                var shipId_to = parseInt(x.api_aftershipid,10) || 0;
                if (shipId_to === 0)
                    return;

                shipDstIds[shipId_to] = true;
                var remodel =
                    { ship_id_from: x.api_id,
                      ship_id_to: shipId_to,
                      level: x.api_afterlv,
                      // yes, this is steel
                      steel: x.api_afterfuel,
                      ammo: x.api_afterbull,
                      // these fields are unknown for now
                      catapult: 0,
                      blueprint: 0,
                      devmat: 0
                    };

                remodel.devmat = self.calcDevMat(remodel.steel);
                remodelInfo[x.api_id] = remodel;

            });

            function id2name(id) {
                return KC3Meta.shipName( KC3Master.ship(id).api_name );
            }

            $.each(masterData.api_mst_shipupgrade, function(i,x) {
                if (x.api_current_ship_id === 0)
                    return;
                var remodel = remodelInfo[x.api_current_ship_id];
                console.assert(
                    remodel.ship_id_to === x.api_id,
                    "data inconsistent:"+x.api_id);
                remodel.catapult = x.api_catapult_count;
                remodel.blueprint = x.api_drawing_count;
                remodelInfo[x.api_current_ship_id] = remodel;
            });

            // step 2: get all original ship ids
            // an original ship can only remodel into other ships
            // but is never a remodel target
            var originalShipIds = [];
            $.each( shipIds, function(i,x) {
                if (!shipDstIds[x])
                    originalShipIds.push(x);
            });

            /*
               remodelGroups[ originalShipId  ] =
                 { origin: shipId
                 // circular-remodels are all considered final forms
                 , final_forms: [shipId]
                 // all forms of one kanmusu
                 , group: [shipId]
                 }
             */
            var remodelGroups = {};
            // reverse from shipId to orginal
            var originOf = {};

            $.each( originalShipIds, function(i, x) {
                var group = [x];
                var cur = x;
                while (typeof remodelInfo[cur] !== 'undefined' &&
                       group.indexOf(remodelInfo[cur].ship_id_to) === -1) {
                    cur = remodelInfo[cur].ship_id_to;
                    group.push( cur );
                }

                cur = group[group.length-1];
                var final_forms = [ cur ];
                while (typeof remodelInfo[cur] !== 'undefined' &&
                       final_forms.indexOf(remodelInfo[cur].ship_id_to) === -1) {
                    cur = remodelInfo[cur].ship_id_to;
                    final_forms.push( cur );
                }

                remodelGroups[x] =
                    { origin: x,
                      group: group,
                      final_forms: final_forms,
                    };

                $.each(group, function(j,y) {
                    originOf[y] = x;
                });
            });

            return { remodelInfo: remodelInfo,
                     remodelGroups: remodelGroups,
                     originOf: originOf,
                     // this 2 numbers are "checksum"s, if master data does not change
                     // on this 2 numbers, we don't recompute
                     shipCount: masterData.api_mst_ship.length,
                     upgradeCount: masterData.api_mst_shipupgrade.length
                   };
        },
        // return root ship in this ships's remodel chain
        originOf: function(shipId) {
            return this._db.originOf[shipId];
        },
        // return remodel info, including cost and required level
        remodelInfo: function(shipId) {
            return this._db.remodelInfo[shipId];
        },
        // return all ships in ship's remodel chain
        // in other words, all ships that considered "same" kanmusu
        remodelGroup: function(shipId) {
            var oid = this.originOf(shipId);
            return oid?this._db.remodelGroups[oid].group:false;
        },
        // get final forms / remodels of one ship,
        // cyclic remodels are all considered final
        finalForms: function(shipId) {
            var oid = this.originOf(shipId);
            return oid?this._db.remodelGroups[oid].final_forms:false;
        },
        // check if one ship is in her final form
        isFinalForm: function(shipId) {
            var ff = this.finalForms(shipId);
            return ff ? ff.indexOf(shipId) !== -1 : false;
        },
        // return ship id of the previous form.
        // if the ship is already in original form, "false" will be returned
        // this relation is not circular - tracing from final form using "previousForm"
        // will not result in infinite loop.
        previousForm: function(shipId) {
            if (shipId === this.originOf(shipId))
                return false;
            var group = this.remodelGroup(shipId);
            var curInd = group.indexOf(shipId);
            console.assert(
                curInd > 0, 
                "previousForm: querying on original form?" );
            return group[curInd-1];
        }
    };
})();

{'fraction_non_alphanumeric': 0.09551331704701185, 'fraction_numerical': 0.013227670857415242, 'mean_word_length': 1.272407256972651, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1342997', 'n_tokens_mistral': 4826, 'n_tokens_neox': 4399, 'n_words': 1069}