<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">import com.cycling74.max.*;
import java.net.*;
import java.io.*;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;

//finance.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgv&amp;e=.csv&amp;s=INTC+SUNW

public class DataScapR extends MaxObject implements Runnable, Executable
{
    //Attributes
    double    interval = 30 * 1000; //30 seconds

  static final int	AFTERHOURSCHANGEREALTIME	=	0	;
static final int	ANNUALIZEDGAIN	=	1	;
static final int	ASK	=	2	;
static final int	ASKREALTIME	=	3	;
static final int	ASKSIZE	=	4	;
static final int	AVERAGEDAILYVOLUME	=	5	;
static final int	BID	=	6	;
static final int	BIDREALTIME	=	7	;
static final int	BIDSIZE	=	8	;
static final int	BOOKVALUEPERSHARE	=	9	;
static final int	CHANGE	=	10	;
static final int	CHANGE_CHANGEINPERCENT	=	11	;
static final int	CHANGEFROMFIFTYDAYMOVINGAVERAGE	=12;
static final int	CHANGEFROMTWOHUNDREDDAYMOVINGAVERAGE= 13;
static final int	CHANGEFROMYEARHIGH	=	14	;
static final int	CHANGEFROMYEARLOW	=	15	;
static final int	CHANGEINPERCENT	=	16	;
static final int	CHANGEREALTIME	=	17	;
static final int	CURRENCY	=	18	;
static final int	DAYSHIGH	=	19	;
static final int	DAYSLOW	=	20	;
static final int	DAYSRANGE	=	21	;
static final int	DAYSRANGEREALTIME	=	22	;
static final int	DAYSVALUECHANGE	=	23	;
static final int	DIVIDENDPAYDATE	=	24	;
static final int	TRAILINGANNUALDIVIDENDYIELD	=	25;
static final int	TRAILINGANNUALDIVIDENDYIELDINPERCENT= 26;
static final int	DILUTEDEPS	=	27	;
static final int	EBITDA	=	28	;
static final int	EPSESTIMATECURRENTYEAR	=	29	;
static final int	EPSESTIMATENEXTQUARTER	=	30	;
static final int	EPSESTIMATENEXTYEAR	=	31	;
static final int	SHARESFLOAT	=	32	;
static final int	LASTTRADEDATE	=	33	;
static final int	LASTTRADEPRICEONLY	=	34	;
static final int	LASTTRADESIZE	=	35	;
static final int	LASTTRADETIME	=	36	;
static final int	LASTTRADEWITHTIME	=	37	;
static final int	LOWLIMIT	=	38	;
static final int	MARKETCAPITALIZATION	=	39	;
static final int	MARKETCAPREALTIME	=	40	;
static final int	NAME	=	41	;
static final int	ONEYRTARGETPRICE	=	42	;
static final int	OPEN	=	43	;
static final int	PEGRATIO	=	44	;
static final int	PERATIO	=	45	;
static final int	PERCENTCHANGEFROMFIFTYDAYMOVINGAVERAGE= 46;
static final int	PERCENTCHANGEFROMTWOHUNDREDDAYMOVINGAVERAGE = 47;
static final int	CHANGEINPERCENTFROMYEARHIGH	=	48;
static final int	PERCENTCHANGEFROMYEARLOW	=	49;
static final int	PREVIOUSCLOSE	=	50	;
static final int	PRICEBOOK	=	51	;
static final int	PRICEEPSESTIMATECURRENTYEAR	=	52;
static final int	PRICEEPSESTIMATENEXTYEAR	=	53	;
static final int	PRICESALES	=	54	;
static final int	REVENUE	=	55	;
static final int	SHARESOUTSTANDING	=	56	;
static final int	SHORTRATIO	=	57	;
static final int	STOCKEXCHANGE	=	58	;
static final int	SYMBOL	=	59	;
// remove symbol and recount list
static final int	TWOHUNDREDDAYMOVINGAVERAGE	=	60;
//static final int	VOLUME	=	61	;
//static final int	YEARHIGH	=	62	;
//static final int	YEARLOW	=	63	;
//static final int	YEARRANGE	=	64	;
//static final int	EXTRAA	=	65	;
//static final int	EXTRAB	=	66	;
//static final int	EXTRAC	=	67	;
//static final int	EXTRAD	=	68	;
//static final int	EXTRAE	=	69	;



    
    private String    _base_url     = "http://download.finance.yahoo.com/d/quotes.csv?f=sl1d1t1v0c4c8b2a5a2b3b6b4c1m7m5k4j5p2c6h0g0m0w1r1d0y0e0j4e7e9e8f6k3j1j3n0t8o0r5r0m8m6k5j6p0p6r6r7p5s6s1j2s7x0m4k0j0hgv&amp;e=.csv";
//  private String    _base_url     = "http://finance.yahoo.com/d/quotes.csv?f=sl1d1t1v0c4/ohgv&amp;e=.csv";

