Official ObjectGraph Blog

Monday, February 04, 2008

Announcing PageChat.com

PageChat.com is an innovative tool to communicate with anyone by dynamically creating chat rooms.

You could also use page chat to communicate with others about various topics of interest. Integrate our chat rooms with your websites/blogs to create a unique experience for your audience to chat with each other while on the same page.

We are currently releasing this version as a public beta and these are upcoming features:
  • Sharing Files
  • Guest View
  • Youtube integration
Please Check it out @ http://www.pagechat.com/ Enjoy!

Labels: , ,


posted by gavi at 11:34 PM | 3 comments |

Monday, January 21, 2008

O'Rielly Maker: Make fun O'Rielly Book Covers

Make funny book covers that resemble O'Reilly books using the link below.


http://www.oreillymaker.com

We just launched it yesterday and there are already some really funny ones.

Check these out.



posted by gavi at 8:53 AM | 6 comments |

Wednesday, November 07, 2007

Zen of Python

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!


posted by Kiichi Takeuchi at 7:53 AM | 1 comments |

Sunday, October 21, 2007

iPhone Cake 2.0

10_20_07 120.jpg

10_20_07 124.jpg


Happy Birth Day!

posted by Kiichi Takeuchi at 1:14 PM | 2 comments |

Monday, October 15, 2007

django vs rails - Funny
and yes, we are DJ Ango!

posted by gavi at 5:11 PM | 0 comments |

Tuesday, September 25, 2007

PyScraper: The Python Screen Scraper

I wrote a light weight python based screen scraper, which seems to be working great.

Some of the features:

  • Session Management when using cookies
  • Seperate functions for get,post and downloading large files
  • Automatic handling of redirections

Here is the code for it.

import httplib,urllib,random,sys,re,os
from urlparse import urlparse


class PyScraper:
 def __init__(self):
  self.cookie=""
  self.currenturl=""
  self.urlhist=[]
 
 def __str__(self):
  ret=''
  for item in self.urlhist:
   ret=ret+item+'->'
  return ret
 
 def download(self,url,localfolder):
  bufsize = 1024
  self.urlhist.append(url)
  o=urlparse(url)
  scheme,hostname,path,q,query,position=o
  head,fname = os.path.split(path)
  if(query!=''):
   path=path+"?"+query
   
  conn=httplib.HTTPConnection(hostname)
  conn.request('GET', path,None,{'Cookie':self.cookie})
  resp=conn.getresponse()
  total=int(resp.getheader('content-length'))
  f = open(localfolder+"/"+fname,'wb')
  sofar = 0
  while 1:
   data = resp.read(bufsize)
   f.write(data)
   sofar += len(data)
   perc = (float(sofar)/float(total))
   count = int(perc * 20)
   sys.stdout.write("\r%-30s|%-20s|%3d percent" % (fname,'#'*count,perc*100))
   
   sys.stdout.flush()
   #sys.stdout.write("\r" + str(sofar) + " / " + str(total))total
   if len(data)==0:
    break
  f.close()
  if(resp.getheader('set-cookie')!=None):
   self.cookie=resp.getheader('set-cookie')
  conn.close()
  if(resp.status==302 or resp.status ==301):
   return self.get(resp.getheader('location'))
  return data
 
 def get(self,url):
  self.urlhist.append(url)
  o=urlparse(url)
  scheme,hostname,path,q,query,position=o
  if(query!=''):
   path=path+"?"+query
   
  conn=httplib.HTTPConnection(hostname)
  conn.request('GET', path,None,{'Cookie':self.cookie})
  resp=conn.getresponse()
  data= resp.read()
  if(resp.getheader('set-cookie')!=None):
   self.cookie=resp.getheader('set-cookie')
  conn.close()
  if(resp.status==302 or resp.status ==301):
   return self.get(resp.getheader('location'))
  return data
 
 def post(self,url,data):
  self.urlhist.append(url)
  o=urlparse(url)
  scheme,hostname,path,q,query,position=o
  conn=httplib.HTTPConnection(hostname)
  conn.request('POST', path,data,
{'Content-Type':'application/x-www-form-urlencoded','Cookie':self.cookie})
  resp=conn.getresponse()
  data= resp.read()
  if(resp.getheader('set-cookie')!=None):
   self.cookie=resp.getheader('set-cookie')
  conn.close()
  if(resp.status==302 or resp.status ==301):
   return self.post(resp.getheader('location'),data)
  return data

Here is some snippet of code on how to use it.

from pyscraper import PyScraper

p=PyScraper()
data=p.get("http://www.yahoo.com/")
print data



posted by gavi at 9:31 AM | 2 comments |

Tuesday, August 07, 2007

ObjectGraph AJAX Dictionary AIR version

I recently start learning Adobe AIR . AIR is a platform that allows you to run your web application on your desktop too. It seems there are two major ways to implement AIR: Flex or JavaScript. I downloaded a free online book from here, and I used Aptana for the IDE, but you can basically build AIR application with your favorite text editor & command-line.

After my Hello-World experience, I tried to port our online AJAX dictionary. I could translate this web application in 25 minutes. In terms of coding, only one part was changed, which is url for XMLHttpRequest method. It was relative path to send request, but I changed this to absolute url since it will send requests from your desktop. This was easy, and rest of changes are window width, removing links & unnecessary scripts.

Click here to download the .air application. Please install the runtime from here.


air_install.png
Installing Application

air_dict.png
Screen Shot

Additional Note:

In order to distribute AIR application, you need following MIME type in your server for .air extention.

application/vnd.adobe.air-application-installer-package+zip

Japanese characters are OK in AIR, but the font lost the sharpness. Maybe it's default font or rendering engine of its browser.

Labels:


posted by Kiichi Takeuchi at 5:29 PM | 2 comments |

Wednesday, July 25, 2007

iPhone Dictionary

Just finished learning about the viewport metatag and implemeted this for dictionary on iPhone. Usage: Just type a few words and click on the reference.

http://www.objectgraph.com/dictionary/iphone.html

Labels:


posted by gavi at 11:34 AM | 2 comments |

Tuesday, July 24, 2007

onkeyup and iPhone

I got my iPhone a while ago and only now started looking at some development. Naturally i am trying to get our AJAX Dictionary to work on iPhone.

But looks like iPhone does not support the onkeyup event in Javascript. Actually it does not support a bunch of keyboard events (there is no real physical keyboard on iphone, so its hard to distinquish keyup, keydown etc), so i am thiking of just putting a button after the text is inputted.

There is an onchange event but it only triggers if you focus outside the textbox. Here is the first version of it.

http://www.objectgraph.com/dictionary/iphone.html

Labels:


posted by gavi at 12:59 PM | 0 comments |

Friday, July 06, 2007

Graphviz

Today I found something cool for drawing graphs. Its called GraphViz, You can download it from

http://www.graphviz.org/

It can output in various formats including SVG, PNG and GIF. But PNG and GIF dont have aliasing enabled, so they are pretty crappy.

For an example, look here. An image generated using PNG output

http://www.linkulu.com/random/?format=png&numnodes=10&size=5,5

Now look @ an another random graph with SVG output

http://www.linkulu.com/random/?format=svg&numnodes=10&size=5,5

Here is the python code to generate the graphs. I used Django ofcourse

def randomGraph(request):
   #Defaults for Generating random graphs
   random.seed()
   numnodes=5
   format="svg"
   size="2,2"
   mime="image/svg+xml"
 
 
   if "format" in request.GET:
       infor=request.GET["format"]
       if(infor=="png"):
           mime="image/png"
           format="png"
         
       elif(infor=="gif"):
           mime="image/gif"
           format="gif"
         
   if "size" in request.GET:
       size=request.GET["size"]
 
 
   if "numnodes" in request.GET:
       numnodes=int(request.GET["numnodes"])
 
 
   dot="""digraph G{
       size ="%s";
       orientation=portrait;
       {{{dot}}}
   }""" % (size)
 
   nodes=[]
   shapes=['ellipse','box','circle','record','triangle','doublecircle']
   styles=['bold','dotted','normal']
   colors=['cadetblue2','dimgray','dodgerblue1','beige','aliceblue','ghostwhite',
                   'greenyellow','hotpink4','lightgoldenrod2']
 
   st=""
   for i in range(numnodes):
       nodes.append("a"+str(i));
 
   for node in nodes:
       s1=random.randint(0,len(shapes)-1)
       c1=random.randint(0,len(colors)-1)
       st=st+" %s [shape=%s fillcolor=%s style=filled];\n" %(node,shapes[s1],colors[c1])
 
   for i in range(numnodes):
       r1=random.randint(0,numnodes-1)
       r2=random.randint(0,numnodes-1)
       s2=random.randint(0,len(styles)-1)
       st=st+nodes[r1]+"->"+nodes[r2]+" [style=%s];\n" %(styles[s2])
 
   dot=dot.replace("{{{dot}}}",st)
 
   tmpout, filename = mkstemp()
 
   pobj=Popen('dot -T%s -o %s' % (format,filename),shell=True,stdin=PIPE,stdout=PIPE)
 
   fin = pobj.stdin
   fout = pobj.stdout
   fin.write(dot)
   fin.flush()
   fin.close()
   pobj.wait()
 
   fout = os.fdopen(tmpout, 'r')
   jpeg = fout.read()
   fout.close()
 
   os.remove(filename)
 
   #jpeg=dot
 
   return HttpResponse(content=jpeg, mimetype='%s' % (mime))

