mirror of
https://github.com/scratchfoundation/scratch-analysis.git
synced 2025-05-15 07:11:16 -04:00
Add aggregate cloud variables data to analysis results
This commit is contained in:
parent
9cc13c4519
commit
2967e71261
8 changed files with 118 additions and 1 deletions
|
@ -26,7 +26,8 @@ The `scratch-analysis` module will return an object containing high-level summar
|
||||||
| `scripts` | `count` |
|
| `scripts` | `count` |
|
||||||
| `blocks` | `count`, `unique`, `list`, `frequency` |
|
| `blocks` | `count`, `unique`, `list`, `frequency` |
|
||||||
| `sprites` | `count` |
|
| `sprites` | `count` |
|
||||||
| `variables` | `count` |
|
| `variables` | `count`, `id` |
|
||||||
|
| `cloud` | `count`, `id` |
|
||||||
| `lists` | `count` |
|
| `lists` | `count` |
|
||||||
| `costumes` | `count`, `list`, `hash` |
|
| `costumes` | `count`, `list`, `hash` |
|
||||||
| `sounds` | `count`, `list`, `hash` |
|
| `sounds` | `count`, `list`, `hash` |
|
||||||
|
|
31
lib/sb2.js
31
lib/sb2.js
|
@ -154,6 +154,35 @@ const extensions = function (project) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts cloud variable information.
|
||||||
|
* @param {object} project Project object (SB2 format)
|
||||||
|
* @param {array} names Names of all variables in project
|
||||||
|
* @return {object} Cloud variable information
|
||||||
|
*/
|
||||||
|
const cloud = function (project, names) {
|
||||||
|
const obj = [];
|
||||||
|
|
||||||
|
// Extract "isPersistent" parameter from all variables in project
|
||||||
|
const cloudyness = extract(project, 'variables', 'isPersistent').id;
|
||||||
|
|
||||||
|
// Ensure that variable names and isPersistent parameter list are the same
|
||||||
|
// length
|
||||||
|
if (names.length !== cloudyness.length) return -1;
|
||||||
|
|
||||||
|
// Iterate over isPersistent values, and extract names of any that are true
|
||||||
|
for (let i in cloudyness) {
|
||||||
|
if (cloudyness[i]) {
|
||||||
|
obj.push(names[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
count: obj.length,
|
||||||
|
id: obj
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyzes a project and returns summary information about the project.
|
* Analyzes a project and returns summary information about the project.
|
||||||
* @param {object} project Project object (SB2 format)
|
* @param {object} project Project object (SB2 format)
|
||||||
|
@ -171,6 +200,8 @@ module.exports = function (project, callback) {
|
||||||
costumes: extract(project, 'costumes', 'costumeName', 'baseLayerMD5')
|
costumes: extract(project, 'costumes', 'costumeName', 'baseLayerMD5')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
meta.cloud = cloud(project, meta.variables.id);
|
||||||
|
|
||||||
// Sprites
|
// Sprites
|
||||||
meta.sprites = sprites(project);
|
meta.sprites = sprites(project);
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,14 @@ const variables = function (targets, attribute) {
|
||||||
let occurrences = 0;
|
let occurrences = 0;
|
||||||
let idList = [];
|
let idList = [];
|
||||||
|
|
||||||
|
// Cloud variables are a type of variable
|
||||||
|
const isCloud = (attribute === 'cloud');
|
||||||
|
if (isCloud) attribute = 'variables';
|
||||||
|
|
||||||
for (let t in targets) {
|
for (let t in targets) {
|
||||||
for (let a in targets[t][attribute]) {
|
for (let a in targets[t][attribute]) {
|
||||||
const variable = targets[t][attribute][a];
|
const variable = targets[t][attribute][a];
|
||||||
|
if (isCloud && (variable.length !== 3 || !variable[2])) continue;
|
||||||
occurrences++;
|
occurrences++;
|
||||||
idList.push(variable[0]);
|
idList.push(variable[0]);
|
||||||
}
|
}
|
||||||
|
@ -97,6 +102,7 @@ module.exports = function (project, callback) {
|
||||||
const meta = {
|
const meta = {
|
||||||
scripts: scripts(project.targets),
|
scripts: scripts(project.targets),
|
||||||
variables: variables(project.targets, 'variables'),
|
variables: variables(project.targets, 'variables'),
|
||||||
|
cloud: variables(project.targets, 'cloud'),
|
||||||
lists: variables(project.targets, 'lists'),
|
lists: variables(project.targets, 'lists'),
|
||||||
comments: extract(project.targets, 'comments'),
|
comments: extract(project.targets, 'comments'),
|
||||||
sounds: extract(project.targets, 'sounds', 'name', 'md5ext'),
|
sounds: extract(project.targets, 'sounds', 'name', 'md5ext'),
|
||||||
|
|
BIN
test/fixtures/sb2/cloud.sb2
vendored
Normal file
BIN
test/fixtures/sb2/cloud.sb2
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/sb2/cloud_complex.sb2
vendored
Normal file
BIN
test/fixtures/sb2/cloud_complex.sb2
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/sb3/cloud.sb3
vendored
Normal file
BIN
test/fixtures/sb3/cloud.sb3
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/sb3/cloud_complex.sb3
vendored
Normal file
BIN
test/fixtures/sb3/cloud_complex.sb3
vendored
Normal file
Binary file not shown.
79
test/unit/cloud.js
Normal file
79
test/unit/cloud.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const test = require('tap').test;
|
||||||
|
const analysis = require('../../lib/index');
|
||||||
|
|
||||||
|
const sb2 = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../fixtures/sb2/cloud.sb2')
|
||||||
|
);
|
||||||
|
const sb3 = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../fixtures/sb3/cloud.sb3')
|
||||||
|
);
|
||||||
|
const sb2Complex = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../fixtures/sb2/cloud_complex.sb2')
|
||||||
|
);
|
||||||
|
const sb3Complex = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../fixtures/sb3/cloud_complex.sb3')
|
||||||
|
);
|
||||||
|
|
||||||
|
test('sb2', t => {
|
||||||
|
analysis(sb2, (err, result) => {
|
||||||
|
t.true(typeof err === 'undefined' || err === null);
|
||||||
|
t.type(result, 'object');
|
||||||
|
t.type(result.cloud, 'object');
|
||||||
|
t.equals(result.cloud.count, 1);
|
||||||
|
t.deepEquals(result.cloud.id, ['☁ baz']);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sb3', t => {
|
||||||
|
analysis(sb3, (err, result) => {
|
||||||
|
t.true(typeof err === 'undefined' || err === null);
|
||||||
|
t.type(result, 'object');
|
||||||
|
t.type(result.cloud, 'object');
|
||||||
|
t.equals(result.cloud.count, 1);
|
||||||
|
t.deepEquals(result.cloud.id, ['☁ baz']);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sb2 complex', t => {
|
||||||
|
analysis(sb2Complex, (err, result) => {
|
||||||
|
t.true(typeof err === 'undefined' || err === null);
|
||||||
|
t.type(result, 'object');
|
||||||
|
t.type(result.cloud, 'object');
|
||||||
|
t.equals(result.cloud.count, 8);
|
||||||
|
t.deepEquals(result.cloud.id, [
|
||||||
|
'☁ Player_1',
|
||||||
|
'☁ Player_2',
|
||||||
|
'☁ Player_3',
|
||||||
|
'☁ Player_4',
|
||||||
|
'☁ Player_5',
|
||||||
|
'☁ GameData',
|
||||||
|
'☁ Player_6',
|
||||||
|
'☁ SAVE_DATA2'
|
||||||
|
]);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sb3 complex', t => {
|
||||||
|
analysis(sb3Complex, (err, result) => {
|
||||||
|
t.true(typeof err === 'undefined' || err === null);
|
||||||
|
t.type(result, 'object');
|
||||||
|
t.type(result.cloud, 'object');
|
||||||
|
t.equals(result.cloud.count, 8);
|
||||||
|
t.deepEquals(result.cloud.id, [
|
||||||
|
'☁ Player_1',
|
||||||
|
'☁ Player_2',
|
||||||
|
'☁ Player_3',
|
||||||
|
'☁ Player_4',
|
||||||
|
'☁ Player_5',
|
||||||
|
'☁ GameData',
|
||||||
|
'☁ Player_6',
|
||||||
|
'☁ SAVE_DATA2'
|
||||||
|
]);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue