# calculate relative frequency of different processing API function calls
# use example corpus
import os
from os.path import join
import string
import re
import math

#list of processing API function names
functions = ['delay','draw','exit','loop','noLoop','popStyle','pushStyle','redraw','setup','size','cursor','frameRate','noCursor','binary','boolean','byte','char','float','hex','int','str','unbinary','unhex','join','match','matchAll','nf','nfc','nfp','nfs','split','splitTokens','trim',
'append','arrayCopy','concat','expand','reverse','shorten','sort','splice','subset',
'for','while','switch',
'arc','ellipse','line','point','quad','rect','triangle',
'bezier','bezierDetail','bezierPoint','bezierTangent','curve','curveDetail','curvePoint','curveTangent','curveTightness',
'box','sphere','sphereDetail',
'ellipseMode','noSmooth','rectMode','smooth','strokeCap','strokeJoin','strokeWeight',
'beginShape','beginVertex','curveVertex','endShape','texture','textureMode','vertex',
'loadShape','shape','shapeMode',
'mouseClicked','mouseDragged','mouseMoved','mousePressed','mouseReleased',
'keyPressed','keyReleased','keyTyped',
'createInput','loadBytes','loadStrings','open','selectFolder','selectInput',
'link','param','status',
'day','hour','millis','minute','month','second','year',
'print','println',
'save','saveFrame',
'beginRaw','beginRecord','createOutput','createReader','createWriter','endRaw','endRecord','saveBytes','saveStream','saveStrings','selectOutput',
'applyMatrix','popMatrix','printMatrix','pushMatrix','resetMatrix','rotate','rotateX','rotateY','rotateZ','scale','translate',
'ambientLight','directionalLight','lightFalloff','lightSpecular','lights','noLights','normal','pointLight','spotLight',
'beginCamera','camera','endCamera','frustum','ortho','perspective','printCamera','printProjection',
'modelX','modelY','modelZ','screenX','screenY','screenZ',
'ambient','emissive','shininess','specular',
'background','colorMode','fill','noFill','noStroke','stroke','alpha','blendColor','blue','brightness','color','green','hue','lerpColor','red','saturation',
'createImage','image','imageMode','loadImage','noTint','requestImage','tint',
'blend','copy','filter','get','loadPixels','set','updatePixels',
'createGraphics','hint','createFont','loadFont','text','textFont','textAlign','textLeading','textMode','textSize','textWidth',
'textAscent','textDescent',
'abs','ceil','constrain','dist','exp','floor','lerp','log','mag','map','max','min','norm','pow','round','sq','sqrt',
'acos','asin','atan','atan2','cos','degrees','radians','sin','tan','noise','noiseDetail','noiseSpeed','random','randomSeed'
]

# build regular expressions to match function calls/defs
# and build dictionary that will hold # of references in examples
rxs = dict()
function_counts = dict()
for fn in functions:
    function_counts[fn] = 0
    rxs[fn] = re.compile(fn+'\s*(.*?)')
    
pdeFiles = []
pdeCount = []
extension = ".pde"
dirs = ["/Applications/Processing.app/Contents/Resources/Java/examples",
"/Users/bjoern/Documents/workspace/processing-stats/google-pdes",
"/Users/bjoern/Documents/workspace/processing-stats/form-pdes"]
for startdir in dirs:
    # walk directory hierarchy, collect paths of pde files into  pdeFiles
    for root, dirs, files in os.walk(startdir):
        print "Current directory", root
        pdeInDir = [f for f in files if os.path.splitext(f)[1] == extension]
        pdeFiles += [os.path.join(root,f) for f in pdeInDir]
        if len(pdeInDir)>0:
            pdeCount.append(len(pdeInDir))

# now read each file and calculate # of function calls
for pde in pdeFiles:
   f = open(pde,'r')
   for l in f.readlines():
       for fn in functions:
           if(rxs[fn].search(l) != None ):
               function_counts[fn] = function_counts[fn] + 1

tosort = [(value,key) for key,value in function_counts.items()]
tosort.sort(reverse=True)

# calculate relative freq as weight [0.0-1.0] 
# apply log() liberally to get around the inevitable power-law
# distribution of results
# then use freq as scalar to calculate font size as
# font_size = min_size + freq*(max_size-min_size)

max = tosort[0][0]
tosort = [(float(v)/max,f) for v,f in tosort]
logged = [(1+int(round(math.log(1+math.log(1+math.log(v+1,2),2),2)*20)),f) for v,f in tosort]
print(logged)

# now load in the reference/index.html
# go through links and add a <font size = x></font> wrapper
f = open('reference/index.html','r')
html = f.read()
f.close()
for v,fn in logged:
    fontified = '><font size="'+str(v)+'">'+fn+'()'+'</font>'
    html = string.replace(html,'>'+fn+'()',fontified)
g = open('reference/index4.html','w')
g.write(html)
g.close()