analyzing make-a-block projects

This commit is contained in:
Glen Chiacchieri 2013-08-09 22:42:33 +00:00
parent aa6fc5ab08
commit d0b0784b03
2 changed files with 60 additions and 1 deletions
python/libscratchproject

View file

@ -0,0 +1,31 @@
"""
A script to iterate over all Scratch 2.0 projects.
"""
import project
start_id = 10000000 # start of scratch 2.0 projects, 10 million
end_id = 11784029 # update this by querying scratch sql: select id from projects_project order by id desc limit 1;
total_projects = 0
make_a_block_ids = set()
for project_id in range(start_id,end_id):
proj = None
try:
proj = project.Project(project_id)
total_projects += 1
except Exception as e:
# ignore folder not existing and unparsable json
pass
if proj:
# process data here
if proj.uses_make_a_block():
make_a_block_ids.add(project_id)
with open('make_a_block_ids', 'wb') as f:
for project_id in make_a_block_ids:
f.write(project_id)
print len(make_a_block_ids), 'out of', len(total_projects)

View file

@ -43,7 +43,6 @@ class ScratchDataStructureObj(BaseObj):
def __init__(self, info_dict):
BaseObj.__init__(self, info_dict)
class Sprite(ScratchObj):
def __init__(self, sprite_dict):
ScratchObj.__init__(self, sprite_dict)
@ -53,6 +52,10 @@ class Sprite(ScratchObj):
return namedtuple('SpriteInfo',
self._d['info'].keys())(**(self._d['info']))
@property
def scripts(self):
return self._d.get('scripts', [])
@property
def costumes(self):
try:
@ -71,6 +74,19 @@ class Sprite(ScratchObj):
def assets(self):
return self.sounds + self.costumes
def has_make_a_block(self):
def traverse(script_list):
for script in script_list:
if hasattr(script, '__iter__'):
if 'procDef' in script:
return True
elif traverse(script):
return True
return False
return traverse(self.scripts)
class Project(ScratchObj):
def __init__(self, project_id):
self.project_id = project_id
@ -81,6 +97,8 @@ class Project(ScratchObj):
project_id), 'LATEST')
with open(filepath) as fp:
d = simplejson.loads(fp.read())
if not isinstance(d, dict):
raise Exception('Unexpected JSON serialization: {}'.format(d))
ScratchObj.__init__(self, d)
@ -128,6 +146,16 @@ class Project(ScratchObj):
ret.append(child)
return ret
def uses_make_a_block(self):
"""
Returns whether any of the sprites in this project use the "make a block"
function.
"""
for sprite in self.sprites:
if sprite.has_make_a_block():
return True
return False
class ProjectRevision(Project):
def __init__(self, project_dict):