[//lasso
/*----------------------------------------------------------------------------

[yahoo_stockquote]
Alternate version of the original [stock_quote] tag.

Author: Jason Huck
Last Modified: Jul. 20, 2006
License: Artistic license <http://opensource.org/licenses/artistic-license.php>

Description:
This is an updated version of the old [stock_quote] ctag for retrieving 
delayed stock quotes from Yahoo! Finance, rewritten as a ctype with the 
following member tags:

->add - Accepts a comma-delimited list of ticker symbols to retrieve.

->(ticker symbol) - Returns the data for the specified symbol.


Sample Usage:
if(action_param('symbol'));
	var('myquotes') = yahoo_stockquote(action_param('symbol'));
	$myquotes->add('GOOG');
	$myquotes->AAPL;
	$myquotes;
/if;


Downloaded from tagSwap.net on Feb. 14, 2007.
Latest version available from <http://tagSwap.net/yahoo_stockquote>.

----------------------------------------------------------------------------*/
		

define_type(
	'stockquote',
	-namespace='yahoo_',
	-prototype,
	-description='Retrieves and displays delayed stock quotes from Yahoo! Finance.'
);
	local('symbols' = map);

	// allow add on create
	define_tag('onCreate', -opt='in');
		self->add(#in);
	/define_tag;
	
	// lookup data for new symbols
	define_tag('add', -req='in', -copy);	
		// strip any non-alphanumeric characters except commas from input
		#in = string_replaceregexp(
			#in,
			-find='[^a-zA-Z0-9,]',
			-replace=''
		);
		
		// retrieve the data
		local('response') = string(
			include_url('http://quote.yahoo.com/d/quote.csv?s=' + #in + '&f=sl1d1t1c&e=.txt')
		);

		// parse results
		local('out' = map);
		
		// normalize line endings
		#response->replace('\r\n','\n')&replace('\r','\n')&removetrailing('\n');
		
		// split into lines
		local('lines') = #response->split('\n');
					
		local('current' = string);
		local('lastupdate' = null);
		
		protect;
			iterate(#lines, local('line'));
				local('linedata') = #line->split(',');

				iterate(#linedata, local('i'));
					#i->removeleading('"')&removetrailing('"');
				
					select(loop_count);
						case(1);
							#out->insert(#i = map);
							#current = #i;
							
						case(2);
							#out->find(#current)->insert('price' = decimal(#i));
							
						case(3);
							#lastupdate = #i;
							
						case(4);
							#lastupdate += ' ' + #i;
							#lastupdate = date(#lastupdate, -format='%D %-H:%M%p');
							#out->find(#current)->insert('lastupdate' = #lastupdate);
							#lastupdate = null;
							
						case(5);
							#out->find(#current)->insert('change' = #i);
							#current = '';
							
					/select;
				/iterate;
			/iterate;
			
			iterate(#out->keys, local('i'));
				self->symbols->insert(#i = #out->find(#i));
			/iterate;			
		/protect;	
	/define_tag;
	
	// returns the data for the requested symbol
	define_tag('getsymbol', -req='in');
		return(@self->symbols->find(#in));
	/define_tag;
	
	// on convert, return a simple pair array of symbols = prices
	define_tag('onConvert');
		local('out' = array);

		iterate(self->symbols->keys, local('i'));
			#out->insert(#i = self->symbols->find(#i)->find('price'));
		/iterate;
		
		#out->sort;
		
		return(#out);
	/define_tag;
	
	// this avoids a recursion error due to the use of _unknowntag
	define_tag('symbols');
		return(@self->'symbols');
	/define_tag;
	
	// allows lookups by symbol directly
	define_tag('_unknownTag');
		return(@self->getsymbol(tag_name));
	/define_tag;
/define_type;
]