Labels:


posted by gavi at 4:09 PM | 2 comments |

Sunday, July 01, 2007

Looks like iPhone crash reports!

Just connected my iPhone to sync it and charge it (BTW the battery claims are totally false - you get may be 4 hours with wifi), Here is the screen shot.

Here is a file in the details..
Process:         Exited process [24]
Path:            Exited process
Version:         N/A (N/A)
Code Type:       0000000C (Native)
Effective UID:   0
Parent Process:  mach_kernel [Unknown]

Date/Time:       2007-07-01 19:41:17.651 -0400
OS Version:      OS X 1.0 (1A543a)
Report Version:  6

Exception Type:  00000020
Exception Codes: 0x8badf00d
Crashed Thread:  Unknown

Backtrace not available

Unknown thread crashed with unknown flavor: 4, state_count: 1

Binary Images:

Labels:


posted by gavi at 11:11 PM | 0 comments |

iPhone Bug?

Just got hands on my own iPhone after learning they were still available on 5th Avenue Store, I just could not resist it being only 20 blocks away!

First this device rocks. Very easy activation and extremely easy to use.

Every application seems to be stable and working great. But there seems to a problem when multitasking listening to music and browsing the web at the same time. My friend Horinaga found this bug and i was able to reproduce it.

It could be a quick software fix! Anyway i love the iPhone.

Labels:


posted by gavi at 10:21 PM | 0 comments |

Saturday, May 19, 2007

Japanese Pages

We would like to announce the first internationalization of our webpages. I'm also glad to announce our good page ranking in Google Japan. If you just search "英和辞書"(English Japanese Dictionary) in google.co.jp, our Ajax dictionary will show up on the first page.

english_japanese_dictionary_firstpage.jpg


japanese_frontpage.jpg

Labels:


posted by Kiichi Takeuchi at 4:25 PM | 0 comments |

Saturday, April 28, 2007

Creating ISO on Mac OSX

I use a Thinkpad X60s that does not have a CD Drive and occasionally need to install software (This time i was trying out Dragon Naturally Speaking 9 which comes in 2 CD's). I also have a Mac Mini and i use it to create the iso images that could be later mounted on my PC using daemon tools.

Here are the steps

First find out what is your CD Drive

df -h

Filesystem                Size   Used  Avail Capacity  Mounted on
/dev/disk0s2               74G    62G    12G    83%    /
devfs                      97K    97K     0B   100%    /dev
fdesc                     1.0K   1.0K     0B   100%    /dev
                   512K   512K     0B   100%    /.vol
automount -nsl [207]        0B     0B     0B   100%    /Network
automount -fstab [235]      0B     0B     0B   100%    /automount/Servers
automount -static [235]     0B     0B     0B   100%    /automount/static
/dev/disk1s0              624M   624M     0B   100%    /Volumes/DNS9_CD1

- After inserting a CD Mac OS X automatically mounts it. Unmount it using


diskutil unmountDisk /dev/disk1s0

Then run the command

dd if=/dev/disk1s0 of=disk1.iso bs=2048

Test the ISO image by mounting it using Finder.

Labels: , ,


posted by gavi at 12:52 PM |

DIY: Building your own live camera with Macmini

OK, I have huge headache today, and this happens to me every year when the season is changing. I took a day-off and I woke up late around noon, then I just decided to have some fun.

What you need:

  1. Macam driver (if your web camera is not supported)
  2. VideoScript - Automate capture images
  3. JDK - Any version to compile applet


Installing Driver:

I got a nice & small Logitech Web Cameralogitech_camera.jpg yesterday, and I just wanted to use this for my Skype which is installed on my macmini in living room. I mounted this on my Sony's LCD, and launched Skype but nothing showed up. According to Logitech's website, the driver for MacOSX is not supported yet. So I found a opensource driver it's called Macam. I downloaded, and the installation was easy (don't forget to install the component in order to use from other applications). Now Skype shows me configuration for the video, and I could see my face. Then I remember that I used to broadcast my living room. OK, let's do it again.