    private String    _sym_string   = "&amp;s=";
    private Hashtable _syms;
    private boolean   _first_sym = true;
    private Thread    _t;
    private MaxClock  _cl;
    

    public DataScapR(Atom[] args)
    {
	declareInlets(new int[]{DataTypes.ALL});
	declareOutlets(new int[]{DataTypes.ALL});
	declareAttribute("interval","_get_interval","_set_interval");
	//virtual attribute
	declareAttribute("quotes","_get_quotes","_set_quotes");

	_syms = new Hashtable();
	_cl = new MaxClock(this);
    }
    
    private void _set_interval(int i)
    {
	interval = i * 1000;
    }

    private Atom[] _get_interval()
    {
	return new Atom[]{Atom.newAtom((float)interval / 1000)};
    }

    private void _set_quotes(Atom[] args)
    {
	_syms.clear();
	for(int i = 0; i &lt; args.length; i++)
	    {
		if(args[i].isString())
		    _add_quote(args[i].toString());
		else
		    System.out.println("Invalid Symbol: "+args[i].toString());
	    }
    }

    private Atom[] _get_quotes()
    {
	Enumeration e = _syms.keys();
	Vector  tmp   = new Vector();
	Atom[] ret = null;
	while(e.hasMoreElements())
		tmp.addElement(Atom.newAtom((String)e.nextElement()));
	
	ret = new Atom[tmp.size()];
	for(int i = 0; i &lt; tmp.size();i++)
	    ret[i] = (Atom)tmp.elementAt(i);
	
	return ret;
    }


    public void bang()
    {
	_cl.delay(0);
    }
    
    public void stop()
    {
	_cl.unset();
    }

    public void clear()
    {
	_syms.clear();
    }

        
    public void addQuote(String quote)
    {
	_add_quote(quote);
    }

    public void removeQuote(String quote)
    {
	quote = quote.toUpperCase();
	if(_syms.containsKey(quote))
	    _syms.remove(quote);
    }


    public void execute()
    {

	_t = new Thread(this);
	try{
	    _t.start();
	}catch(Exception e)
	    {
		e.printStackTrace();
	    }

	_cl.delay(interval);
    }

