2018-12-17 18:11:08 -05:00
|
|
|
const utility = require('./utility');
|
|
|
|
|
|
|
|
const scripts = function (targets) {
|
|
|
|
// Storage objects
|
2018-12-18 12:26:14 -05:00
|
|
|
let occurrences = 0;
|
2018-12-17 18:11:08 -05:00
|
|
|
|
|
|
|
// Iterate over all blocks in each target, and look for "top level" blocks
|
|
|
|
for (let t in targets) {
|
|
|
|
for (let b in targets[t].blocks) {
|
2018-12-18 12:26:14 -05:00
|
|
|
if (targets[t].blocks[b].topLevel) occurrences++;
|
2018-12-17 18:11:08 -05:00
|
|
|
}
|
2018-12-17 20:05:13 -05:00
|
|
|
}
|
2018-12-17 18:11:08 -05:00
|
|
|
|
|
|
|
return {
|
2018-12-18 12:26:14 -05:00
|
|
|
count: occurrences
|
2018-12-17 18:11:08 -05:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const variables = function (targets, attribute) {
|
|
|
|
// Storage objects
|
2018-12-18 12:26:14 -05:00
|
|
|
let occurrences = 0;
|
2018-12-17 18:11:08 -05:00
|
|
|
let idList = [];
|
|
|
|
|
2019-03-13 15:01:11 -04:00
|
|
|
// Cloud variables are a type of variable
|
|
|
|
const isCloud = (attribute === 'cloud');
|
|
|
|
if (isCloud) attribute = 'variables';
|
|
|
|
|
2018-12-17 18:11:08 -05:00
|
|
|
for (let t in targets) {
|
|
|
|
for (let a in targets[t][attribute]) {
|
|
|
|
const variable = targets[t][attribute][a];
|
2019-03-13 15:01:11 -04:00
|
|
|
if (isCloud && (variable.length !== 3 || !variable[2])) continue;
|
2018-12-18 12:26:14 -05:00
|
|
|
occurrences++;
|
2018-12-17 18:11:08 -05:00
|
|
|
idList.push(variable[0]);
|
|
|
|
}
|
2018-12-17 20:05:13 -05:00
|
|
|
}
|
2018-12-17 18:11:08 -05:00
|
|
|
|
|
|
|
return {
|
2018-12-18 12:26:14 -05:00
|
|
|
count: occurrences,
|
2018-12-17 18:11:08 -05:00
|
|
|
id: idList
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// Iterate over targets, extract attribute, and aggregate results
|
|
|
|
const extract = function (targets, attribute, id, hash) {
|
|
|
|
// Storage objects
|
2018-12-18 12:26:14 -05:00
|
|
|
let occurrences = 0;
|
2018-12-17 18:11:08 -05:00
|
|
|
let idList = [];
|
|
|
|
let hashList = [];
|
|
|
|
|
|
|
|
for (let t in targets) {
|
|
|
|
for (let a in targets[t][attribute]) {
|
|
|
|
const asset = targets[t][attribute][a];
|
2018-12-18 12:26:14 -05:00
|
|
|
occurrences++;
|
2018-12-17 18:11:08 -05:00
|
|
|
if (typeof id !== 'undefined') idList.push(asset[id]);
|
|
|
|
if (typeof hash !== 'undefined') hashList.push(asset[hash]);
|
|
|
|
}
|
2018-12-17 20:05:13 -05:00
|
|
|
}
|
2018-12-17 18:11:08 -05:00
|
|
|
|
2018-12-18 12:26:14 -05:00
|
|
|
const result = {count: occurrences};
|
2018-12-17 18:11:08 -05:00
|
|
|
if (typeof id !== 'undefined') result.id = idList;
|
|
|
|
if (typeof hash !== 'undefined') result.hash = hashList;
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
|
|
|
const sprites = function (targets) {
|
|
|
|
return {
|
|
|
|
count: targets.length - 1
|
|
|
|
};
|
2018-12-17 20:05:13 -05:00
|
|
|
};
|
2018-12-17 18:11:08 -05:00
|
|
|
|
|
|
|
const blocks = function (targets) {
|
|
|
|
// Storage object
|
|
|
|
let result = [];
|
|
|
|
|
2019-03-13 15:57:04 -04:00
|
|
|
/**
|
|
|
|
* Determine if a argument is the name of a known cloud variable.
|
|
|
|
* @param {string} arg Argument (variable name)
|
|
|
|
* @return {boolean} Is cloud variable?
|
|
|
|
*/
|
|
|
|
const isArgCloudVar = function (arg) {
|
|
|
|
// Validate argument
|
|
|
|
if (typeof arg !== 'string') return false;
|
|
|
|
|
|
|
|
// Check first target (stage) to determine if arg is a cloud variable id
|
|
|
|
const stage = targets[0];
|
|
|
|
if (typeof stage.variables[arg] !== 'undefined') {
|
|
|
|
return stage.variables[arg].length === 3 && stage.variables[arg][2];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Iterate over all targets and push block opcodes to storage object
|
2018-12-17 18:11:08 -05:00
|
|
|
for (let t in targets) {
|
|
|
|
for (let a in targets[t].blocks) {
|
|
|
|
const block = targets[t].blocks[a];
|
2019-03-13 15:57:04 -04:00
|
|
|
|
|
|
|
// Get opcode and check variable manipulation for the presence of
|
|
|
|
// cloud variables
|
|
|
|
let opcode = block.opcode;
|
|
|
|
if (opcode === 'data_setvariableto' || opcode === 'data_changevariableby') {
|
|
|
|
if (isArgCloudVar(block.fields.VARIABLE[1])) {
|
|
|
|
opcode += '_cloud';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!block.shadow) result.push(opcode);
|
2018-12-17 18:11:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate block frequency
|
|
|
|
const freq = utility.frequency(result);
|
|
|
|
|
|
|
|
// Return summary
|
|
|
|
return {
|
|
|
|
count: result.length,
|
|
|
|
unique: Object.keys(freq).length,
|
|
|
|
id: result,
|
|
|
|
frequency: freq
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2018-12-17 20:05:13 -05:00
|
|
|
const extensions = function (list) {
|
2018-12-17 18:11:08 -05:00
|
|
|
return {
|
2018-12-17 20:05:13 -05:00
|
|
|
count: list.length,
|
|
|
|
id: list
|
2018-12-17 18:11:08 -05:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2021-02-10 16:14:36 -05:00
|
|
|
const metadata = function (meta) {
|
|
|
|
return {
|
|
|
|
origin: meta.origin ? meta.origin : ''
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2018-12-17 18:11:08 -05:00
|
|
|
module.exports = function (project, callback) {
|
|
|
|
const meta = {
|
|
|
|
scripts: scripts(project.targets),
|
|
|
|
variables: variables(project.targets, 'variables'),
|
2019-03-13 15:01:11 -04:00
|
|
|
cloud: variables(project.targets, 'cloud'),
|
2018-12-17 18:11:08 -05:00
|
|
|
lists: variables(project.targets, 'lists'),
|
|
|
|
comments: extract(project.targets, 'comments'),
|
|
|
|
sounds: extract(project.targets, 'sounds', 'name', 'md5ext'),
|
|
|
|
costumes: extract(project.targets, 'costumes', 'name', 'md5ext'),
|
|
|
|
sprites: sprites(project.targets),
|
|
|
|
blocks: blocks(project.targets),
|
2021-02-10 16:14:36 -05:00
|
|
|
extensions: extensions(project.extensions),
|
|
|
|
meta: metadata(project.meta)
|
2018-12-17 18:11:08 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
callback(null, meta);
|
|
|
|
};
|