/*
* MktModel.java (Market View Java Applet)
* Copyright (C) 1996 Softbear Inc. (info@softbear.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/



/*
* The MktModel class contains the raw data
* used to graph stock quotes over time, e.g. over
* multiple days. Initially, this data is read
* from a CGI script on the Web server.
* @see #MktView
*/
public class MktModel {
static boolean debug = false;

String symbolName;
java.util.Date startDate;
int intervalType,
maxQuotes,
nrQuotes;
QuoteModel dailyQuotes[];
String cgiServer;

static int HOUR_INTERVAL = 1;
static int DAY_INTERVAL = 2;


public MktModel(java.lang.String serverName,
java.util.Date initDate, int maxQuotes,
int intervalType) {

this.cgiServer = "http://" + serverName + "/cgi/quotes.cgi";
this.symbolName = null;
this.startDate = initDate;
this.nrQuotes = 0;
this.intervalType = intervalType;
this.maxQuotes = maxQuotes;
this.dailyQuotes = new QuoteModel[this.maxQuotes];
}

public void addQuote(QuoteModel quoteModel) throws java.lang.Exception {
if (this.nrQuotes == this.maxQuotes) {
throw new java.lang.Exception("quote overflow");
}
this.dailyQuotes[this.nrQuotes++] = quoteModel;
}

public int countQuotes() { return this.nrQuotes; }

/**
* Downloads market data by running a CGI script on the Web server.
*/
private void downloadQuotes(java.util.Date startDate) throws java.lang.Exception {
if (intervalType != MktModel.DAY_INTERVAL) {
throw new java.lang.Exception("MktModel: invalid interval");
}
String queryStr = "?symbol=" + this.symbolName +
"&start=" + Pretty.date(startDate) +
"&days=" + maxQuotes;
java.net.URL feedUrl = new java.net.URL(this.cgiServer + queryStr);
if (this.debug) { System.out.println("MktView.downloadQuotes(): feedUrl=" + feedUrl.toString()); }
/*
* FUTURE: implement code to call addQuote() for each
* quote read from network connection to CGI script.
*
java.io.InputStream istream = feedUrl.openStream();
if (istream == null) {
throw new java.lang.Exception("MktModel: invalid URL");
}
*/
}

private void fabricateQuotes(java.util.Date startDate) throws java.lang.Exception {
java.util.Random random = new java.util.Random(5L);
long msec = startDate.getTime();
if (this.debug) {
System.out.println("MktView.fabricateQuotes(): msec=" + msec + " (START)");
}

int lp0 = (int) (random.nextDouble() * 50*8); /* $0..$50 */
for (int i = 0; i < this.maxQuotes; ++i) {
QuoteModel quoteModel = new QuoteModel();
java.util.Date date = new java.util.Date(msec);

/* -2% ... +5% */
int pct = (int) (random.nextDouble() * 7);
if (pct > 5) {
pct = -(pct - 5);
}

/* calculate next quote */
int ch = (lp0 * pct) / 100;
int lp1 = lp0 + ch;
if (lp1 < 1) {
/* this shouldn't happen anyway */
lp1 = 0;
}
int lo = lp1 - (int) (2 + random.nextDouble() * 18);
int hi = lp1 + (int) (2 + random.nextDouble() * 9);
int vl = 100 * (int) (random.nextDouble() * 10000);
quoteModel.set(date, hi, lo, lp1, ch, vl);
msec += 24*60*60*1000;
this.addQuote(quoteModel);
lp0 = lp1;
}
}

public String getName() {
if (this.symbolName == null) {
return "";
} else {
return this.symbolName;
}
}

public boolean isEmpty() {
if (this.nrQuotes == 0) {
return true;
} else {
return false;
}
}

/* this method is used to obtain the "current day" info */
public QuoteModel getQuote(int quoteNr) throws java.lang.Exception {
if (quoteNr < 0 || quoteNr > this.nrQuotes) {
throw new java.lang.Exception("MktModel: invalid quoteNr");
}
return dailyQuotes[quoteNr];
}

public int maxPrice() {
int max = 0;
for (int i = 0; i < this.nrQuotes; ++i) {
try {
max = java.lang.Math.max(max, this.getQuote(i).getHigh());
} catch (java.lang.Exception exception) {
throw new InternalError(); // this should never happen
}
}
return max;
}

public int maxVolume() {
int max = 0;
for (int i = 0; i < this.nrQuotes; ++i) {
try {
max = java.lang.Math.max(max, this.getQuote(i).getVolume());
} catch (java.lang.Exception exception) {
throw new InternalError(); // this should never happen
}
}
return max;
}

public int minPrice() {
int min = 0;
for (int i = 0; i < this.nrQuotes; ++i) {
try {
min = java.lang.Math.min(min, this.getQuote(i).getHigh());
} catch (java.lang.Exception exception) {
throw new InternalError(); // this should never happen
}
}
return min;
}

public void setSymbol(String newSymbol) {
if (this.symbolName == null || this.symbolName.equals(newSymbol) == false) {

this.symbolName = newSymbol;
this.nrQuotes = 0; // erase prior data (if any)
try {
if (symbolName.equals("FAKE")) {
this.fabricateQuotes(this.startDate);
} else {
this.downloadQuotes(this.startDate);
}
} catch (java.lang.Exception ex) {
this.nrQuotes = 0;
}
}
}
}