    public void run()
    {
	_do_lookup();
	Enumeration e = _syms.keys();
	outlet(0,"BEGIN");
	while(e.hasMoreElements())
	    {
		String[] nfo = (String[])_syms.get(e.nextElement());
		Atom[] list = new Atom[]{Atom.newAtom(nfo[	0	]),
Atom.newAtom(nfo[	1	]),
Atom.newAtom(nfo[	2	]),
Atom.newAtom(nfo[	3	]),
Atom.newAtom(nfo[	4	]),
Atom.newAtom(nfo[	5	]),
Atom.newAtom(nfo[	6	]),
Atom.newAtom(nfo[	7	]),
Atom.newAtom(nfo[	8	]),
Atom.newAtom(nfo[	9	]),
Atom.newAtom(nfo[	10	]),
Atom.newAtom(nfo[	11	]),
Atom.newAtom(nfo[	12	]),
Atom.newAtom(nfo[	13	]),
Atom.newAtom(nfo[	14	]),
Atom.newAtom(nfo[	15	]),
Atom.newAtom(nfo[	16	]),
Atom.newAtom(nfo[	17	]),
Atom.newAtom(nfo[	18	]),
Atom.newAtom(nfo[	19	]),
Atom.newAtom(nfo[	20	]),
Atom.newAtom(nfo[	21	]),
Atom.newAtom(nfo[	22	]),
Atom.newAtom(nfo[	23	]),
Atom.newAtom(nfo[	24	]),
Atom.newAtom(nfo[	25	]),
Atom.newAtom(nfo[	26	]),
Atom.newAtom(nfo[	27	]),
Atom.newAtom(nfo[	28	]),
Atom.newAtom(nfo[	29	]),
Atom.newAtom(nfo[	30	]),
Atom.newAtom(nfo[	31	]),
Atom.newAtom(nfo[	32	]),
Atom.newAtom(nfo[	33	]),
Atom.newAtom(nfo[	34	]),
Atom.newAtom(nfo[	35	]),
Atom.newAtom(nfo[	36	]),
Atom.newAtom(nfo[	37	]),
Atom.newAtom(nfo[	38	]),
Atom.newAtom(nfo[	39	]),
Atom.newAtom(nfo[	40	]),
Atom.newAtom(nfo[	41	]),
Atom.newAtom(nfo[	42	]),
Atom.newAtom(nfo[	43	]),
Atom.newAtom(nfo[	44	]),
Atom.newAtom(nfo[	45	]),
Atom.newAtom(nfo[	46	]),
Atom.newAtom(nfo[	47	]),
Atom.newAtom(nfo[	48	]),
Atom.newAtom(nfo[	49	]),
Atom.newAtom(nfo[	50	]),
Atom.newAtom(nfo[	51	]),
Atom.newAtom(nfo[	52	]),
Atom.newAtom(nfo[	53	]),
Atom.newAtom(nfo[	54	]),
Atom.newAtom(nfo[	55	]),
Atom.newAtom(nfo[	56	]),
Atom.newAtom(nfo[	57	]),
Atom.newAtom(nfo[	58	]),
Atom.newAtom(nfo[	59	]),
Atom.newAtom(nfo[	60	]),
//Atom.newAtom(nfo[	61	]),
//Atom.newAtom(nfo[	62	]),
//Atom.newAtom(nfo[	63	]),
//Atom.newAtom(nfo[	64	]),
//Atom.newAtom(nfo[	65	]),
//Atom.newAtom(nfo[	66	]),
//Atom.newAtom(nfo[	67	]),
//Atom.newAtom(nfo[	68	]),
//Atom.newAtom(nfo[	69	])
};
		outlet(0,list);
	    }
	outlet(0,"END");

    }

    private void _add_quote(String sym)
    {
	sym = sym.toUpperCase();
	if(!_syms.containsKey(sym))
	    {
		_syms.put(sym, new String[61]);
	    }
    }
    
    private void _do_lookup()
    {
	try{
	    String url = genURL();
	    int c;
	    URL u = new URL(url);
	    BufferedInputStream in = new BufferedInputStream(u.openStream());
	    StringBuffer sb = new StringBuffer();
	    while((c = in.read()) != -1)
		{
		    if(c == (int)'\n')
			{
			    _stuff_into_hash(sb.toString());
			    sb.setLength(0);
			    continue;
			}
		    sb.append((char)c);
		}

	    in.close();
	}catch(Exception e)
	    {
		e.printStackTrace();
	    }
    }
    
    private String genURL()
    {
	Enumeration e = _syms.keys();
	int cnt = 0;
	StringBuffer ret = new StringBuffer(_base_url);
	while(e.hasMoreElements())
	    {
		if(cnt == 0)
		    ret.append(_sym_string+(String)e.nextElement());
		else
		    ret.append("+"+(String)e.nextElement());
		cnt++;
	    }
	return ret.toString();
    }

    //indexOf(StringB str, intB fromIndex);     
    private void _stuff_into_hash(String line)
    {
	byte[] b = line.getBytes();
	StringBuffer word = new StringBuffer();
	int idx = 0;
	String key = null;

	for(int i = 0; i &lt; b.length;i++)
	    {
		if(idx &gt;= 61)
		    break;
		if(b[i] == (byte)'"')
		    continue; //skip quotes
		else if(b[i] == (byte)',' &amp;&amp; idx == 0) //first word
		    {
			key = word.toString();
			((String[])(_syms.get(key)))[idx] = word.toString();
			idx++;
			word.setLength(0);
			continue;
		    }
		else if(b[i] == (byte)',')
		    {
			((String[])(_syms.get(key)))[idx] = word.toString();
			idx++;
			word.setLength(0);		
			continue;
		    }
		word.append((char)b[i]);
	    }
    }

    protected void notifyDeleted() {
    	_cl.release();
    }

    
}


















</pre></body></html>