Building Applet:

Since my Hello World experience was in Java, I spend some time with Applet in long time ago. An applet program to stream from jpg file might be nice. This is the program:

import java.awt.*; 
import java.applet.Applet; 

public class WebCamClient extends Applet { 
 private Image mImg;
 private int mIsStarted = 1;
 private int mInterval = 10000; // in millisec
 private String mFile = "webcam.jpg";

 public void start() { 
  mIsStarted = 1; 
 } 

 public void stop() { 
  mIsStarted = 0; 
 } 

 public void paint ( Graphics g ) { 
  mImg = getImage( getDocumentBase(),mFile); 
  MediaTracker mt = new MediaTracker(this); 
  mImg = getImage( getDocumentBase(),mFile); 
  mt.addImage(mImg,0); 
  try { 
   showStatus("loading ..."); 
   mt.waitForAll(); 
  } 
  catch (InterruptedException e){ 
   System.err.println("ERROR: "+e); 
  } 
  g.drawImage( mImg,0,0,this); 
  mImg.flush(); 

  showStatus("Showing every "+mInterval+" milliseconds"); 

  if ( mIsStarted == 1 ) {    
   repaint();
   //repaint(mInterval); // this does not guarantee delay

   // Wait for next cycle
   try {
    Thread.sleep(mInterval);
   }
   catch (InterruptedException e){ 
    System.err.println("ERROR: "+e); 
   }
  } 
 } 

 public void update(Graphics g) { 
  paint(g); 
 } 
}


Good, this program grab webcam.jpg in the same directory and just show it in every 10 seconds. I stored this file in

/Users/kiichi/work/java/webcam/WebCamClient.java

and just compile like:

javac WebCamClient.java



Writting HTML Files:

All you have to do is write am index.html to load this applet in your browser:

index.html

Let's prepare for html refresh version too:

index2.html

Automating Video Capture:

I spend a little bit time for researching automating video capturing and I found VideoScript. This script does a lot of jobs; however, I would like to use the simplest feature to capture the image. When you download the package, it comes with a small editor so that you can run&check your script. This is how it looks like:

set vs to videosource;
repeat 4 times every 1 seconds // min is 4 sec
set f to frame of vs; 
set file "/Users/kiichi/work/java/webcam/webcam.jpg" to f;


In the beginning, I just had a black screen. I tested a sample script to generate QuickTime movie, and it works fine, so what's wrong with the still image? The forum told me the reason because the camera takes a couple of seconds to calibrate the exposure. That's why I inserted the second line to wait 4 seconds. I saved it as update.vs and just run like:

videoscript -f update.vs

This gave me a clear image!

I think, it's ready to go. I had two choices to broadcast my living room. 1. Upload this picture to remote. 2. Open port 80 and let other people look at my Macmini. For today. I decided #1 so that I don't overwhelm my connection speed.



Scheduling FTP upload:

Mac OSX is just another UNIX system, so it might have cron to schedule my jobs. I found crontab under /etc/crontab (or /private/etc/crontab). I did

sudo gvim

to edit crontab. What I added is this line

* * * * * kiichi sh /Users/kiichi/work/java/webcam/update.sh

this means, run update.sh for every minutes.

This is inside update.sh

#!/bin/bash
videoscript -f /Users/kiichi/work/java/webcam/update.vs

FTPSERVER='your ftp url goes here'
FTPUSER='username'
FTPPASS='password'
SOURCE='/Users/kiichi/work/java/webcam/webcam.jpg'
DEST='.'
TARGET='webcam.jpg'

ftp -ni $FTPSERVER <<EOF
user $FTPUSER $FTPPASS
cd $DEST
binary
put $SOURCE $TARGET
quit
EOF
exit 0


