#!/usr/bin/python
# Sprites moving around and colliding randomly
# Movement controlled by setting line start/end points.
# includes collision detection and object restriction mask
# rssh bin/sprite_mover5.py nyk:/usr/bin/
import sys,os,random,Image,bresenham,pgdb,time,math,ImageDraw,numpy
dbuser='nyk'
dbpw='rattenhund'
db=pgdb.connect(database='forum',user=dbuser,password=dbpw,host='localhost')
dbc=db.cursor()
objd='/var/www/img/objects/'
odir='frames'
frames=25*120
wave=frames/20
fade_nb=10
transparent=(0, 0, 0, 0)
dilution_factor=1.0
collision_pause=10
start_pause=20

def digits_only(s):
 zahlen=map(str,range(10)) # all numbers
 rs=''
 for c in str(s):
  if c in zahlen: rs+=c
 return rs

def current_median():
 median_nb=10
 imgs=[]
 d='/opt/objects/'
 for f in os.listdir(d):
  if f[-4:]!='.jpg': continue
  imgs.append(d+f)
 random.shuffle(imgs)
 assert len(imgs)>=median_nb
 mimg_fn='/tmp/median%d.png' % median_nb
 if os.path.isfile(mimg_fn): os.unlink(mimg_fn)
 os.system('/opt/objector/median_image %s %s' % (' '.join(imgs[:median_nb]),mimg_fn))
 assert os.path.isfile(mimg_fn)
 mimg=Image.open(mimg_fn)
# os.unlink(mimg_fn)
 return mimg

def randpos(yp):
 x=int(random.random()*ming.size[0])
# if yp>ming.size[1]/2: y=0
# else: y=ming.size[1]
 if random.random()>0.5: y=0
 else: y=ming.size[1]
 return x,y

def sprite_paths(cat,nb,sizelimit=100,ordering='RANDOM()'):
 hour=lambda x : int(time.strftime('%H',time.gmtime(int(digits_only(x))+3600)))
 dbc.execute("""SELECT filename,time,x,y FROM zytob WHERE category=%%s AND status IS NOT NULL 
 ORDER BY %s""" % ordering,(cat,))
 sprites,lines=[],[]
 count=0
 hd={}
 for fn,tt,x,y in dbc.fetchall():
  if x*y>sizelimit*sizelimit: continue
  if hour(tt)<9 or hour(tt)>16: continue
  fns1=fn.replace('object','sprite')
  fns2=fn.replace('object','largest')
  fnt=fn.replace('.png','.txt')
  box=map(int,open(objd+fnt).read().strip().split(','))
  pos=[int(float(box[0])/2.5),int(float(box[1])/2.5)-160]
  if pos[0]<0: pos[0]=0
  if pos[1]<0: pos[1]=0
  if not os.path.isfile(objd+fns2): continue
  hd[pos[1]]=hd.get(pos[1],[])+[y]
  sprite=Image.open(objd+fns2)
  sprites.append(sprite.resize((int(sprite.size[0]/2.5),int(sprite.size[1]/2.5))))
  lines.append(bresenham.line(pos,randpos(pos[1])))
  count+=1
  if count==nb: break
 return sprites,lines

def empty_directory(d):
 for f in os.listdir(d):
  os.unlink('%s/%s' % (d.rstrip('/'),f))

def bright(iimg,n,cidx):
 oimg=Image.new('RGBA',iimg.size)
 for x in range(iimg.size[0]):
  for y in range(iimg.size[1]):
   c=iimg.getpixel((x,y))
   cl=list(c)
   if cl[3]>0: 
    cl[3]=int(n*255/(fade_nb-1))
    if cidx>-1: cl[cidx]=int(cl[cidx]+(200-cl[cidx])/fade_nb*(fade_nb-n))
   oimg.putpixel((x,y),tuple(cl))
 return oimg

if os.path.isdir(odir): empty_directory(odir)
else: os.mkdir(odir)
ming=current_median()
nb_objs=frames/3*2 # depends on wave function
sprites,lines=sprite_paths('Person',nb_objs,sizelimit=100)
numin=10
sprites2,lines2=sprite_paths('Car',numin,sizelimit=150)
for n,(s,l) in enumerate(zip(sprites2,lines2)):
 i=nb_objs/(numin+1)*(n+1)
 sprites[i],lines[i]=s,l
sprites2,lines2=sprite_paths('Bike',numin,sizelimit=100)
for n,(s,l) in enumerate(zip(sprites2,lines2)):
 i=(nb_objs/2)+n
 sprites[i],lines[i]=s,l
speeds,movepos,colid,totalmove={},{},{},{}
counter=0
mask=Image.open('kg_mask.png')
for i in range(frames):
 if i % 10==0: print '%d / %d' % (i,frames)
 timg=Image.new('RGBA',ming.size,transparent)
 add_count=abs(math.cos(float(i)/float(wave)))/dilution_factor
 counter+=add_count
 for j in range(int(counter)):
  if j % 10 == 0: cx=1
  else: cx=-1
  points=lines[j]
  if not speeds.has_key(j): 
   speeds[j]=random.random()*1.5+0.5
   movepos[j]=0.0
   totalmove[j]=0.0
  if int(movepos[j])>=len(points): continue
  fading=True
  if int(movepos[j])<fade_nb: spr=bright(sprites[j],movepos[j],cx)
  elif int(movepos[j])>len(points)-fade_nb: spr=bright(sprites[j],len(points)-movepos[j],cx)
  else: spr=sprites[j]; fading=False
  target=points[int(movepos[j])]
  collision=False
  range1,range2=range(spr.size[0]),range(spr.size[1])
  random.shuffle(range1)
  random.shuffle(range2)
  for x in range1:
   for y in range2:
    xy=target[0]+x,target[1]+y
    if xy[0]>=timg.size[0]: continue
    if xy[1]>=timg.size[1]: continue
    if spr.getpixel((x,y))==transparent: continue
    if timg.getpixel(xy)!=transparent: collision=(x,y)
    if collision: break
   if collision: break
  if not colid.has_key(j): colid[j]=start_pause
  elif colid[j]>0: colid[j]-=1
  if collision and not colid[j] and not fading:
   movepos[j]=fade_nb+1
   if collision[0]>spr.size[0]/2: xnew=0
   else: xnew=spr.size[0]
   if collision[1]>spr.size[1]/2: ynew=0
   else: ynew=spr.size[1]
   lines[j]=fade_nb*[(0,0)] + bresenham.line(target,(xnew,ynew))
   if movepos[j]>=len(lines[j]): continue
   target=lines[j][movepos[j]]
   colid[j]=collision_pause # give it some time to get away from this collision to prevent lumps
  if target[0]>=mask.size[0] or target[1]>=mask.size[1]: continue
  if mask.getpixel(target)[0]==255 and totalmove[j]>fade_nb*3 and not fading: 
   lines[j]=list(lines[j][:int(movepos[j]+fade_nb)])
  timg.paste(spr,target,spr)
  movepos[j]+=speeds[j]
  totalmove[j]+=speeds[j]
 timg2=Image.new('RGB',ming.size)
 timg2.paste(ming,(0,0))
 timg2.paste(timg,(0,0),timg)
 timg2.save('%s/frame%05d.jpg' % (odir,i))

cmd='mencoder mf://%s/*.jpg -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=5000 -o spr5.avi -mf fps=25' % odir
os.system(cmd)
print 'Objects used: %d' % counter