File: NwsForecaster.java

package info (click to toggle)
nws 2.11-3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,700 kB
  • ctags: 2,820
  • sloc: ansic: 28,849; sh: 3,289; java: 1,205; makefile: 697; perl: 12
file content (280 lines) | stat: -rwxr-xr-x 10,089 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
package edu.ucsb.cs.nws.nwsprotocol;

import java.io.*;
import java.net.*;


/**
 * The NwsForecaster class implements the protocol specific to NWS
 * forecaster -- forecasting requests and method queries.
 */
public class NwsForecaster extends NwsHost {


  /** See the constructor for NwsHost. */
  public NwsForecaster(String hostName,
                       int hostPort,
                       boolean keepOpen) {
    super(hostName, hostPort, keepOpen);
  }


  /** See the constructor for NwsHost. */
  public NwsForecaster(String hostName,
                       int hostPort) {
    super(hostName, hostPort);
  }


  /** See the constructor for NwsHost. */
  public NwsForecaster(Socket s) {
    super(s);
  }


  /**
   * Returns a list of names of forecasting methods used by the forecaster.
   * The methodUsed field of the Forecast class can be used as an index into
   * this list to determine what method was used to generate the forecast.
   */
  public String[] askMethods() throws Exception {

    int methodCount;
    String methods;
    String[] returnValue;
    int tabPlace;

    messagePrelude();
    NwsMessage.send(connection, METHODS_ASK);
    methods = (String)NwsMessage.receive(connection, this);
    messagePostlude();

    methodCount = 1;
    for(tabPlace = methods.indexOf("\t");
        tabPlace != -1;
        tabPlace = methods.indexOf("\t", tabPlace + 1)) {
      methodCount++;
    }
    returnValue = new String[methodCount];

    for(int i = 0; i < methodCount - 1; i++) {
      tabPlace = methods.indexOf("\t");
      returnValue[i] = methods.substring(0, tabPlace);
      methods = methods.substring(tabPlace + 1);
    }
    returnValue[methodCount - 1] = methods;
    return returnValue;

  }


  /**
   * Requests that the forecaster generate a series of forecast collections
   * from <i>measurements</i>; the last <i>howMany</i> of this series are
   * returned.  <i>forecastName</i> identifies the measurement series;
   * forecasts are based both on the current series of measurements and any
   * measurements identified by the same name passed in prior calls.
   */
  public NwsForecastAPI.ForecastCollection[]
  getForecasts(String forecastName,
               NwsForecastAPI.Measurement[] measurements,
               int howMany) throws Exception {
    byte[][] allBytes = {null, null};
    NwsForecastAPI.ForecastCollection[] returnValue;
    allBytes[0] = new ForecastDataHeader(false,
                                         howMany,
                                         forecastName,
                                         measurements.length).toBytes();
    for(int i = 0; i < measurements.length; i++) {
      allBytes[1] = measurements[i].toBytes();
      allBytes[0] = NwsMessage.concatenateBytes(allBytes);
    }
    messagePrelude();
    NwsMessage.send(connection, FORE_DATA, allBytes[0]);
    returnValue = (NwsForecastAPI.ForecastCollection [])NwsMessage.receive(connection, this);
    messagePostlude();
    return returnValue;
  }


  /**
   * Requests that the forecaster generate a series of forecast collections
   * for the series <i>seriesName</i> which is held by the memory
   * <i>seriesMemory</i>; the last <i>howMany</i> are returned.
   */
  public NwsForecastAPI.ForecastCollection[]
  getForecasts(NwsMemory seriesMemory,
               String seriesName,
               int howMany) throws Exception {
    byte[][] allBytes = {NwsMessage.toBytes(1), null};
    NwsForecastAPI.ForecastCollection[] returnValue;
    allBytes[1] = new ForecastSeries(false,
                                     howMany,
                                     seriesName,
                                     seriesMemory.toString(),
                                     seriesName).toBytes();
    messagePrelude();
    NwsMessage.send
      (connection, FORE_SERIES, NwsMessage.concatenateBytes(allBytes));
    returnValue = (NwsForecastAPI.ForecastCollection [])NwsMessage.receive(connection, this);
    messagePostlude();
    return returnValue;
  }


  /** The header enclosed with FORE_DATA messages. */
  protected static class ForecastDataHeader {

    /** Will we ask for this series again?  Presently always set false. */
    public boolean moreToCome;
    /** The maximum number of ForecastCollections to return. */
    public int atMost;
    /** Identifies the forecast.  Supplied by the client. */
    public String forecastName;
    /** The number of measurements enclosed. */
    public int measurementCount;

    /** Produces a ForecastDataHeader with the specified field values. */
    public ForecastDataHeader(boolean moreToCome,
                              int atMost,
                              String forecastName,
                              int measurementCount) {
      this.moreToCome = moreToCome;
      this.atMost = atMost;
      this.forecastName = forecastName;
      this.measurementCount = measurementCount;
    }

    /** Produces a ForecastDataHeader initialized by reading <i>stream</i>. */
    public ForecastDataHeader(DataInputStream stream) throws Exception {
      moreToCome = stream.readInt() != 0;
      atMost = stream.readInt();
      forecastName = new CString(FORECAST_NAME_SIZE, stream).toString();
      measurementCount = stream.readInt();
    }