It's all set. cron suppose to pickup this script, and this script takes care of generating image and upload on ftp. If you access my streaming web page, the applet automatically refreshes those images. Since this script does not hold the device, when you have Skype call, it will sends a black image that says "Web camera is used by another program" for my ftp.

In the future, this is the todo list:

  • Archiving images
  • Streaming from the local machine - you can write a VideoScript to hold the device, and dump image for every second within the for-loop.
  • Add date and time stamp
  • Motion Detection

Download Source Code:

webcam_sample.zip

Labels:


posted by Kiichi Takeuchi at 1:59 AM | 1 comments |

Monday, April 09, 2007

Guide to use screencasting to save time of programmers for free

You might think, "I'm coding guy, not movie guy", but I know what you hate if you are a programmer: Documentation and Training. I was impressed by some OSS communities, Like Ruby On Rails guys, because they demonstrated the power of screencast in their movies. After I start using screencast softwares, it released me from tons of burdens to explain how-to-use-it for my end users. I save time for training, and user's undersdanding level increases.

Wink

Wink is a completed package in order to publish your movie tutorial. This is basic steps:

  1. Create a New Project
  2. Select capture area. At this point, you are able to choose rectangle area or each window. This window selection is very neat because it allows me to choose inside tab of my browser.
  3. Hit Shift-Pause to start. Do the same thing to stop.
  4. Edit the movie if you need. You are able to add speech bubbles, rounded rectangle, arrows, and so on.
  5. Render and publish. You might save this project as *.wnk file.


I had some problems to capture my secondaly monitor, but it works pretty well if you use it in regular way. A lot of features are included in this software, but it's designed to use in minimal steps.

DebugMode



wink.png


CamStudio

CamStudio.org

I had some problems to play video on FireFox 2.0, however it's quick and easy. Recording steps are minimized.

  1. Hit the record button
  2. Select the capture area and go. It will start recording right after you release button from the rectangle area.
  3. When you stopp it, it will ask you where to save.

After finding Wink, I just use this when I need to dump my screen cast into avi, but it still useful and extream minimized steps to use.


cam.png


posted by Kiichi Takeuchi at 9:22 AM | 2 comments |

Saturday, March 10, 2007

CSS Cross Browser Initialization

Yahoo YUI developer explains how to absorb gap between various browsers. They recommend to include this css in beginning of your css first.

Click here to get Yahoo YUI website.

body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { 
 margin:0;
 padding:0;
}
table {
 border-collapse:collapse;
 border-spacing:0;
}
fieldset,img { 
 border:0;
}
address,caption,cite,code,dfn,em,strong,th,var {
 font-style:normal;
 font-weight:normal;
}
ol,ul {
 list-style:none;
}
caption,th {
 text-align:left;
}
h1,h2,h3,h4,h5,h6 {
 font-size:100%;
 font-weight:normal;
}
q:before,q:after {
 content:'';
}
abbr,acronym { border:0;
}


posted by Kiichi Takeuchi at 8:21 PM | 0 comments |

Tuesday, March 06, 2007

Seven Habits For Effective Text Editing
Bram Moolenaar who is creator of the Vim gave speech about how to improve your coding experience. He also works at Google in Zurich.

This is very basic but powerful principal he offers:

1. Detect inefficiency
2. Find a quicker way
3. Make it a habit


Google Video
You can download hi-resolution avi version and his keynote here

This is not only about bunch of vim tricks but there are a lot of hints to increase your productivity. Even if you are emacs guy, it's worth to review his presentation.





posted by Kiichi Takeuchi at 7:08 PM | 0 comments |

Saturday, March 03, 2007

New Dictionary Launched

I just got some time to fix the CSS and launch ObjectGraph.com with a new design. I learned a lot about CSS during this transformation process.

But the best part is i got a chance to launch the new much improved interface to the ever popular dictionary

Check it out here

http://www.objectgraph.com/dictionary.html

posted by gavi at 11:53 PM | 1 comments |

Tuesday, February 27, 2007

ObjectGraph.com running in a virtual server

With some downtime, i was able to completely move ObjectGraph.com to a virtual server running on an AMD 64 X2 with 4GB of RAM. Looks like dictionary is running very fast after the upgrade.


posted by gavi at 8:57 PM | 0 comments |