    /**
     * Returns the fields of the ForecastDataHeader converted to a byte array.
     */
    public byte[] toBytes() {
      byte[][] allBytes =
        {NwsMessage.toBytes(moreToCome ? 1 : 0),
         NwsMessage.toBytes(atMost),
         new CString(FORECAST_NAME_SIZE, forecastName).toBytes(),
         NwsMessage.toBytes(measurementCount)};
      return NwsMessage.concatenateBytes(allBytes);
    }

  }


  /** The header enclosed with FORE_SERIES messages. */
  protected static class ForecastSeries {

    /** Will we ask for this series again?  Presently always set false. */
    public boolean moreToCome;
    /** The maximum number of ForecastCollections to return. */
    public int atMost;
    /** Identifies the forecast.  Presently identical to the seriesName. */
    public String forecastName;
    /** The name of the memory holding the series in machine:port format. */
    public String memoryName;
    /** The name by which the Memory identifies the series. */
    public String seriesName;

    /** Produces a ForecastSeries with the specified field values. */
    public ForecastSeries(boolean moreToCome,
                          int atMost,
                          String forecastName,
                          String memoryName,
                          String seriesName) {
      this.moreToCome = moreToCome;
      this.atMost = atMost;
      this.forecastName = forecastName;
      this.memoryName = memoryName;
      this.seriesName = seriesName;
    }

    /** Produces a ForecastSeries initialized by reading <i>stream</i>. */
    public ForecastSeries(DataInputStream stream) throws Exception {
      moreToCome = stream.readInt() != 0;
      atMost = stream.readInt();
      forecastName = new CString(FORECAST_NAME_SIZE, stream).toString();
      memoryName = new CString(MAX_HOST_NAME, stream).toString();
      seriesName = new CString(STATE_NAME_SIZE, stream).toString();
    }

    /** Returns the fields of the ForecastSeries converted to a byte array. */
    public byte[] toBytes() {
      byte[][] allBytes =
        {NwsMessage.toBytes(moreToCome ? 1 : 0),
         NwsMessage.toBytes(atMost),
         new CString(FORECAST_NAME_SIZE, forecastName).toBytes(),
         new CString(MAX_HOST_NAME, memoryName).toBytes(),
         new CString(STATE_NAME_SIZE, forecastName).toBytes()};
      return NwsMessage.concatenateBytes(allBytes);
    }

  }


  protected static final int FORECAST_NAME_SIZE = 128;
  protected static final int STATE_NAME_SIZE = 128;

  protected static final int FORE_DATA = NwsMessage.FORECASTER_FIRST_MESSAGE;
  protected static final int FORE_FORECAST = FORE_DATA + 1;
  protected static final int FORE_SERIES = FORE_FORECAST + 1;
  protected static final int METHODS_ASK = FORE_SERIES + 1;
  protected static final int METHODS_TELL = METHODS_ASK + 1;

  protected static final int FORE_FAIL = NwsMessage.FORECASTER_LAST_MESSAGE;


  /** See NwsMessage. */
  public Object receive(int message,
                        DataInputStream stream,
                        int dataLength) throws Exception {
    if(message == METHODS_TELL) {
      return new CString(stream).toString();
    }
    else if(message == FORE_FORECAST) {
      new CString(FORECAST_NAME_SIZE, stream); /* Ignore the forecast name */
      NwsForecastAPI.ForecastCollection[] returnValue =
        new NwsForecastAPI.ForecastCollection[stream.readInt()];
      for(int i = 0; i < returnValue.length; i++)
        returnValue[i] = new NwsForecastAPI.ForecastCollection(stream);
      return returnValue;
    }
    else {
      return super.receive(message, stream, dataLength);
    }
  }


  /**
   * The main() method for this class is a small test program that takes a
   * forecaster spec, a memory spec, and a series name and displays 20
   * measurements and MSE forecasts for that series.
   */
  public static void main(String[] args) {
    final int MAE_FORECAST = NwsForecastAPI.ForecastCollection.MAE_FORECAST;
    final int MSE_FORECAST = NwsForecastAPI.ForecastCollection.MSE_FORECAST;
    try {
      NwsForecaster caster = new NwsForecaster(args[0], 8070);
      NwsForecastAPI.ForecastCollection[] forecasts =
        caster.getForecasts(new NwsMemory(args[1], 8050), args[2], 20);
      String[] methods = caster.askMethods();
      for(int i = 0; i < forecasts.length; i++) {
        NwsForecastAPI.ForecastCollection forecast = forecasts[i];
        System.out.println(
          (int)forecast.measurement.timeStamp + " " +
          forecast.measurement.measurement + " " +
          forecast.forecasts[MSE_FORECAST].forecast + " " +
          forecast.forecasts[MSE_FORECAST].error + " " +
          methods[forecast.forecasts[MSE_FORECAST].methodUsed].replace(' ', '_'));
      }
    } catch(Exception x) { System.err.println(x.toString()); }
  }


}