Merge branch 'asdt_16.2.1' of ssh://vlab.ncep.noaa.gov:29418/AWIPS2_Dev_Baseline into master_16.2.1

Former-commit-id: 70c5b3a39104af92685e80e7e76177deb05c94e5
This commit is contained in:
Shawn.Hooper 2015-11-16 16:40:30 -05:00
commit 4982393e5d
69 changed files with 3849 additions and 154 deletions

View file

@ -43,6 +43,7 @@ import com.raytheon.uf.common.serialization.SerializationException;
* ------------ ---------- ----------- --------------------------
* Jun 5, 2015 4498 nabowle Use JAXBManager to unmarshal. Rename to
* RcmUtil.
* Oct 15,2015 17789 wkwock Change max TDWR radar ID to 3099
*
* </pre>
*
@ -52,7 +53,7 @@ public class RcmUtil {
public static RadarType getRadarType(RadarConfig rc) {
int id = rc.getNexradID();
if (id >= 3000 && id <= 3045) // TODO: 3045 is the current max, but...
if (id >= 3000 && id <= 3099) // TODO: 3099 is the current max, but...
return RadarType.TDWR;
else if (id >= 4000 && id < 4050) // TODO: may be 4050
return RadarType.ASR;

View file

@ -124,7 +124,7 @@ public class Loader {
// This is not in any baselined database yet.
switch (rp.pid) {
case 180: case 181: case 182: case 183: case 185:
case 180: case 181: case 182: case 183: case 184: case 185:
case 186: case 187:
rp.typeRestriction = EnumSet.of(RadarType.TDWR);
break;

View file

@ -60,6 +60,7 @@
25 | 16 | 0 | 0.25 | 60 | V | Velocity (V) | Radial | y | | | | V | | | | | 1 | |
26 | 16 | 0 | 0.50 | 115 | V | Velocity (V) | Radial | y | | | | V | | | | | 1 | |
27 | 16 | 0 | 1.00 | 230 | V | Velocity (V) | Radial | y | | | | V | | | | | 1 | |
184|256 | 0 | 0.15 | 90 | SW | Spectrum Width (SW) | Radial | y | | | | | | | | | 2 | | y
185| 8 | 0 | 0.15 | 90 | SW | Spectrum Width (SW) | Radial | y | | | | | | | | | 2 | |
28 | 8 | 0 | 0.25 | 60 | SW | Spectrum Width (SW) | Radial | y | | | | | | | | | 2 | |
29 | 8 | 0 | 0.50 | 115 | SW | Spectrum Width (SW) | Radial | y | | | | | | | | | 2 | |

View file

@ -64,6 +64,7 @@ import com.raytheon.rcm.server.Log;
* 2009 dfriedma Initial version
* 2012-04-30 DR 14904 D. Friedman Add backup links to dial ORPGs.
* 2015-06-10 4498 nabowle Rename Util->RcmUtil
* 2015-10-15 DCS 17789 wkwock Change max TDWR radar ID to 3099
* </pre>
*/
public class Awips1ConfigProvider implements ConfigurationProvider {
@ -502,8 +503,8 @@ public class Awips1ConfigProvider implements ConfigurationProvider {
if (name.substring(1, 4).equalsIgnoreCase(namelet)) {
int nexradId = radars.get(name).getNexradID();
if (linespeed.equals("D6")) {
// TODO: can we really rely on the 3045 number?
if (nexradId >= 3000 && nexradId <= 3045)
// TODO: can we really rely on the 3099 number?
if (nexradId >= 3000 && nexradId <= 3099)
return name;
} else {
if (nexradId < 3000

View file

@ -12,6 +12,7 @@ Import-Package: com.raytheon.uf.common.dataplugin,
com.raytheon.uf.viz.core.drawables,
com.raytheon.uf.viz.core.exception,
com.raytheon.uf.viz.core.map,
com.raytheon.uf.viz.core.point.display,
com.raytheon.uf.viz.core.rsc,
com.raytheon.uf.viz.core.rsc.capabilities,
com.vividsolutions.jts.algorithm,

View file

@ -33,7 +33,6 @@ import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Polygon;
/**
*
* A class containing all parameters necessary for an outline resource to be
@ -45,6 +44,7 @@ import com.vividsolutions.jts.geom.Polygon;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 2, 2009 bsteffen Initial creation
* Jul 7, 2015 10352 byin Added labelSymbolId
*
* </pre>
*
@ -52,7 +52,7 @@ import com.vividsolutions.jts.geom.Polygon;
* @version 1.0
*/
public class AdvisoryRecord {
private static GeometryFactory FACTORY = new GeometryFactory();
protected static final UnitConverter NM_TO_METERS = NonSI.NAUTICAL_MILE
@ -61,21 +61,23 @@ public class AdvisoryRecord {
protected static final int NUM_VERTICES = 40;
protected static final double ANGLE_STEP = 360.0 / NUM_VERTICES;
public enum AdvisoryResourceType {
LINE, ISOL, AREA, TEXT
}
private AdvisoryResourceType type;
private Polygon polygon;
private Coordinate[] line;
private Coordinate labelLoc;
private String label;
private char labelSymbolId = 0;
private String inspectString;
public AdvisoryRecord(Coordinate labelLoc, String label) {
@ -98,7 +100,7 @@ public class AdvisoryRecord {
this.label = label;
this.inspectString = inspectString;
}
public AdvisoryRecord(Coordinate[] line, double diameter, String label,
String inspectString) {
this.type = AdvisoryResourceType.LINE;
@ -144,7 +146,7 @@ public class AdvisoryRecord {
this.label = label;
this.inspectString = inspectString;
}
public AdvisoryRecord(Coordinate center, double diameter, String label,
String inspectString) {
this.type = AdvisoryResourceType.ISOL;
@ -167,7 +169,7 @@ public class AdvisoryRecord {
this.label = label;
this.inspectString = inspectString;
}
/**
* Convert a pair of Lat Lon coords to a pair of pixel coords in a certain
* direction and a certain distance away
@ -202,8 +204,7 @@ public class AdvisoryRecord {
* @return a new Coordinate at the correct location
*/
public static Coordinate getPointOnCircle(Coordinate center,
double distance,
double angle) {
double distance, double angle) {
while (angle > 180) {
angle -= 360;
}
@ -268,5 +269,12 @@ public class AdvisoryRecord {
return inspectString;
}
public char getLabelSymbolId() {
return labelSymbolId;
}
public void setLabelSymbolId(char labelSymbolId) {
this.labelSymbolId = labelSymbolId;
}
}

View file

@ -47,6 +47,9 @@ import com.vividsolutions.jts.geom.Coordinate;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 2, 2009 bsteffen Initial creation
* Jul 7, 2015 10352 byin Display symbols for turb/icing
* and hazard types for IFR/MTOS
*
*
* </pre>
*
@ -56,14 +59,28 @@ import com.vividsolutions.jts.geom.Coordinate;
@XmlAccessorType(XmlAccessType.NONE)
public class AirmetDataAdapter extends AbstractAdvisoryDataAdapter {
private static final String LABEL_FORMAT = "%d%s";
private static final String INSPECT_FORMAT = "Valid UNTIL %02d%02d%02d\n%s";
private static final String REPORT_INDICATOR = "AIRMET";
private static final String SEGMENT_SEPERATOR = "\n. \n";
private static final String TURBULENCE_TYPE = "TURBULENCE";
private static final String ICING_TYPE = "ICING";
private static final String IFR_TYPE = "INSTRUMENT FLIGHT RULES";
private static final String MTN_TYPE = "MOUNTAIN OBSCURATION";
private static final String IFR_LABEL = "IFR";
private static final String MTN_LABEL = "MTOS";
protected static final char TURBULENCE_SYMBOL = '\u007b';
protected static final char ICING_SYMBOL = '\u007e';
private static final float LINE_WIDTH = 1.5f;
private static final LineStyle LINE_STYLE = LineStyle.SOLID;
@ -111,7 +128,6 @@ public class AirmetDataAdapter extends AbstractAdvisoryDataAdapter {
coords[loc.getIndex() - 1] = new Coordinate(loc.getLongitude(),
loc.getLatitude());
}
int updateNumber = parent.getUpdateNumber();
String sequenceId = report.getSequenceID();
if (sequenceId == null) {
sequenceId = "";
@ -134,11 +150,30 @@ public class AirmetDataAdapter extends AbstractAdvisoryDataAdapter {
} else {
segment = "";
}
String label = String.format(LABEL_FORMAT, updateNumber, sequenceId);
String inspectString = String.format(INSPECT_FORMAT, day, hour, min,
segment);
String hazType = report.getHazardType();
String label;
if (hazType.equalsIgnoreCase(IFR_TYPE)) {
label = IFR_LABEL;
} else if (hazType.equalsIgnoreCase(MTN_TYPE)) {
label = MTN_LABEL;
} else {
label = "";
}
AdvisoryRecord aRecord = new AdvisoryRecord(coords, label,
inspectString);
if (hazType.equalsIgnoreCase(ICING_TYPE)) {
aRecord.setLabelSymbolId(ICING_SYMBOL);
} else if (hazType.equalsIgnoreCase(TURBULENCE_TYPE)) {
aRecord.setLabelSymbolId(TURBULENCE_SYMBOL);
}
return aRecord;
}

View file

@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
@ -42,12 +43,15 @@ import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle;
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
import com.raytheon.uf.viz.core.PixelCoverage;
import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.uf.viz.core.drawables.IFont.Style;
import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.point.display.SymbolLoader;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
@ -75,6 +79,7 @@ import com.vividsolutions.jts.geom.Polygon;
* Jun 13, 2011 9758 cjeanbap Set colorString of AdvisoryResourceData.
* Aug 14, 2014 3523 mapeters Updated deprecated {@link DrawableString#textStyle}
* assignments.
* Jul 7, 2015 10352 byin Added SymbolLoader to plot symbols
* </pre>
*
* @author bsteffen
@ -101,6 +106,8 @@ public class AdvisoryResource extends
private float magnification;
private SymbolLoader symbolLoader;
protected AdvisoryResource(AdvisoryResourceData resourceData,
LoadProperties loadProperties) {
super(resourceData, loadProperties);
@ -188,6 +195,7 @@ public class AdvisoryResource extends
font.dispose();
}
this.font = target.initializeFont("Monospace", 10, new Style[] {});
this.symbolLoader = new SymbolLoader();
}
@Override
@ -209,6 +217,7 @@ public class AdvisoryResource extends
}
this.displayedDataTime = curDataTime;
double scale[] = getScale(paintProps);
if (mainShape == null || dottedShape == null || dashedShape == null) {
clearShapes();
@ -283,6 +292,21 @@ public class AdvisoryResource extends
RGB[] colors = new RGB[labels.length];
Arrays.fill(colors, color);
double x = pixelLoc[0];
double y = pixelLoc[1];
if (record.getLabelSymbolId() != 0) {
IImage symbolImg = symbolLoader.getImage(target, color,
(char) record.getLabelSymbolId());
Coordinate ul = new Coordinate(x, y);
Coordinate ur = new Coordinate(x + 12 * scale[0], y);
Coordinate lr = new Coordinate(ur.x, y + 12 * scale[1]);
Coordinate ll = new Coordinate(x, lr.y);
PixelCoverage extent = new PixelCoverage(ul, ur, lr, ll);
target.drawRaster(symbolImg, extent, paintProps);
}
DrawableString dStrings = new DrawableString(labels, colors);
dStrings.font = font;
dStrings.setCoordinates(pixelLoc[0], pixelLoc[1]);
@ -418,4 +442,13 @@ public class AdvisoryResource extends
clearShapes();
}
private double[] getScale(PaintProperties paintProps) {
IExtent extent = paintProps.getView().getExtent();
Rectangle canvasBounds = paintProps.getCanvasBounds();
double[] scale = new double[2];
scale[0] = extent.getWidth() / canvasBounds.width;
scale[1] = extent.getHeight() / canvasBounds.height;
return scale;
}
}

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bundle>
<displayList>
<displays xsi:type="d2DMapRenderableDisplay"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<descriptor xsi:type="mapDescriptor">
<resource>
<loadProperties loadWithoutData="true">
<capabilities>
<capability xsi:type="imagingCapability"
interpolationState="false" brightness="2.0"
contrast="1.0" alpha="1.0" />
<capability xsi:type="colorableCapability"
colorAsString="#00ff00" />
</capabilities>
</loadProperties>
<properties isSystemResource="false"
isBlinking="false" isMapLayer="false" isHoverOn="false"
isVisible="true" />
<resourceData xsi:type="plotResourceData"
plotSource="Spot Forecast Request"
plotModelFile="stqPlotDesign.svg" pixelSizeHint="45"
retrieveData="false" isUpdatingOnMetadataOnly="false"
isRequeryNecessaryOnTimeMatch="true">
<binOffset posOffset="43200"
negOffset="43200" virtualOffset="0" />
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="stq"
constraintType="EQUALS" />
</mapping>
</metadataMap>
</resourceData>
</resource>
</descriptor>
</displays>
</displayList>
</bundle>

View file

@ -33,4 +33,6 @@
fileName="menus/ncepHydro/cpc/baseCPC.xml"/>
<include installTo="menu:ncepHydro?after=AWC"
fileName="menus/ncepHydro/awc/baseAWC.xml"/>
<include installTo="menu:ncepHydro?after=STQ"
fileName="menus/ncepHydro/stq/baseSTQ.xml"/>
</menuContributionFile>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contribute xsi:type="bundleItem"
file="bundles/ncepHydro/SpotRequestPlot.xml" menuText="Spot Forecast Requests"
id="spotRequestPlot">
</contribute>
</menuTemplate>

View file

@ -0,0 +1,54 @@
<?xml version="1.0"?>
<svg width="80" height="80"
viewBox="0 0 80 80"
overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
class StqPlotDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
projectName = rec.getString("projectName")
reqOfficial = rec.getString("reqOfficial")
emPhone = rec.getString("emPhone")
sampleString = "Project Name: %s\n\tOffcial Name: %s\n\tEmergency Phone: %s"%(projectName,reqOfficial,emPhone)
return sampleString
plotDelegate = StqPlotDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";
src: url(WindSymbols.svg#WindSymbols); }
@font-face { font-family: "StandardFont";
src: url(Standard.svg#Standard); }
@font-face { font-family: "WxSymbolFont";
src: url(WxSymbols.svg#WxSymbols); }
@font-face { font-family: "SpecialSymbolFont";
src: url(SpecialSymbols.svg#SpecialSymbols); }
text.text
{
fill: none;
font-size: 1.2em;
stroke-width: 1px;
font-family: StandardFont;
font-size: 1.2em;
}
]]>
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="stqsymbol" plotMode="text" class="text" plotParam="stqSymbol" x="0" y="0">0</text>
<text id="sample" plotMode="sample" class="text" plotParam="projectName,reqOfficial,emPhone">0</text>
</symbol>
</defs>
<use id="wind" x="40" y="40" width="80" height="80" visibility="visible" xlink:href="#plotData"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -104,6 +104,14 @@
name="xyx"
visible="true">
</separator>
<command id="STQ"
commandId="com.raytheon.viz.ui.actions.titleAction"
label="------ STQ ------">
</command>
<separator
name="xxx"
visible="true">
</separator>
<command
commandId="com.raytheon.viz.ui.actions.titleAction"
label="------ Local Analyses/Statistical Guidance ------">

View file

@ -23,6 +23,7 @@
<displays xsi:type="d2DMapRenderableDisplay"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<descriptor xsi:type="mapDescriptor">
<!-- Not High severity -->
<resource>
<loadProperties>
<capabilities>
@ -69,6 +70,53 @@
</resource>
</resourceData>
</resource>
<!-- High severity -->
<resource>
<loadProperties>
<capabilities>
</capabilities>
</loadProperties>
<resourceData xsi:type="plotBlendedResourceData">
<resource>
<loadProperties loadWithoutData="true"/>
<properties isSystemResource="false" isBlinking="false"
isMapLayer="false" isHoverOn="false"
isVisible="true" />
<resourceData xsi:type="plotResourceData" plotSource="${legend} Sev"
plotModelFile="${svg2}"
retrieveData="false" isUpdatingOnMetadataOnly="false">
<binOffset posOffset="1800" negOffset="1800" virtualOffset="0"/>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="pirep" constraintType="EQUALS" />
</mapping>
<mapping key="location.flightLevel">
<constraint constraintValue="${between}" constraintType="BETWEEN" />
</mapping>
</metadataMap>
</resourceData>
</resource>
<resource>
<loadProperties loadWithoutData="true"/>
<properties isSystemResource="false" isBlinking="false"
isMapLayer="false" isHoverOn="false"
isVisible="true" />
<resourceData xsi:type="plotResourceData" plotSource="${legend} Sev"
plotModelFile="${svg3}"
retrieveData="false" isUpdatingOnMetadataOnly="false">
<binOffset posOffset="1800" negOffset="1800" virtualOffset="0"/>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="airep" constraintType="EQUALS" />
</mapping>
<mapping key="location.flightLevel">
<constraint constraintValue="${between}" constraintType="BETWEEN" />
</mapping>
</metadataMap>
</resourceData>
</resource>
</resourceData>
</resource>
</descriptor>
</displays>
</displayList>

View file

@ -24,6 +24,8 @@
<substitute key="svg0" value="pirepPlotDesign.svg"/>
<substitute key="svg1" value="pirepPlotDesign.svg"/>
<substitute key="legend" value="PIREP Plot 000-180 hft"/>
<substitute key="svg2" value="pirepPlotDesignSev.svg"/>
<substitute key="svg3" value="pirepPlotDesignSev.svg"/>
<substitute key="between" value="0--18000"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/PirepPlot.xml"
@ -31,6 +33,8 @@
<substitute key="svg0" value="pirepPlotDesign.svg"/>
<substitute key="svg1" value="pirepPlotDesign.svg"/>
<substitute key="legend" value="PIREP Plot 180-260 hft"/>
<substitute key="svg2" value="pirepPlotDesignSev.svg"/>
<substitute key="svg3" value="pirepPlotDesignSev.svg"/>
<substitute key="between" value="18000--26000"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/PirepPlot.xml"
@ -38,6 +42,8 @@
<substitute key="svg0" value="pirepPlotDesign.svg"/>
<substitute key="svg1" value="pirepPlotDesign.svg"/>
<substitute key="legend" value="PIREP Plot 260-500 hft"/>
<substitute key="svg2" value="pirepPlotDesignSev.svg"/>
<substitute key="svg3" value="pirepPlotDesignSev.svg"/>
<substitute key="between" value="26000--50000"/>
</contribute>
<contribute xsi:type="titleItem"
@ -47,6 +53,8 @@
<substitute key="svg0" value="pirepIcingDesign.svg"/>
<substitute key="svg1" value="airepIcingDesign.svg"/>
<substitute key="legend" value="PIREP Icing 000-180 hft"/>
<substitute key="svg2" value="pirepIcingDesignSev.svg"/>
<substitute key="svg3" value="airepIcingDesignSev.svg"/>
<substitute key="between" value="0--18000"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/PirepPlot.xml"
@ -54,6 +62,8 @@
<substitute key="svg0" value="pirepIcingDesign.svg"/>
<substitute key="svg1" value="airepIcingDesign.svg"/>
<substitute key="legend" value="PIREP Icing 180-260 hft"/>
<substitute key="svg2" value="pirepIcingDesignSev.svg"/>
<substitute key="svg3" value="airepIcingDesignSev.svg"/>
<substitute key="between" value="18000--26000"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/PirepPlot.xml"
@ -61,6 +71,8 @@
<substitute key="svg0" value="pirepIcingDesign.svg"/>
<substitute key="svg1" value="airepIcingDesign.svg"/>
<substitute key="legend" value="PIREP Icing 260-500 hft"/>
<substitute key="svg2" value="pirepIcingDesignSev.svg"/>
<substitute key="svg3" value="airepIcingDesignSev.svg"/>
<substitute key="between" value="26000--50000"/>
</contribute>
<contribute xsi:type="titleItem"
@ -70,6 +82,8 @@
<substitute key="svg0" value="pirepTurbDesign.svg"/>
<substitute key="svg1" value="airepTurbDesign.svg"/>
<substitute key="legend" value="PIREP Turb 000-180 hft"/>
<substitute key="svg2" value="pirepTurbDesignSev.svg"/>
<substitute key="svg3" value="airepTurbDesignSev.svg"/>
<substitute key="between" value="0--18000"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/PirepPlot.xml"
@ -77,6 +91,8 @@
<substitute key="svg0" value="pirepTurbDesign.svg"/>
<substitute key="svg1" value="airepTurbDesign.svg"/>
<substitute key="legend" value="PIREP Turb 180-260 hft"/>
<substitute key="svg2" value="pirepTurbDesignSev.svg"/>
<substitute key="svg3" value="airepTurbDesignSev.svg"/>
<substitute key="between" value="18000--26000"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/PirepPlot.xml"
@ -84,6 +100,8 @@
<substitute key="svg0" value="pirepTurbDesign.svg"/>
<substitute key="svg1" value="airepTurbDesign.svg"/>
<substitute key="legend" value="PIREP Turb 260-500 hft"/>
<substitute key="svg2" value="pirepTurbDesignSev.svg"/>
<substitute key="svg3" value="airepTurbDesignSev.svg"/>
<substitute key="between" value="26000--50000"/>
</contribute>
</menuTemplate>

View file

@ -1920,6 +1920,14 @@ class FWS_Overrides:
argDict["creationTime"] = self._getTime(self._creationDate, self._creationTime)
return None
def _parseTime(self,date,t,rtz):
try:
cTime = time.strptime(t + ' ' + date + ' ' + rtz, '%H%M %m/%d/%y %Z')
except ValueError:
cTime = time.strptime(t + ' ' + date + ' ' + rtz, '%H%M %m/%d/%Y %Z')
return cTime
def _getTime(self, date, t):
# Make a unix time integer from the given date and time strings
if t == "":
@ -1934,7 +1942,7 @@ class FWS_Overrides:
ptz = rtz[0:1]
offset = 0
if otz == ptz:
cTime = time.strptime(t + ' ' + date + ' ' + rtz, '%H%M %m/%d/%y %Z')
cTime = self._parseTime (date,t,rtz)
else:
if ptz == "E":
if otz == "E":
@ -1973,9 +1981,9 @@ class FWS_Overrides:
elif otz == "P":
offset = 0
if stz[1:3] == rtz[1:3]:
cTime = time.strptime(t + ' ' + date + ' ' + stz, '%H%M %m/%d/%y %Z')
cTime = self._parseTime (date,t,stz)
else:
cTime = time.strptime(t + ' ' + date + ' ' + dtz, '%H%M %m/%d/%y %Z')
cTime = self._parseTime (date,t,dtz)
return time.mktime(cTime) + offset*3600
@ -2004,9 +2012,7 @@ class FWS_Overrides:
otz = stz[0:1]
ptz = rtz[0:1]
if otz == ptz:
self._fireDateTime = time.strptime(
self._fireTime + ' ' + self._fireDate + ' ' + rtz,
'%H%M %m/%d/%y %Z')
self._fireDateTime = self._parseTime (self._fireDate,self._fireTime,rtz)
fcst = fcst + time.strftime(
'Forecast is based on ' + requestWords + ' time of %H%M %Z on %B %d. ',
self._fireDateTime)
@ -2049,19 +2055,19 @@ class FWS_Overrides:
elif otz == "P":
offset = 0
if stz[1:3] == rtz[1:3]:
self._fireDateTime = time.strptime(
self._fireTime + ' ' + self._fireDate + ' ' + stz,
'%H%M %m/%d/%y %Z')
self._fireDateTime = self._parseTime (self._fireDate,self._fireTime,stz)
tempTime = time.mktime(self._fireDateTime) + offset*3600
self._fireDateTime = time.localtime(tempTime)
else:
self._fireDateTime = time.strptime(
self._fireTime + ' ' + self._fireDate + ' ' + dtz,
'%H%M %m/%d/%y %Z')
self._fireDateTime = self._parseTime (self._fireDate,self._fireTime,dtz)
tempTime = time.mktime(self._fireDateTime) + offset*3600
self._fireDateTime = time.localtime(tempTime)
fireDateTime = time.strptime(
self._fireTime + ' ' + self._fireDate, '%H%M %m/%d/%y')
try:
fireDateTime = time.strptime(
self._fireTime + ' ' + self._fireDate, '%H%M %m/%d/%y')
except ValueError:
fireDateTime = time.strptime(
self._fireTime + ' ' + self._fireDate, '%H%M %m/%d/%Y')
fcst = fcst + time.strftime(
'Forecast is based on ' + requestWords + ' time of %H%M ' + rtz + ' on %B %d. ',
fireDateTime)

View file

@ -1795,9 +1795,9 @@ class SampleAnalysis(CommonUtils.CommonUtils):
timeRange = subRange
exec "result = " + primaryMethod
# Handle no data
# If a subRange has no data return None
# If a subRange has no data continue
if result is None:
return None
continue
statsByRange.append((result, subRange))
return statsByRange

View file

@ -84,6 +84,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Both not existing, set as MISSING
* Dec 07, 2012 1353 rferrel Make dialog non-blocking.
* Feb 05, 2013 1578 rferrel Changes for non-blocking singleton TimeSeriesDlg.
* Jun 15, 2015 16579 wkwock Add HSA filter.
*
* </pre>
*
@ -116,6 +117,11 @@ public class AlertAlarmValuesDlg extends CaveSWTDialog implements
*/
private Combo exceedingCbo;
/**
* HSA combo box.
*/
private Combo hsaCbo;
/**
* Sort by time radio button.
*/
@ -263,7 +269,7 @@ public class AlertAlarmValuesDlg extends CaveSWTDialog implements
*/
private void createTopControls() {
Composite topControlComp = new Composite(shell, SWT.NONE);
GridLayout topControlGl = new GridLayout(6, false);
GridLayout topControlGl = new GridLayout(8, false);
topControlComp.setLayout(topControlGl);
Label showLbl = new Label(topControlComp, SWT.NONE);
@ -326,6 +332,25 @@ public class AlertAlarmValuesDlg extends CaveSWTDialog implements
}
});
GridData hsagd = new GridData(100, SWT.DEFAULT);
Label hsaLbl = new Label(topControlComp, SWT.RIGHT);
hsaLbl.setText("HSA");
hsaLbl.setLayoutData(hsagd);
hsaCbo = new Combo(topControlComp, SWT.DROP_DOWN | SWT.READ_ONLY);
populateHsa();
hsaCbo.select(0);
hsaCbo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
queryAlertalarmval();
super.widgetSelected(e);
}
});
gd = new GridData(370, SWT.DEFAULT);
Label noteLbl = new Label(topControlComp, SWT.CENTER);
noteLbl.setText("Note: SupVal is ObsValue for forecast diff threats\n"
@ -333,6 +358,28 @@ public class AlertAlarmValuesDlg extends CaveSWTDialog implements
noteLbl.setLayoutData(gd);
}
/**
* Populate the HsaCbo
*/
private void populateHsa() {
hsaCbo.add("All HSAs");
String hsaSql = "select distinct(hsa) from location order by hsa";
java.util.List<Object[]> rs;
try {
rs = (java.util.List<Object[]>) DirectDbQuery.executeQuery(
hsaSql , HydroConstants.IHFS, QueryLanguage.SQL);
if (rs.size() > 0) {
for (Object[] oa : rs) {
hsaCbo.add((String) oa[0]);
}
}
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM, e.getMessage(), e);
}
}
/**
* Create the controls for sorting the data.
*/
@ -499,6 +546,11 @@ public class AlertAlarmValuesDlg extends CaveSWTDialog implements
myQuery.append(DIFF_CHECKSTR);
}
//HSA filter
if (!hsaCbo.getItem(hsaCbo.getSelectionIndex()).equalsIgnoreCase("All HSAs")) {
myQuery.append(" and hsa='"+hsaCbo.getItem(hsaCbo.getSelectionIndex())+"'");
}
// Build 'sort' options based on toggle buttons on the dialog.
if (locationRdo.getSelection()) {

View file

@ -80,6 +80,7 @@ import com.raytheon.viz.hydro.timeseries.util.GraphData;
import com.raytheon.viz.hydro.timeseries.util.GroupInfo;
import com.raytheon.viz.hydro.timeseries.util.LIDData;
import com.raytheon.viz.hydro.timeseries.util.PageInfo;
import com.raytheon.viz.hydro.timeseries.util.PreferredOrderManager;
import com.raytheon.viz.hydro.timeseries.util.TimeSeriesUtil;
import com.raytheon.viz.hydro.timeseries.util.TraceData;
import com.raytheon.viz.hydrocommon.HydroConstants;
@ -126,6 +127,8 @@ import com.raytheon.viz.hydrocommon.util.StnClassSyncUtil;
* Jul 21, 2015 4500 rjpeter Use Number in blind cast.
* Oct 13, 2015 4933 rferrel Log error if unable to find group definition file
* Fixed formatter resource leaks.
* 30 Oct, 2015 15102 wkwock Implements preferred order for PE-D-TS-EXT list
*
* </pre>
*
* @author lvenable
@ -1512,9 +1515,13 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog {
ArrayList<Object[]> data = (ArrayList<Object[]>) dataManager
.getSitePEData(selectedLid);
PreferredOrderManager pom = PreferredOrderManager.getInstance();
Map<String, String[]> peMap = pom.getPreferedOrder(selectedLid);
bottomDataList.removeAll();
/* Get the lists of PE data */
LinkedHashMap<String, ArrayList<SiteInfo>> preferredMap = new LinkedHashMap<String, ArrayList<SiteInfo>>();
LinkedHashMap<String, ArrayList<SiteInfo>> hMap = new LinkedHashMap<String, ArrayList<SiteInfo>>();
LinkedHashMap<String, ArrayList<SiteInfo>> qMap = new LinkedHashMap<String, ArrayList<SiteInfo>>();
LinkedHashMap<String, ArrayList<SiteInfo>> pMap = new LinkedHashMap<String, ArrayList<SiteInfo>>();
@ -1533,7 +1540,30 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog {
si.setExt((String) row[3]);
si.setDur(((Number) row[4]).intValue());
if (si.getPe().startsWith("H")) {
boolean preferredLstFlg = false;
if (peMap!=null){
String[] typeSrcLst = peMap.get(si.getPe());
if (typeSrcLst != null) {
for (String typesrc : typeSrcLst) {
if (typesrc.equalsIgnoreCase(si.getTs())) {
preferredLstFlg = true;
break;
}
}
} else if (peMap.containsKey(si.getPe())) {
preferredLstFlg = true;
}
}
if (preferredLstFlg) {
if (!si.getPe().equals(prevPE)) {
preferredMap.put(si.getPe(), new ArrayList<SiteInfo>());
prevPE = si.getPe();
}
preferredMap.get(si.getPe()).add(si);
} else if (si.getPe().startsWith("H")) {
if (!si.getPe().equals(prevPE)) {
hMap.put(si.getPe(), new ArrayList<SiteInfo>());
prevPE = si.getPe();
@ -1591,6 +1621,7 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog {
tsSelected = false;
}
populatePreferredDataInOrder(preferredMap,peMap);
processDataList(hMap, tsSelected);
processDataList(qMap, tsSelected);
processDataList(pMap, tsSelected);
@ -1601,7 +1632,41 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog {
selectedDataLbl.setText(selectedLid);
bottomDataList.setSelection(0);
} catch (VizException e) {
e.printStackTrace();
statusHandler.error("Failed to populate time series list",e);
}
}
/**
* populate data to bottomDataList base on preferred predefined order
* @param preferredMap
* @param peMap
*/
private void populatePreferredDataInOrder (LinkedHashMap<String, ArrayList<SiteInfo>>preferredMap, Map<String, String[]> peMap) {
if (peMap!=null && preferredMap!=null ){
for (String pe:peMap.keySet()){
java.util.List<SiteInfo> siList = preferredMap.get(pe);
if (siList == null) {
continue;
}
String[] tsList = peMap.get(pe);
if (tsList==null) { //There's PE but no TS in preffered_order.txt
for(SiteInfo si : siList) {
bottomDataList.add(formatDataLine(si));
siteInfoList.add(si);
}
} else { //There's both PE and TS in preferred_order.txt
for (String ts: tsList){
for(SiteInfo si : siList) {
if (ts.equalsIgnoreCase(si.getTs())) {
bottomDataList.add(formatDataLine(si));
siteInfoList.add(si);
}
}
}
}
}
}
}

View file

@ -0,0 +1,156 @@
package com.raytheon.viz.hydro.timeseries.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedHashMap;
import java.util.Map;
import com.raytheon.uf.common.localization.FileUpdatedMessage;
import com.raytheon.uf.common.localization.ILocalizationFileObserver;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.viz.hydrocommon.HydroConstants;
/**
* This class read the user preferred predefined PE-D-TS-EXT list from file:
* hydro/preferred_order.txt File format: lines start with # is a comment One
* line per LID LID PE1:TS1,TS2 PE2:TS2,TS3 ... Duplicated LID will replaced by
* last one.
*
* @author wkwock
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ---------- ---------- ----------- --------------------------
* 6/22/2015 DCS15102 wkwock Initial creation.
* </pre>
*/
public class PreferredOrderManager implements ILocalizationFileObserver {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(PreferredOrderManager.class);
private static PreferredOrderManager pom = null;
private Map<String, LinkedHashMap<String, String[]>> lidHm = new LinkedHashMap<String, LinkedHashMap<String, String[]>>();
private boolean readFileFlag = true;
private static final String COMMA_REGEX = "\\s*,\\s*";
// For remove space around commas.
private static final String COLON_REGEX = "\\s*:\\s*";
// For remove spaces around colons.
private static final String SPACE_REGEX = "\\s+";
private PreferredOrderManager() {
IPathManager pm = PathManagerFactory.getPathManager();
LocalizationFile file = pm
.getStaticLocalizationFile(HydroConstants.PREFERRED_ORDER);
if (file == null || !file.exists()) {
return;
}
file.addFileUpdatedObserver(this);
}
private void readPreferredOrderFile() {
IPathManager pm = PathManagerFactory.getPathManager();
LocalizationFile file = pm
.getStaticLocalizationFile(HydroConstants.PREFERRED_ORDER);
lidHm.clear();
if (file == null || !file.exists()) {
return;
}
StringBuilder message = new StringBuilder();
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
file.openInputStream()));
String line;
inloop: while ((line = in.readLine()) != null) {
String str = line.trim();
if (str.startsWith("#") || str.length() == 0) {
continue;// This is a comment or blank line
}
str = str.replaceAll(COMMA_REGEX, ",").replaceAll(COLON_REGEX,
":");
String[] lineSplit = str.split(SPACE_REGEX);
if (lineSplit.length < 2) {
message.append(line + "\n");
continue;
}
String lid = lineSplit[0].toUpperCase();
LinkedHashMap<String, String[]> peHm = new LinkedHashMap<String, String[]>();
for (int index = 1; index < lineSplit.length; index++) {
String[] peSplit = lineSplit[index].split(":");
if (peSplit.length > 2) {
message.append(line + "\n");
continue inloop;
}
String pe = peSplit[0].toUpperCase();
if (peSplit.length == 2) {
String[] tsSplit = peSplit[1].split(",");
peHm.put(pe, tsSplit);
} else {
peHm.put(pe, null);
}
}
lidHm.put(lid, peHm);
}
if (message.length() > 0) {
message.insert(0,"Invalid line in file "+HydroConstants.PREFERRED_ORDER+":\n");
message.append("Valid example: ACCM2 PP:RZ,RG TA:RZ\n");
}
} catch (IOException | LocalizationException e) {
message.append("Failed to read file "+HydroConstants.PREFERRED_ORDER);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
message.append("Failed to close file "+HydroConstants.PREFERRED_ORDER);
}
}
}
if (message.length() > 0) {
statusHandler.warn(message.toString());
}
}
public final static synchronized PreferredOrderManager getInstance() {
if (pom == null) {
pom = new PreferredOrderManager();
}
return pom;
}
public Map<String, String[]> getPreferedOrder(String lid) {
if (readFileFlag) {
readPreferredOrderFile();
readFileFlag = false;
}
Map<String, String[]> peMap = lidHm.get(lid);
return peMap;
}
@Override
public void fileUpdated(FileUpdatedMessage message) {
readFileFlag = true;
}
}

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.hydrobase;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@ -39,6 +40,7 @@ import com.raytheon.viz.hydrocommon.datamanager.HydroDataManager;
* ------------ ---------- ----------- --------------------------
* Sep 2, 2009 2259 mpduff Initial creation
* May 14, 2012 14965 wkwock Fix crash in query for data
* Jun 10, 2015 DCS15095 wkwock Added edit/insert flood event feature.
*
* </pre>
*
@ -69,7 +71,7 @@ public class FloodReportDataManager extends HydroDataManager {
* The selected location id.
*/
private String selectedLid = null;
/**
* The selected key for the dataMap.
*/
@ -149,6 +151,28 @@ public class FloodReportDataManager extends HydroDataManager {
return lidList;
}
/**
* Get a list of lids from the riverstat table.
*
* @param where
* The where clause to constrain the query
* @return ArrayList<String> of location ids
*/
public List<String> getLidListFromRiverStat(String where) {
List<String> lidList = new ArrayList<String>();
String query = "select distinct lid from riverstat ";
List<Object[]> rs = runQuery(query + where);
if (rs!=null) {
for (Object[] oa : rs) {
lidList.add((String) oa[0]);
}
}
return lidList;
}
/**
* Get Flood Report data.
*
@ -157,7 +181,8 @@ public class FloodReportDataManager extends HydroDataManager {
* @return FloodReportData object populated with data, null if problem or no
* data
*/
public ArrayList<FloodReportData> getFloodRptData(String lid, String start, String end) {
public ArrayList<FloodReportData> getFloodRptData(String lid, String start,
String end) {
ArrayList<FloodReportData> dataList = new ArrayList<FloodReportData>();
String lname = HydroDataCache.getInstance().getLocationMap().get(lid);
double fs = getFloodStage(lid);
@ -180,10 +205,10 @@ public class FloodReportDataManager extends HydroDataManager {
data.setLastCrest((Double) lastCrest[0]);
data.setLastCrestDate((Date) lastCrest[1]);
}
dataList.add(data);
}
return dataList;
}
@ -191,15 +216,14 @@ public class FloodReportDataManager extends HydroDataManager {
* Get the flood stage for the site.
*
* @param lid
* The site
* @return The flood stage for the site
*/
public double getFloodStage(String lid) {
double fs = -999;
ArrayList<Object[]> rs = runQuery("select fs from riverstat where lid = '"
List<Object[]> rs = runQuery("select fs from riverstat where lid = '"
+ lid + "'");
if ((rs != null) && (rs.size() > 0) && rs.get(0)[0]!=null) {
if ((rs != null) && (rs.size() > 0) && rs.get(0)[0] != null) {
fs = (Double) rs.get(0)[0];
}
@ -216,7 +240,7 @@ public class FloodReportDataManager extends HydroDataManager {
public String getRiverBasin(String lid) {
String basin = null;
ArrayList<Object[]> rs = runQuery("select rb from location where lid = '"
List<Object[]> rs = runQuery("select rb from location where lid = '"
+ lid + "'");
if (rs != null) {
basin = (String) rs.get(0)[0];
@ -235,7 +259,7 @@ public class FloodReportDataManager extends HydroDataManager {
public String getState(String lid) {
String state = null;
ArrayList<Object[]> rs = runQuery("select state from location where lid = '"
List<Object[]> rs = runQuery("select state from location where lid = '"
+ lid + "'");
if (rs != null) {
state = (String) rs.get(0)[0];
@ -254,7 +278,7 @@ public class FloodReportDataManager extends HydroDataManager {
public String getRiver(String lid) {
String river = null;
ArrayList<Object[]> rs = runQuery("select stream from riverstat where lid = '"
List<Object[]> rs = runQuery("select stream from riverstat where lid = '"
+ lid + "'");
if (rs != null) {
river = (String) rs.get(0)[0];
@ -273,9 +297,13 @@ public class FloodReportDataManager extends HydroDataManager {
public int[] getFloodEventIds(String lid, String start, String end) {
int[] id = null;
ArrayList<Object[]> rs = runQuery("select distinct flood_event_id from floodts where lid = '"
+ lid + "' and obstime >= '" + start + "' and obstime <= '" + end + "'");
List<Object[]> rs = runQuery("select distinct flood_event_id from floodts where lid = '"
+ lid
+ "' and obstime >= '"
+ start
+ "' and obstime <= '"
+ end + "'");
if ((rs != null) && (rs.size() > 0)) {
id = new int[rs.size()];
for (int i = 0; i < rs.size(); i++) {
@ -301,7 +329,7 @@ public class FloodReportDataManager extends HydroDataManager {
String query = "Select value, obstime from floodts where lid = '" + lid
+ "' and flood_event_id = " + id + " order by obstime";
ArrayList<Object[]> rs = runQuery(query);
List<Object[]> rs = runQuery(query);
lastCrest = new Object[rs.get(0).length];
Object[] retVal = new Object[2];
if ((rs != null) && (rs.size() > 0)) {
@ -343,6 +371,27 @@ public class FloodReportDataManager extends HydroDataManager {
return retVal;
}
/**
* get the max flood_event_id of a lid. Default to 0.
*
* @param lid
* @return
*/
public int getMaxFloodeventID(String lid) {
String query = "Select max(flood_event_id) from floodts where lid = '"
+ lid + "' and flood_event_id > 0";
List<Object[]> rs = runQuery(query);
Integer feID = new Integer(0);
if ((rs != null) && (rs.size() > 0)) {
feID = (Integer) rs.get(0)[0];
if (feID == null) {
return 0;
}
}
return feID.intValue();
}
/**
* Get the value and obstime from the floodts table.
*
@ -429,8 +478,7 @@ public class FloodReportDataManager extends HydroDataManager {
if ((ptsMissing[INDEX_PT_A] == false)
&& (ptsMissing[INDEX_PT_B] == false)) {
anchor1 = FloodReportUtils
.floodreptInterp(ptA, ptB, floodStage);
anchor1 = FloodReportUtils.floodreptInterp(ptA, ptB, floodStage);
ptsMissing[INDEX_ANCHOR1] = false;
} else {
if (ptA.getCrest() == floodStage) {
@ -443,8 +491,7 @@ public class FloodReportDataManager extends HydroDataManager {
}
/*
* get last Anchor point, use index to continue loop where we left
* off
* get last Anchor point, use index to continue loop where we left off
*/
for (int i = index; i < rs.size(); i++) {
if (findLastAnchor == false) {
@ -495,8 +542,7 @@ public class FloodReportDataManager extends HydroDataManager {
/* interpolate to find time of recession below flood stage */
if ((ptsMissing[INDEX_PT_C] == false)
&& (ptsMissing[INDEX_PT_D] == false)) {
anchor2 = FloodReportUtils
.floodreptInterp(ptC, ptD, floodStage);
anchor2 = FloodReportUtils.floodreptInterp(ptC, ptD, floodStage);
ptsMissing[INDEX_ANCHOR2] = false;
} else {
if (ptC.getCrest() == floodStage) {
@ -650,7 +696,8 @@ public class FloodReportDataManager extends HydroDataManager {
}
/**
* @param selectedKey the selectedKey to set
* @param selectedKey
* the selectedKey to set
*/
public void setSelectedKey(String selectedKey) {
this.selectedKey = selectedKey;

View file

@ -68,6 +68,7 @@ import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.hydrobase.addEditFloodTS.AddEditFloodEventDlg;
import com.raytheon.viz.hydrocommon.HydroConstants;
import com.raytheon.viz.hydrocommon.util.DbUtils;
import com.raytheon.viz.hydrocommon.util.RatingUtils;
@ -79,15 +80,16 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 4, 2008 2259 lvenable Initial creation
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 4, 2008 2259 lvenable Initial creation
* Dec 3, 2010 4952 lbousaidi
* Jan 13, 2011 5415 lbousaidi added a dialog when
* "Compute Latest data" button runs
* Jan 13, 2011 5415 lbousaidi added a dialog when
* "Compute Latest data" button runs
* May 14, 2012 14965 wkwock fix crash in query for data
* Jun 18, 2012 14377 wkwock Correct insert data into crest table.
* Jun 27, 2013 2088 rferrel Made dialog non-blocking.
* Jun 10, 2015 DCS15095 wkwock Added edit/insert flood event feature.
*
* </pre>
*
@ -140,6 +142,16 @@ public class FloodReportDlg extends CaveSWTDialog {
*/
private Button deleteBtn;
/**
* Edit event button
*/
private Button editEventBtn;
/**
* New event button
*/
private Button newEventBtn;
/**
* Above flood stage text control.
*/
@ -208,6 +220,8 @@ public class FloodReportDlg extends CaveSWTDialog {
private SimpleDateFormat dbFormat = null;
private SimpleDateFormat fr = null;
private AddEditFloodEventDlg efeDlg = null;
/**
* Constructor.
@ -335,6 +349,7 @@ public class FloodReportDlg extends CaveSWTDialog {
* Create the middle list and canvas controls.
*/
private void createMiddleControls() {
final int BUTTON_WIDTH=165;
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
Composite mainComp = new Composite(shell, SWT.NONE);
mainComp.setLayout(new GridLayout(2, false));
@ -405,7 +420,7 @@ public class FloodReportDlg extends CaveSWTDialog {
buttonComp.setLayoutData(gd);
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
gd.widthHint = 165;
gd.widthHint = BUTTON_WIDTH;
saveEventsBtn = new Button(buttonComp, SWT.PUSH);
saveEventsBtn.setText("Save Events to File...");
saveEventsBtn.setLayoutData(gd);
@ -417,7 +432,7 @@ public class FloodReportDlg extends CaveSWTDialog {
});
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
gd.widthHint = 165;
gd.widthHint = BUTTON_WIDTH;
deleteBtn = new Button(buttonComp, SWT.PUSH);
deleteBtn.setText("Delete Event");
deleteBtn.setLayoutData(gd);
@ -456,6 +471,30 @@ public class FloodReportDlg extends CaveSWTDialog {
}
});
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
gd.widthHint = BUTTON_WIDTH;
editEventBtn = new Button(buttonComp, SWT.PUSH);
editEventBtn.setText("Edit Event");
editEventBtn.setLayoutData(gd);
editEventBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
editEvent(false);
}
});
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
gd.widthHint = BUTTON_WIDTH;
newEventBtn = new Button(buttonComp, SWT.PUSH);
newEventBtn.setText("New Event");
newEventBtn.setLayoutData(gd);
newEventBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
editEvent(true);
}
});
// ----------------------------------------------------
// Create the Stage canvas composite
// ----------------------------------------------------
@ -980,6 +1019,32 @@ public class FloodReportDlg extends CaveSWTDialog {
}
}
/**
* Edit selected event or edit a new event base on @param newEvent.
*
* @param newEvent
*/
private void editEvent(boolean newEventFlg) {
String key = null;
if (!newEventFlg && locationList.getSelectionIndex() < 0) {
MessageBox mb = new MessageBox(shell, SWT.OK);
mb.setText("Make a Selection");
mb.setMessage("You must select a river observation!");
mb.open();
} else {
if (!newEventFlg) {
key=selectedKey;
}
if (efeDlg==null || efeDlg.isDisposed()) {
efeDlg = new AddEditFloodEventDlg(this.getParent(), key, this);
efeDlg.open();
} else {
efeDlg.bringToTop();
}
}
}
/**
* Get the text to output to the file.
*
@ -1265,4 +1330,9 @@ public class FloodReportDlg extends CaveSWTDialog {
}
shell.setCursor(cursor);
}
public void refreshReport() {
clearCanvas();
updateFloodList();
}
}

View file

@ -0,0 +1,450 @@
package com.raytheon.viz.hydrobase.addEditFloodTS;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map;
import java.util.TimeZone;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.viz.hydrobase.FloodReportData;
import com.raytheon.viz.hydrobase.FloodReportDataManager;
import com.raytheon.viz.hydrobase.FloodReportDlg;
import com.raytheon.viz.hydrocommon.HydroConstants;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
/**
* This class display the Edit Flood Event dialog.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ---------- ---------- ----------- --------------------------
* 6/10/2015 DCS15095 wkwock Initial creation
*
* </pre>
*
* @author wkwock
* @version 1.0
*/
public class AddEditFloodEventDlg extends CaveSWTDialog implements ITSCompositeAction {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(AddEditFloodEventDlg.class);
/**
* Location list control.
*/
private List lidsLst;
private Label lidLbl;
private Label stageLbl;
private SimpleDateFormat dateFormat = null;
private String lid = null;
private int floodEventID = -1;
private double floodStage = 0;
private String selectedKey;
private Composite obsComp;
private ScrolledComposite obsSComp;
private FloodReportDlg owner;
private LinkedList<TSComposite> tsLinkedList = null;
/**
* Constructor
*
* @param parent
* @param key
* @param owner
*/
public AddEditFloodEventDlg(Shell parent, String key, FloodReportDlg owner) {
super(parent, SWT.DIALOG_TRIM, CAVE.DO_NOT_BLOCK);
this.owner = owner;
this.selectedKey = key;
if (selectedKey == null) {
setText("Adding New Flood Event");
} else {
FloodReportDataManager dman = FloodReportDataManager.getInstance();
lid = dman.getSelectedLid();
floodStage = dman.getFloodStage(lid);
floodEventID = dman.getReportData().get(selectedKey)
.getFloodEventId();
setText("Editing Flood Event for " + lid);
}
dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
tsLinkedList = new LinkedList<TSComposite>();
};
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#constructShellLayout()
*/
@Override
protected Layout constructShellLayout() {
// Create the main layout for the shell.
GridLayout mainLayout = new GridLayout(1, false);
mainLayout.marginHeight = 2;
mainLayout.marginWidth = 2;
mainLayout.verticalSpacing = 2;
return mainLayout;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#disposed()
*/
@Override
protected void disposed() {
}
/*
* initialize components
*
* @see
* com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org
* .eclipse.swt.widgets.Shell)
*/
@Override
protected void initializeComponents(Shell shell) {
setReturnValue(false);
// Initialize all of the controls and layouts
initializeComponents();
}
/**
* Initialize the components on the display.
*/
private void initializeComponents() {
createControls();
createBottomButtons();
populateLIDLst();
populateObsComp();
}
/**
* Create the middle list and canvas controls.
*/
private void createControls() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
Composite mainComp = new Composite(shell, SWT.NONE);
mainComp.setLayout(new GridLayout(2, false));
mainComp.setLayoutData(gd);
gd = new GridData(SWT.DEFAULT, SWT.TOP, false, true);
Composite leftComp = new Composite(mainComp, SWT.NONE);
leftComp.setLayout(new GridLayout(1, false));
leftComp.setLayoutData(gd);
Label listLbl = new Label(leftComp, SWT.NONE);
listLbl.setText("Select a LID");
if (selectedKey == null) {
gd = new GridData(50, 400);
gd.horizontalSpan = 2;
lidsLst = new List(leftComp, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL);
lidsLst.setLayoutData(gd);
} else {
listLbl.setText("");// not use it
lidLbl = new Label(leftComp, SWT.None);
lidLbl.setText("LID: " + selectedKey);
stageLbl = new Label(leftComp, SWT.None);
stageLbl.setText("flood stage: " + floodStage);
}
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
Composite rightComp = new Composite(mainComp, SWT.NONE);
rightComp.setLayout(new GridLayout(1, false));
rightComp.setLayoutData(gd);
gd = new GridData();
gd.horizontalIndent = 4;
gd.horizontalSpan = 2;
Label obsListLbl = new Label(rightComp, SWT.NONE);
obsListLbl.setText("Observation");
obsListLbl.setLayoutData(gd);
obsSComp = new ScrolledComposite(rightComp, SWT.BORDER | SWT.V_SCROLL);
obsSComp.setLayoutData(new GridData(350, 400));
obsComp = new Composite(obsSComp, SWT.NONE);
obsComp.setLayout(new FormLayout());
obsSComp.setAlwaysShowScrollBars(true);
obsSComp.setContent(obsComp);
obsSComp.setExpandHorizontal(true);
obsSComp.setExpandVertical(true);
obsSComp.setMinSize(obsComp.computeSize(SWT.DEFAULT, SWT.DEFAULT));
Label topInsertLbl = new Label(obsComp, SWT.NONE);
topInsertLbl.setForeground(obsSComp.getDisplay().getSystemColor(
SWT.COLOR_GREEN));
topInsertLbl.setText("-->");
Cursor handCursor = this.getDisplay().getSystemCursor(SWT.CURSOR_HAND);
topInsertLbl.setCursor(handCursor);
FormData insertFd = new FormData();
insertFd.top = new FormAttachment(0, 4);
insertFd.left = new FormAttachment(0, 4);
topInsertLbl.setLayoutData(insertFd);
final AddEditFloodEventDlg floodEventDlg = this;
topInsertLbl.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent event) {
TSComposite tsComp= new TSComposite(obsComp, 0.0,TimeUtil.newGmtCalendar(),floodEventDlg );
tsLinkedList.add(0,tsComp);
reorganizeGui();
}
});
}
/**
* Create the buttons at the bottom of the dialog.
*/
private void createBottomButtons() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
Composite buttonComp = new Composite(shell, SWT.NONE);
buttonComp.setLayout(new GridLayout(2, true));
buttonComp.setLayoutData(gd);
int buttonWidth = 120;
gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
gd.widthHint = buttonWidth;
Button saveBtn = new Button(buttonComp, SWT.PUSH|SWT.LEFT);
saveBtn.setText("Save Event");
saveBtn.setLayoutData(gd);
saveBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
int status = saveNewEditTS();
if (status >= 0) {
close();
owner.refreshReport();
}
}
});
gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
gd.widthHint = buttonWidth;
Button cancelBtn = new Button(buttonComp, SWT.PUSH|SWT.RIGHT);
cancelBtn.setText("Cancel");
cancelBtn.setLayoutData(gd);
cancelBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
close();
}
});
}
/**
* populate LIDLst. LIDs are from riverstat table
*/
private void populateLIDLst() {
FloodReportDataManager dman = FloodReportDataManager.getInstance();
if (selectedKey == null) {
java.util.List<String> lidList = dman.getLidListFromRiverStat("");
Collections.sort(lidList);
lidsLst.removeAll();
for (String lid : lidList) {
lidsLst.add(lid);
}
} else {
dman.setSelectedKey(selectedKey);
lidLbl.setText("LID: " + lid);
}
}
/**
* Populate the observation composite
*/
private void populateObsComp() {
if (selectedKey == null) {
TSComposite tsComp= new TSComposite(obsComp, 0.0,TimeUtil.newGmtCalendar(), this);
tsLinkedList.add(0,tsComp);
reorganizeGui();
} else {
FloodReportDataManager dataManager = FloodReportDataManager
.getInstance();
Map<String, FloodReportData> dataMap = dataManager.getReportData();
dataManager.setSelectedKey(selectedKey);
FloodReportData floodData = dataMap.get(selectedKey);
java.util.List<Object[]> eventData = dataManager.getFloodEventData(
floodData.getLid(), floodData.getFloodEventId());
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm");
try {
for (Object[] oa : eventData) {
double val = (Double) oa[0];
String date = dateFormat.format((Date) oa[1]);
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(date));
TSComposite tsComp= new TSComposite(obsComp, val,cal,this);
tsLinkedList.add(tsComp);
reorganizeGui();
}
} catch (ParseException e) {
statusHandler.error("Failed to parse time", e);
}
}
}
/**
* Save this new time series to table floodts
*
* @return status:0 succeed to save data, -1 failed to save data.
*/
private int saveNewEditTS() {
FloodReportDataManager dman = FloodReportDataManager.getInstance();
String tsLID = this.lid;
int eventID = this.floodEventID;
if (selectedKey == null) {
tsLID = lidsLst.getSelection()[0];
eventID = dman.getMaxFloodeventID(tsLID) + 1;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:00");
StringBuilder sqlStr = new StringBuilder(
"insert into floodts (lid,obstime,flood_event_id,value) ");
boolean firstOneFlg = true;
try {
ListIterator<TSComposite> listIterator = tsLinkedList.listIterator();
while (listIterator.hasNext()) {
if (firstOneFlg) {
sqlStr.append("values ");
} else {
sqlStr.append(",");
}
TSComposite tsComp = listIterator.next();
sqlStr.append("('").append(tsLID).append("','")
.append(sdf.format(tsComp.getDateTime().getTime()))
.append("',").append(eventID).append(",")
.append(tsComp.getValue()).append(")");
firstOneFlg = false;
}
} catch (NumberFormatException nfe) {
MessageBox mbe = new MessageBox(shell, SWT.OK | SWT.ERROR);
mbe.setMessage("Error: an observe value is invalid. Please fix and try again.");
mbe.open();
return -1;
}
int status = 0;
try {
if (selectedKey != null) {
StringBuilder deleteSql = new StringBuilder();
deleteSql.append("delete from floodts where lid='")
.append(tsLID).append("' and flood_event_id=")
.append(eventID);
status = DirectDbQuery.executeStatement(deleteSql.toString(),
HydroConstants.IHFS, QueryLanguage.SQL);
}
status = DirectDbQuery.executeStatement(sqlStr.toString(),
HydroConstants.IHFS, QueryLanguage.SQL);
} catch (Exception e) {
MessageBox mbe = new MessageBox(shell, SWT.OK | SWT.ERROR);
mbe.setMessage("Failed to save data. Please check for observe time confliction.");
mbe.open();
return -1;
}
return status;
}
/**
* add a new TS composite to the linked list and the GUI
*/
@Override
public void addTSComp (TSComposite tsComp) {
int index = tsLinkedList.indexOf(tsComp);
TSComposite newTSComp= new TSComposite(obsComp, 0.0,TimeUtil.newGmtCalendar(),this);
tsLinkedList.add(index+1, newTSComp);
reorganizeGui();
}
/**
* Remove a TS composite from the linked list and the GUI
*/
@Override
public void removeTSComp (TSComposite tsComp) {
if (tsLinkedList.size()>1){
tsLinkedList.remove(tsComp);
tsComp.dispose();
reorganizeGui();
} else {
tsComp.setValue(0.0);
}
}
/**
* Reflect the tsLinkedList on the AddEditFloodEvent GUI
*/
private void reorganizeGui () {
ListIterator<TSComposite> listIterator = tsLinkedList.listIterator();
TSComposite lastTSComp = null;
TSComposite tsComp= null;
while (listIterator.hasNext()) {
tsComp=listIterator.next();
FormData tfd = new FormData();
if (lastTSComp==null) {
tfd.top = new FormAttachment(0, 20);
} else {
tfd.top = new FormAttachment(lastTSComp, 1);
}
tsComp.setLayoutData(tfd);
lastTSComp = tsComp;
}
obsComp.setSize(obsComp.computeSize(SWT.DEFAULT, SWT.DEFAULT));
obsSComp.setMinSize(obsComp.computeSize(SWT.DEFAULT, SWT.DEFAULT));
}
}

View file

@ -0,0 +1,22 @@
package com.raytheon.viz.hydrobase.addEditFloodTS;
/**
* Action interface in AddEditFloodEventDlg
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ---------- ---------- ----------- --------------------------
* 11/09/2015 DCS15095 wkwock Initial creation
*
* </pre>
*
* @author wkwock
* @version 1.0
*/
public interface ITSCompositeAction {
public void removeTSComp (TSComposite tsComp);
public void addTSComp(TSComposite tsComp);
}

View file

@ -0,0 +1,172 @@
package com.raytheon.viz.hydrobase.addEditFloodTS;
import java.util.Calendar;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
/**
* This composite customized with a insert label, an observation(a value text, 2
* time widgets), and a delete label.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ---------- ---------- ----------- --------------------------
* 11/05/2015 DCS15095 wkwock Initial creation
*
* </pre>
*
* @author wkwock
* @version 1.0
*/
public class TSComposite extends Composite {
private Text valueTxt;
private DateTime date;
private DateTime time;
private Label deleteLbl;
private Label insertLbl;
private ITSCompositeAction actionCallback = null;
/**
* Constructor for composite with observe value and time
*
* @param parent
* @param obsValue
* @param cal
* @param owner
*/
public TSComposite(Composite parent, double obsValue, Calendar cal, ITSCompositeAction owner) {
super(parent, SWT.NONE);
this.actionCallback = owner;
createAnObsComp();
setValue(obsValue);
setDateTime(cal);
}
/**
* set the value to the value text box
*
* @param obsValue
*/
public void setValue(double obsValue) {
valueTxt.setText(Double.toString(obsValue));
}
/**
* Get the value from the value text box
*
* @return double value
* @throws NumberFormatException
*/
public double getValue() throws NumberFormatException {
return Double.parseDouble(valueTxt.getText());
}
/**
* set date time to both date time box
*
* @param cal
*/
public void setDateTime(Calendar cal) {
date.setDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
cal.get(Calendar.DATE));
date.setTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), 0);
time.setDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
cal.get(Calendar.DATE));
time.setTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), 0);
}
/**
* Get date time
* @return date time
*/
public Calendar getDateTime() {
Calendar cal = Calendar.getInstance();
cal.set(date.getYear(), date.getMonth(), date.getDay(),
time.getHours(), time.getMinutes(), 0);
return cal;
}
/**
* create an observe composite
*/
private void createAnObsComp() {
FormLayout cfl = new FormLayout();
cfl.marginWidth = 5;
cfl.marginHeight = 2;
this.setLayout(cfl);
valueTxt = new Text(this, SWT.BORDER);
FormData vfd = new FormData();
vfd.width = 50;
vfd.height = 18;
valueTxt.setLayoutData(vfd);
valueTxt.setText("0.0");
date = new DateTime(this, SWT.DATE | SWT.BORDER);
FormData fd = new FormData();
fd.left = new FormAttachment(valueTxt, 10);
fd.width = 100;
date.setLayoutData(fd);
time = new DateTime(this, SWT.TIME | SWT.BORDER | SWT.SHORT);
FormData timeFd = new FormData();
timeFd.left = new FormAttachment(date, 10);
timeFd.width = 100;
time.setLayoutData(timeFd);
Cursor handCursor = this.getDisplay().getSystemCursor(SWT.CURSOR_HAND);
deleteLbl = new Label(this, SWT.NONE);
deleteLbl
.setForeground(this.getDisplay().getSystemColor(SWT.COLOR_RED));
deleteLbl.setText("x");
deleteLbl.setCursor(handCursor);
FormData dfd = new FormData();
dfd.left = new FormAttachment(time, 10);
dfd.top = new FormAttachment(this, 5);
deleteLbl.setLayoutData(dfd);
insertLbl = new Label(this, SWT.NONE);
insertLbl.setForeground(this.getDisplay().getSystemColor(
SWT.COLOR_GREEN));
insertLbl.setText("-->");
insertLbl.setCursor(handCursor);
FormData insertFd = new FormData();
insertFd.top = new FormAttachment(valueTxt, 4);
insertLbl.setLayoutData(insertFd);
final TSComposite tsComp=this;
deleteLbl.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent event) {
actionCallback.removeTSComp(tsComp);
}
});
insertLbl.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent event) {
actionCallback.addTSComp(tsComp);
}
});
}
}

View file

@ -33,6 +33,7 @@ import org.eclipse.swt.graphics.RGB;
* ------------ ---------- ----------- --------------------------
* Jun 17, 2008 1194 M. Duff Initial creation.
* 11/18/2008 1662 grichard Added physical element enum type.
* 14 Sep, 2015 15102 wkwock Implements preferred order for PE-D-TS-EXT list
*
* </pre>
*
@ -262,6 +263,8 @@ public class HydroConstants {
public static final String RFCMOSAIC_DIR_TOKEN = "gaq_xmrg_1hr_dir";
public static final String PREFERRED_ORDER = "/hydro/preferred_order.txt";
/**
* Enumeration used for selection of physical element.
*/

View file

@ -9,6 +9,7 @@
47.5281 -97.3250 2219.321 KMVX
64.5114 -165.2950 1806.983 PAEC
18.1157 -66.0782 1769.318 TJUA
35.3930 -97.6280 1769.318 TPSF
27.7839 -97.5108 1615.021 KCRP
45.7150 -122.9650 1510.339 KRTX
37.5908 -83.3131 1452.663 KJKL

View file

@ -56,6 +56,32 @@ class AirepPlotDelegate(PlotDelegate):
sampleString += turbType
return sampleString
def isValid(self, rec):
# DCS10257
# need icing or hazard
# only show non-severe / no severity
if rec.isValidParameter("iceInten"):
iceInten = rec.getString("iceInten")
else:
iceInten = ""
if rec.isValidParameter("iceType"):
iceType = rec.getString("iceType")
else:
iceType = ""
if rec.isValidParameter("flightHazard"):
flightHazard = rec.getInt("flightHazard")
else:
flightHazard = -1
if (iceInten == "") and (iceType == "") and (flightHazard == -1):
# no icing or hazard data
return False
elif (iceInten == "SEV") or (iceInten == "EXTRM") or (flightHazard == 8) or (flightHazard == 9):
# incorrect severity/hazard level (from AIREPWeather)
return False
else:
# low or no severity, and has some icing data
return True
plotDelegate = AirepPlotDelegate()
</script>
@ -83,6 +109,7 @@ plotDelegate = AirepPlotDelegate()
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleParams1" plotMode="sample" plotParam="stationId,longitude,latitude,timeObs,flightLevel"> </text>
<text id="sampleParams2" plotMode="sample" plotParam="temperature,windDir,windSpeed,turbInten,turbFreq,turbType"> </text>
<text id="validityParams" plotMode="null" class="text" plotParam="iceType,iceInten" x="0" y="0" visibility="hidden">0</text>
<text id="iceInensity" plotMode="table" class="weather" plotLookupTable="airep_icing_intens_trans.txt" plotParam="flightHazard" x="0" y="0">0</text>
<text id="fltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
</symbol>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,112 @@
<?xml version="1.0"?>
<svg width="80" height="80"
viewBox="0 0 80 80"
overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
import time
class AirepPlotDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
sampleString = "ARP "
sampleString += rec.getString("stationId")
sampleString += " "
lat = rec.getFloat("latitude")
if(lat &lt; 0):
sampleString += "%.3fS " % (-1*lat)
else:
sampleString += "%.3fN " % (lat)
lon = rec.getFloat("longitude")
if(lon &lt; 0):
sampleString += "%.3fW " % (-1*lon)
else:
sampleString += "%.3fE " % (lon)
timeObs = rec.getLong("timeObs")
sampleString += time.strftime("%H%M",time.localtime(timeObs/1000))
sampleString += " F%d" % (rec.getInt("flightLevel")/100)
temp = rec.getFloat("temperature")
if temp &lt; -273.15:
pass
elif temp &lt; 0:
sampleString += " M%d" % (int(-1*temp))
else:
sampleString += " P%d" % (int(temp))
windDir = int(rec.getFloat("windDir"))
windSpeed = int(rec.getFloat("windSpeed"))
if windDir > -1080 or windSpeed > 0:
sampleString += " %d/%dKT" % (windDir, windSpeed)
turbFreq = rec.getString("turbFreq")
turbInten = rec.getString("turbInten")
turbType = rec.getString("turbType")
if turbFreq != "" or turbInten != "" or turbType != "":
sampleString += " TB"
if turbFreq != "":
sampleString += " "
sampleString += turbFreq
if turbInten != "":
sampleString += " "
sampleString += turbInten
if turbType != "":
sampleString += " "
sampleString += turbType
return sampleString
def isValid(self, rec):
# DCS10257
# need icing severity or ice hazard
# only show severe
if rec.isValidParameter("iceInten"):
iceInten = rec.getString("iceInten")
else:
iceInten = ""
if rec.isValidParameter("flightHazard"):
flightHazard = rec.getInt("flightHazard")
else:
flightHazard = -1
if (iceInten == "SEV") or (iceInten == "EXTRM") or (flightHazard == 8) or (flightHazard == 9):
# high severity/hazard level (from AIREPWeather)
return True
else:
# low or no severity, and has some icing data
return False
plotDelegate = AirepPlotDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";
src: url(WindSymbols.svg#WindSymbols); }
@font-face { font-family: "StandardFont";
src: url(Standard.svg#Standard); }
@font-face { font-family: "WxSymbolFont";
src: url(WxSymbols.svg#WxSymbols); }
@font-face { font-family: "SpecialSymbolFont";
src: url(SpecialSymbols.svg#SpecialSymbols); }
text.text
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: StandardFont;
font-size: 1em;
}
]]>
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleParams1" plotMode="sample" plotParam="stationId,longitude,latitude,timeObs,flightLevel"> </text>
<text id="sampleParams2" plotMode="sample" plotParam="temperature,windDir,windSpeed,turbInten,turbFreq,turbType"> </text>
<text id="validityParams" plotMode="null" class="text" plotParam="iceType,iceInten" x="0" y="0" visibility="hidden">0</text>
<text id="iceInensity" plotMode="table" class="weather" plotLookupTable="airep_icing_intens_trans.txt" plotParam="flightHazard" x="0" y="0">0</text>
<text id="fltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
</symbol>
</defs>
<use id="wind" x="40" y="40" width="80" height="80" visibility="visible" xlink:href="#plotData"/>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -56,6 +56,32 @@ class AirepPlotDelegate(PlotDelegate):
sampleString += turbType
return sampleString
def isValid(self, rec):
# DCS10257
# need some turbulence data
# only show non-severe / no severity
if rec.isValidParameter("turbInten"):
turbInten = rec.getString("turbInten")
else:
turbInten = ""
if rec.isValidParameter("turbFreq"):
turbFreq = rec.getString("turbFreq")
else:
turbFreq = ""
if rec.isValidParameter("turbType"):
turbType = rec.getString("turbType")
else:
turbType = ""
if (turbInten == "") and (turbFreq == "") and (turbType == ""):
# no turbulence data present
return False
elif (turbInten == "SEV") or (turbInten == "EXTRM"):
# turbulence data present, but not correct severity
return False
else:
# turbulence data present, and if severity is present it is not high
return True
plotDelegate = AirepPlotDelegate()
</script>
@ -91,6 +117,7 @@ plotDelegate = AirepPlotDelegate()
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleParams1" plotMode="sample" plotParam="stationId,longitude,latitude,timeObs,flightLevel"> </text>
<text id="sampleParams2" plotMode="sample" plotParam="temperature,windDir,windSpeed,turbInten,turbFreq,turbType"> </text>
<text id="validityParams" plotMode="null" class="text" plotParam="turbType" x="0" y="0" visibility="hidden">0</text>
<text id="airepturbIntensity" plotMode="table" class="weather" plotLookupTable="turb_intens_trans.txt" plotParam="turbInten" x="0" y="0">0</text>
<text id="airepturbFreq" plotMode="table" class="weather" plotLookupTable="turb_freq_trans.txt" plotParam="turbFreq" style="text-anchor: end" x="0" y="-10">0</text>
<text id="airepfltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -0,0 +1,116 @@
<?xml version="1.0"?>
<svg width="80" height="80"
viewBox="0 0 80 80"
overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
import time
class AirepPlotDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
sampleString = "ARP "
sampleString += rec.getString("stationId")
sampleString += " "
lat = rec.getFloat("latitude")
if(lat &lt; 0):
sampleString += "%.3fS " % (-1*lat)
else:
sampleString += "%.3fN " % (lat)
lon = rec.getFloat("longitude")
if(lon &lt; 0):
sampleString += "%.3fW " % (-1*lon)
else:
sampleString += "%.3fE " % (lon)
timeObs = rec.getLong("timeObs")
sampleString += time.strftime("%H%M",time.localtime(timeObs/1000))
sampleString += " F%d" % (rec.getInt("flightLevel")/100)
temp = rec.getFloat("temperature")
if temp &lt; -273.15:
pass
elif temp &lt; 0:
sampleString += " M%d" % (int(-1*temp))
else:
sampleString += " P%d" % (int(temp))
windDir = int(rec.getFloat("windDir"))
windSpeed = int(rec.getFloat("windSpeed"))
if windDir > -1080 or windSpeed > 0:
sampleString += " %d/%dKT" % (windDir, windSpeed)
turbFreq = rec.getString("turbFreq")
turbInten = rec.getString("turbInten")
turbType = rec.getString("turbType")
if turbFreq != "" or turbInten != "" or turbType != "":
sampleString += " TB"
if turbFreq != "":
sampleString += " "
sampleString += turbFreq
if turbInten != "":
sampleString += " "
sampleString += turbInten
if turbType != "":
sampleString += " "
sampleString += turbType
return sampleString
def isValid(self, rec):
# DCS10257
# need some turbulence severity data
# only show non-severe / no severity
if rec.isValidParameter("turbInten"):
turbInten = rec.getString("turbInten")
else:
turbInten = ""
if (turbInten == "SEV") or (turbInten == "EXTRM"):
# turbulence data present, high severity
return True
else:
# turbulence data present, low severity
return False
plotDelegate = AirepPlotDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";
src: url(WindSymbols.svg#WindSymbols); }
@font-face { font-family: "StandardFont";
src: url(Standard.svg#Standard); }
@font-face { font-family: "WxSymbolFont";
src: url(WxSymbols.svg#WxSymbols); }
@font-face { font-family: "SpecialSymbolFont";
src: url(SpecialSymbols.svg#SpecialSymbols); }
text.text
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: StandardFont;
font-size: 1em;
}
text.weather
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: WxSymbolFont;
}
]]>
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleParams1" plotMode="sample" plotParam="stationId,longitude,latitude,timeObs,flightLevel"> </text>
<text id="sampleParams2" plotMode="sample" plotParam="temperature,windDir,windSpeed,turbInten,turbFreq,turbType"> </text>
<text id="airepturbIntensity" plotMode="table" class="weather" plotLookupTable="turb_intens_trans.txt" plotParam="turbInten" x="0" y="0">0</text>
<text id="airepturbFreq" plotMode="table" class="weather" plotLookupTable="turb_freq_trans.txt" plotParam="turbFreq" style="text-anchor: end" x="0" y="-10">0</text>
<text id="airepfltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
</symbol>
</defs>
<use id="wind" x="40" y="40" width="80" height="80" visibility="visible" xlink:href="#plotData"/>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -6,4 +6,5 @@ LGT : 125
LGTMOD : 194
MOD : 126
MODSEV : 195
SEV : 127
SEV : 127
EXTRM : 127

View file

@ -5,6 +5,65 @@ overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
import time
class PirepIcingDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
# use obsText for pirep
if rec.isValidParameter("obsText"):
return rec.getString("obsText")
# rebuild text for airep
sampleString = "ARP "
sampleString += " "
sampleString += " F%d" % (rec.getInt("flightLevel")/100)
try:
iceInten = rec.getString("iceInten")
except ValueError:
iceInten = ""
try:
iceType = rec.getString("iceType")
except ValueError:
icetype = ""
if iceInten != "" or iceType != "":
sampleString += " IC"
if iceInten != "":
sampleString += " "
sampleString += iceInten
if iceType != "":
sampleString += " "
sampleString += iceType
return sampleString
def isValid(self, rec):
# DCS10257
# need icing data
# only show non-severe / no severity
if rec.isValidParameter("iceInten"):
iceInten = rec.getString("iceInten")
else:
iceInten = ""
if rec.isValidParameter("iceType"):
iceType = rec.getString("iceType")
else:
iceType = ""
if (iceInten == "") and (iceType == ""):
# no icing data
return False
elif (iceInten == "SEV") or (iceInten == "EXTRM"):
# incorrect severity
return False
else:
# low or no severity, and has some icing data
return True
plotDelegate = PirepIcingDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";
@ -35,7 +94,8 @@ xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
]]>
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleText" plotMode="sample" plotParam="obsText"> </text>
<text id="sampleText" plotMode="sample" plotParam="obsText"> </text>
<text id="validityParams" plotMode="null" class="text" plotParam="iceType" x="0" y="0" visibility="hidden">0</text>
<text id="iceInensity" plotMode="table" class="weather" plotLookupTable="icing_intens_trans.txt" plotParam="iceInten" x="0" y="0">0</text>
<text id="fltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
<text id="iceType" plotMode="table" class="weather" plotLookupTable="icing_type_trans.txt" plotParam="iceType" style="text-anchor: end" x="0" y="-10">0</text>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -0,0 +1,99 @@
<?xml version="1.0"?>
<svg width="80" height="80"
viewBox="0 0 80 80"
overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
import time
class PirepIcingDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
# use obsText for pirep
if rec.isValidParameter("obsText"):
return rec.getString("obsText")
# rebuild text for airep
sampleString = "ARP "
sampleString += " "
sampleString += " F%d" % (rec.getInt("flightLevel")/100)
try:
iceInten = rec.getString("iceInten")
except ValueError:
iceInten = ""
try:
iceType = rec.getString("iceType")
except ValueError:
icetype = ""
if iceInten != "" or iceType != "":
sampleString += " IC"
if iceInten != "":
sampleString += " "
sampleString += iceInten
if iceType != "":
sampleString += " "
sampleString += iceType
return sampleString
def isValid(self, rec):
# DCS10257
# need icing severity data
# only show severe
if rec.isValidParameter("iceInten"):
iceInten = rec.getString("iceInten")
if (iceInten == "SEV") or (iceInten == "EXTRM"):
# high severity
return True
else:
# low or empty severity
return False
else:
# no severity data
return False
plotDelegate = PirepIcingDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";
src: url(WindSymbols.svg#WindSymbols); }
@font-face { font-family: "StandardFont";
src: url(Standard.svg#Standard); }
@font-face { font-family: "WxSymbolFont";
src: url(WxSymbols.svg#WxSymbols); }
@font-face { font-family: "SpecialSymbolFont";
src: url(SpecialSymbols.svg#SpecialSymbols); }
text.text
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: StandardFont;
font-size: 1em;
}
text.weather
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: WxSymbolFont;
}
]]>
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleText" plotMode="sample" plotParam="obsText"> </text>
<text id="iceInensity" plotMode="table" class="weather" plotLookupTable="icing_intens_trans.txt" plotParam="iceInten" x="0" y="0">0</text>
<text id="fltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
<text id="iceType" plotMode="table" class="weather" plotLookupTable="icing_type_trans.txt" plotParam="iceType" style="text-anchor: end" x="0" y="-10">0</text>
</symbol>
</defs>
<use id="wind" x="40" y="40" width="80" height="80" visibility="visible" xlink:href="#plotData"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -44,9 +44,19 @@ class PirepPlotDelegate(PlotDelegate):
windSpeed = int(rec.getFloat("windSpeed"))
if windDir > -1080 or windSpeed > 0:
sampleString += " %d/%dKT" % (windDir, windSpeed)
turbFreq = rec.getString("turbFreq")
turbInten = rec.getString("turbInten")
turbType = rec.getString("turbType")
try:
turbFreq = rec.getString("turbFreq")
except ValueError:
turbFreq = ""
try:
turbInten = rec.getString("turbInten")
except ValueError:
turbInten = ""
try:
turbType = rec.getString("turbType")
except ValueError:
turbType = ""
if turbFreq != "" or turbInten != "" or turbType != "":
sampleString += " TB"
if turbFreq != "":
@ -58,7 +68,45 @@ class PirepPlotDelegate(PlotDelegate):
if turbType != "":
sampleString += " "
sampleString += turbType
try:
iceInten = rec.getString("iceInten")
except ValueError:
iceInten = ""
try:
iceType = rec.getString("iceType")
except ValueError:
icetype = ""
if iceInten != "" or iceType != "":
sampleString += " IC"
if iceInten != "":
sampleString += " "
sampleString += iceInten
if iceType != "":
sampleString += " "
sampleString += iceType
return sampleString
def isValid(self, rec):
# DCS10257
# only show non-severe Turb/Ice data, non-UUA (urgent)
if rec.isValidParameter("obsText"):
obsText = rec.getString("obsText")
if "UUA" in obsText:
# urgent message
return False
if rec.isValidParameter("turbInten"):
turbInten = rec.getString("turbInten")
if (turbInten == "SEV") or (turbInten == "EXTRM"):
# high severity turbulence
return False
if rec.isValidParameter("iceInten"):
iceInten = rec.getString("iceInten")
if (iceInten == "SEV") or (iceInten == "EXTRM"):
# high severity turbulence, high severity icing
return False
# low or no severity, non-urgent data
return True
plotDelegate = PirepPlotDelegate()
@ -92,7 +140,8 @@ plotDelegate = PirepPlotDelegate()
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleParams1" plotMode="sample" plotParam="obsText,stationId,longitude,latitude,timeObs,flightLevel"> </text>
<text id="sampleParams2" plotMode="sample" plotParam="temperature,windDir,windSpeed,turbInten,turbFreq,turbType"> </text>
<text id="sampleParams2" plotMode="sample" plotParam="temperature,windDir,windSpeed,turbInten,turbFreq,turbType,iceInten,iceType"> </text>
<text id="validityParams" plotMode="null" class="text" plotParam="obsText,turbInten,iceInten" x="0" y="0" visibility="hidden">0</text>
<text id="fltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: start;" x="10px" y="-10px">75</text>
<text id="tempText" plotMode="text" plotParam="temperature" plotFormat="%3.0f" style="text-anchor: end;" x="-10px" y="-10px">75</text>
<g id="windVaneText" plotMode="barb" plotParam="windSpeed,windDir" plotUnit="kts" x="0" y="0" transform="rotate(0,0,0)">

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View file

@ -0,0 +1,155 @@
<?xml version="1.0"?>
<svg width="80" height="80"
viewBox="0 0 80 80"
overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
import time
class PirepPlotDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
# use obsText for pirep
if rec.isValidParameter("obsText"):
return rec.getString("obsText")
# rebuild text for airep
sampleString = "ARP "
sampleString += rec.getString("stationId")
sampleString += " "
lat = rec.getFloat("latitude")
if(lat &lt; 0):
sampleString += "%.3fS " % (-1*lat)
else:
sampleString += "%.3fN " % (lat)
lon = rec.getFloat("longitude")
if(lon &lt; 0):
sampleString += "%.3fW " % (-1*lon)
else:
sampleString += "%.3fE " % (lon)
timeObs = rec.getLong("timeObs")
sampleString += time.strftime("%H%M",time.localtime(timeObs/1000))
sampleString += " F%d" % (rec.getInt("flightLevel")/100)
temp = rec.getFloat("temperature")
if temp &lt; -273.15:
pass
elif temp &lt; 0:
sampleString += " M%d" % (int(-1*temp))
else:
sampleString += " P%d" % (int(temp))
windDir = int(rec.getFloat("windDir"))
windSpeed = int(rec.getFloat("windSpeed"))
if windDir > -1080 or windSpeed > 0:
sampleString += " %d/%dKT" % (windDir, windSpeed)
try:
turbFreq = rec.getString("turbFreq")
except ValueError:
turbFreq = ""
try:
turbInten = rec.getString("turbInten")
except ValueError:
turbInten = ""
try:
turbType = rec.getString("turbType")
except ValueError:
turbType = ""
if turbFreq != "" or turbInten != "" or turbType != "":
sampleString += " TB"
if turbFreq != "":
sampleString += " "
sampleString += turbFreq
if turbInten != "":
sampleString += " "
sampleString += turbInten
if turbType != "":
sampleString += " "
sampleString += turbType
try:
iceInten = rec.getString("iceInten")
except ValueError:
iceInten = ""
try:
iceType = rec.getString("iceType")
except ValueError:
icetype = ""
if iceInten != "" or iceType != "":
sampleString += " IC"
if iceInten != "":
sampleString += " "
sampleString += iceInten
if iceType != "":
sampleString += " "
sampleString += iceType
return sampleString
def isValid(self, rec):
# DCS10257
# only show non-severe Turb/Ice data, non-UUA (urgent)
if rec.isValidParameter("obsText"):
obsText = rec.getString("obsText")
if "UUA" in obsText:
# urgent message
return True
if rec.isValidParameter("turbInten"):
turbInten = rec.getString("turbInten")
if (turbInten == "SEV") or (turbInten == "EXTRM"):
# high severity turbulence
return True
if rec.isValidParameter("iceInten"):
iceInten = rec.getString("iceInten")
if (iceInten == "SEV") or (iceInten == "EXTRM"):
# high severity turbulence, high severity icing
return True
# low or no severity, non-urgent data
return False
plotDelegate = PirepPlotDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";
src: url(WindSymbols.svg#WindSymbols); }
@font-face { font-family: "StandardFont";
src: url(Standard.svg#Standard); }
@font-face { font-family: "WxSymbolFont";
src: url(WxSymbols.svg#WxSymbols); }
@font-face { font-family: "SpecialSymbolFont";
src: url(SpecialSymbols.svg#SpecialSymbols); }
text.barb
{
fill: none;
font-size: 1em;
font-size: 1em;
font-family: WindSymbolFont;
}
text.text
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: StandardFont;
font-size: 1em;
}
]]>
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleParams1" plotMode="sample" plotParam="obsText,stationId,longitude,latitude,timeObs,flightLevel"> </text>
<text id="sampleParams2" plotMode="sample" plotParam="temperature,windDir,windSpeed,turbInten,turbFreq,turbType,iceInten,iceType"> </text>
<text id="validityParams" plotMode="null" class="text" plotParam="obsText,turbInten,iceInten" x="0" y="0" visibility="hidden">0</text>
<text id="fltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: start;" x="10px" y="-10px">75</text>
<text id="tempText" plotMode="text" plotParam="temperature" plotFormat="%3.0f" style="text-anchor: end;" x="-10px" y="-10px">75</text>
<g id="windVaneText" plotMode="barb" plotParam="windSpeed,windDir" plotUnit="kts" x="0" y="0" transform="rotate(0,0,0)">
<text id="windVaneText" class="arrow" x="0" y="0">0</text>
<text id="windArrowText" class="barb" x="0" y="0">arrow</text>
</g>
</symbol>
</defs>
<use id="wind" x="40" y="40" width="80" height="80" visibility="visible" xlink:href="#plotData"/>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -5,6 +5,65 @@ overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
import time
class PirepTurbDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
# use obsText for pirep
if rec.isValidParameter("obsText"):
return rec.getString("obsText")
# rebuild text for airep
sampleString = "ARP "
sampleString += " "
sampleString += " F%d" % (rec.getInt("flightLevel")/100)
try:
turbFreq = rec.getString("turbFreq")
except ValueError:
turbFreq = ""
try:
turbInten = rec.getString("turbInten")
except ValueError:
turbInten = ""
if turbInten != "" or turbFreq != "":
sampleString += " TB"
if turbInten != "":
sampleString += " "
sampleString += turbInten
if turbFreq != "":
sampleString += " "
sampleString += turbFreq
return sampleString
def isValid(self, rec):
# DCS10257
# need some turbulence data
# only show non-severe
if rec.isValidParameter("turbInten"):
turbInten = rec.getString("turbInten")
else:
turbInten = ""
if rec.isValidParameter("turbFreq"):
turbFreq = rec.getString("turbFreq")
else:
turbFreq = ""
if (turbInten == "") and (turbFreq == ""):
# no turbulence data present
return False
elif (turbInten == "SEV") or (turbInten == "EXTRM"):
# turbulence data present, but not correct severity
return False
else:
# turbulence data present, and if severity is present it is not high
return True
plotDelegate = PirepTurbDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -0,0 +1,99 @@
<?xml version="1.0"?>
<svg width="80" height="80"
viewBox="0 0 80 80"
overflow="visible"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
<defs>
<script type="text/python" plotDelegate="plotDelegate">
import time
class PirepTurbDelegate(PlotDelegate):
def __init__(self):
PlotDelegate.__init__(self)
def getSampleText(self, rec):
# use obsText for pirep
if rec.isValidParameter("obsText"):
return rec.getString("obsText")
# rebuild text for airep
sampleString = "ARP "
sampleString += " "
sampleString += " F%d" % (rec.getInt("flightLevel")/100)
try:
turbFreq = rec.getString("turbFreq")
except ValueError:
turbFreq = ""
try:
turbInten = rec.getString("turbInten")
except ValueError:
turbInten = ""
if turbInten != "" or turbFreq != "":
sampleString += " TB"
if turbInten != "":
sampleString += " "
sampleString += turbInten
if turbFreq != "":
sampleString += " "
sampleString += turbFreq
return sampleString
def isValid(self, rec):
# DCS10257
# need turbulence severity data
# only show severe
if rec.isValidParameter("turbInten"):
turbInten = rec.getString("turbInten")
if (turbInten == "SEV") or (turbInten == "EXTRM"):
# high severity
return True
else:
# low or empty severity
return False
else:
# no turbulence severity data, so cannot have high turbulence severity
return False
plotDelegate = PirepTurbDelegate()
</script>
<style type="text/css">
<![CDATA[
@font-face { font-family: "WindSymbolFont";
src: url(WindSymbols.svg#WindSymbols); }
@font-face { font-family: "StandardFont";
src: url(Standard.svg#Standard); }
@font-face { font-family: "WxSymbolFont";
src: url(WxSymbols.svg#WxSymbols); }
@font-face { font-family: "SpecialSymbolFont";
src: url(SpecialSymbols.svg#SpecialSymbols); }
text.text
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: StandardFont;
font-size: 1em;
}
text.weather
{
fill: none;
font-size: 1em;
stroke-width: 1px;
font-family: WxSymbolFont;
}
]]>
</style>
<symbol overflow="visible" id="plotData" class="info">
<text id="sampleText" plotMode="sample" plotParam="obsText"> </text>
<text id="turbInensity" plotMode="table" class="weather" plotLookupTable="turb_intens_trans.txt" plotParam="turbInten" x="0" y="0">0</text>
<text id="fltLvlText" plotMode="text" plotParam="flightLevel" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
<text id="turbFreq" plotMode="table" class="weather" plotLookupTable="turb_freq_trans.txt" plotParam="turbFreq" style="text-anchor: end" x="0" y="-10">0</text>
</symbol>
</defs>
<use id="wind" x="40" y="40" width="80" height="80" visibility="visible" xlink:href="#plotData"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -822,160 +822,264 @@
</contribute>
<contribute xsi:type="subMenu" menuText="${icao} SW"
id="${icao}TerminalSpectrumWidth">
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev0} SW" id="${icao}Terminal${elev0}SpecWidth" suppressErrors="${suppressErrors0}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev0}--${elev0}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev1} SW" id="${icao}Terminal${elev1}SpecWidth" suppressErrors="${suppressErrors1}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev1}--${elev1}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev2} SW" id="${icao}Terminal${elev2}SpecWidth" suppressErrors="${suppressErrors2}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev2}--${elev2}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev3} SW" id="${icao}Terminal${elev3}SpecWidth" suppressErrors="${suppressErrors3}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev3}--${elev3}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev4} SW" id="${icao}Terminal${elev4}SpecWidth" suppressErrors="${suppressErrors4}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev4}--${elev4}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev5} SW" id="${icao}Terminal${elev5}SpecWidth" suppressErrors="${suppressErrors5}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev5}--${elev5}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev6} SW" id="${icao}Terminal${elev6}SpecWidth" suppressErrors="${suppressErrors6}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev6}--${elev6}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev7} SW" id="${icao}Terminal${elev7}SpecWidth" suppressErrors="${suppressErrors7}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev7}--${elev7}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev8} SW" id="${icao}Terminal${elev8}SpecWidth" suppressErrors="${suppressErrors8}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev8}--${elev8}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev9} SW" id="${icao}Terminal${elev9}SpecWidth" suppressErrors="${suppressErrors9}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev9}--${elev9}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev10} SW" id="${icao}Terminal${elev10}SpecWidth" suppressErrors="${suppressErrors10}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev10}--${elev10}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev11} SW" id="${icao}Terminal${elev11}SpecWidth" suppressErrors="${suppressErrors11}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev11}--${elev11}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev12} SW" id="${icao}Terminal${elev12}SpecWidth" suppressErrors="${suppressErrors12}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev12}--${elev12}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev13} SW" id="${icao}Terminal${elev13}SpecWidth" suppressErrors="${suppressErrors13}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev13}--${elev13}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev14} SW" id="${icao}Terminal${elev14}SpecWidth" suppressErrors="${suppressErrors14}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev14}--${elev14}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev15} SW" id="${icao}Terminal${elev15}SpecWidth" suppressErrors="${suppressErrors15}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev15}--${elev15}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev16} SW" id="${icao}Terminal${elev16}SpecWidth" suppressErrors="${suppressErrors16}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev16}--${elev16}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev17} SW" id="${icao}Terminal${elev17}SpecWidth" suppressErrors="${suppressErrors17}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev17}--${elev17}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev18} SW" id="${icao}Terminal${elev18}SpecWidth" suppressErrors="${suppressErrors18}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev18}--${elev18}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev19} SW" id="${icao}Terminal${elev19}SpecWidth" suppressErrors="${suppressErrors19}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev19}--${elev19}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev20} SW" id="${icao}Terminal${elev20}SpecWidth" suppressErrors="${suppressErrors20}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev20}--${elev20}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev21} SW" id="${icao}Terminal${elev21}SpecWidth" suppressErrors="${suppressErrors21}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev21}--${elev21}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev22} SW" id="${icao}Terminal${elev22}SpecWidth" suppressErrors="${suppressErrors22}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev22}--${elev22}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev23} SW" id="${icao}Terminal${elev23}SpecWidth" suppressErrors="${suppressErrors23}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev23}--${elev23}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="${elev24} SW" id="${icao}Terminal${elev24}SpecWidth" suppressErrors="${suppressErrors24}">
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="${elev24}--${elev24}" />
</contribute>
<contribute xsi:type="bundleItem" file="bundles/DefaultRadar.xml"
<contribute xsi:type="bundleItem" file="bundles/DefaultRadarBestRes.xml"
menuText="All SW" id="${icao}TerminalAllSpecWidth" >
<substitute key="icao" value="${icao}" />
<substitute key="product" value="185" />
<substitute key="product1" value="184" />
<substitute key="product2" value="185" />
<substitute key="product3" value="" />
<substitute key="product4" value="" />
<substitute key="mode" value="" />
<substitute key="elevation" value="0.0--360.0" />
</contribute>
</contribute>

View file

@ -0,0 +1,13 @@
# ----------------------------------------------------------------------------
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 09/09/2015 #16287 amoore Created
#
########################################################################
#Pattern for requested ISC parms.
#Alphanumeric pattern string form, potentially ending in _SFC
ISC_PARM_PATTERN="^[a-zA-Z0-9]+(?:_SFC)?$"

View file

@ -35,9 +35,10 @@
# 11/18/2014 #4953 randerso Added check for empty unit string
# 04/09/2015 #4383 dgilling Added support for FireWx ISC.
# Apr 23, 2015 4259 njensen Updated for new JEP API
# 09/01/2015 16287 amoore Additional validation of user input
#
########################################################################
import types
import types,re,configProps
from java.util import ArrayList,LinkedHashMap
from java.lang import Integer,Float
@ -431,7 +432,7 @@ def parseSat(satdata):
raise SyntaxError, "Invalid syntax for SATDATA" + `satdata`
return rval
def otherParse(serverhost, mhsid, port,
def otherParse(validSites, serverhost, mhsid, port,
initmodules, accumElem,
initskips, d2ddbver, logfilepurge, prddir, home,
extraWEPrec, vtecRequestTime, autoConfigureNotifyTextProd,
@ -489,6 +490,9 @@ def otherParse(serverhost, mhsid, port,
if type(r) != str:
raise TypeError, "REQUESTED_ISC_SITES not list of strings: " + \
`requestedISCsites`
#Verify requested ISC site is of desired pattern
elif r not in validSites:
raise ValueError, "Requested ISC site: " + str(r) + " could not be found in serverConfig.py."
else:
reqISCsites.add(r);
@ -501,15 +505,38 @@ def otherParse(serverhost, mhsid, port,
if type(r) != str:
raise TypeError, "REQUESTED_ISC_PARMS not list of strings: " + \
`requestedISCparms`
#Verify requested ISC parm is of desired pattern
elif not re.match(configProps.ISC_PARM_PATTERN, str(r)):
raise ValueError, "Requested ISC parm: " + str(r) + " does not match desired pattern: " + configProps.ISC_PARM_PATTERN
else:
reqISCparms.add(r)
if type(requestISC) != int:
raise TypeError, "REQUEST_ISC not an int: " + `requestISC`
if type(sendiscOnSave) != int:
raise TypeError, "SEND_ISC_ON_SAVE not an int: " + `sendiscOnSave`
if type(sendiscOnPublish) != int:
raise TypeError, "SEND_ISC_ON_PUBLISH not an int: " + `sendiscOnPublish`
if type(requestISC) != bool:
#If the type is boolean, it is already a valid value
#If the type is not boolean, and is not int, then it is not valid
if type(requestISC) != int:
raise TypeError, "REQUEST_ISC not an int or boolean: " + `requestISC`
#Verify request ISC is of valid value
elif not ((requestISC == 0) or (requestISC == 1)):
raise ValueError, "REQUEST_ISC is: " + `requestISC` + ", but expected True, False, 0 or 1"
if type(sendiscOnSave) != bool:
#If the type is boolean, it is already a valid value
#If the type is not boolean, and is not int, then it is not valid
if type(sendiscOnSave) != int:
raise TypeError, "SEND_ISC_ON_SAVE not an int or boolean: " + `sendiscOnSave`
#Verify send ISC on save is of valid value
elif not ((sendiscOnSave == 0) or (sendiscOnSave == 1)):
raise ValueError, "SEND_ISC_ON_SAVE is: " + `sendiscOnSave` + ", but expected True, False, 0 or 1"
if type(sendiscOnPublish) != bool:
#If the type is boolean, it is already a valid value
#If the type is not boolean, and is not int, then it is not valid
if type(sendiscOnPublish) != int:
raise TypeError, "SEND_ISC_ON_PUBLISH not an int or boolean: " + `sendiscOnPublish`
#Verify send ISC on publish is of valid value
elif not ((sendiscOnPublish == 0) or (sendiscOnPublish == 1)):
raise ValueError, "SEND_ISC_ON_PUBLISH is: " + `sendiscOnPublish` + ", but expected True, False, 0 or 1"
if type(transmitScript) not in [str, types.NoneType]:
raise TypeError, "TRANSMIT_SCRIPT not None or str: " + `transmitScript`

View file

@ -71,6 +71,7 @@
# 09/02/2015 #4819 rferrel Added HWRF.
# 10/07/2015 #4958 dgilling Added support for NationalBlend D2D data.
# 10/13/2015 #4961 randerso Updated NewTerrain/BaseTerrain database definitions
# 09/09/2015 16287 amoore Additional validation of user input
####################################################################################################
#----------------------------------------------------------------------------
@ -972,6 +973,15 @@ SITES = {
'NHA' : ([1833,1241], (41.5,5.0), (54.0,40.5), 'EST5EDT', Grid211, "nc"),
}
# Get list of valid office types, for validation.
VALID_OFFICE_TYPES = []
# List of all values of all sites.
for siteValues in SITES.values():
# Office type is the 5th element of each site's values
officeType = siteValues[5]
if officeType not in VALID_OFFICE_TYPES:
# A new office type
VALID_OFFICE_TYPES.append(officeType)
#---------------------------------------------------------------------------
#
@ -2238,11 +2248,17 @@ for wes, tc in (OFFICIALDBS + localISCParms):
for wes, officeType in (EXTRA_ISC_PARMS + localISCExtraParms):
if myOfficeType == officeType:
continue
if type(officeType) != str:
raise TypeError, "Office type not a str: " + `officeType`
else:
if officeType not in VALID_OFFICE_TYPES:
raise ValueError, "Office type: " + str(officeType) + " does not match any of the following: [" + (', '.join(VALID_OFFICE_TYPES)) + "]"
for we in wes:
wecopy = list(we)
wecopy[0] = wecopy[0] + officeType #rename the weather element
wecopy = tuple(wecopy)
ISCPARMS.append(([wecopy], TC1))
# Restore database parameter groupings (based on OFFICIALDBS, but TC1)
RESTOREPARMS = []
@ -2334,7 +2350,7 @@ def doIt():
sendiscOnSave, sendiscOnPublish, \
requestedISCparms, \
transmitScript) \
= doConfig.otherParse(\
= doConfig.otherParse(SITES.keys(), \
GFESUITE_SERVER, GFESUITE_MHSID, \
GFESUITE_PORT, INITMODULES,
D2DAccumulativeElements,

View file

@ -87,6 +87,8 @@ PHX PSR HAZ 0.6 0.6 0.6 1.0 3.7 7.4 0.6 11.2 15.0 19.3 0.6 25.7 34.7 3.7 0.6 7.4
PHX PSR MON 0.6 0.6 0.6 1.0 3.7 6.1 11.0 15.9 20.8 25.7 30.6 35.5 40.4 45.3 50.2 55.1 60.0
PIT PBZ HAZ 0.6 0.3 0.3 1.0 1.8 3.7 0.3 5.7 8.6 11.4 0.3 15.3 20.6 1.8 0.3 3.7 5.7 8.6 0.3 11.4 15.3 20.6 0.3
PIT PBZ MON 0.6 0.3 0.3 1.0 1.8 6.1 11.0 15.9 20.8 25.7 30.6 35.5 40.4 45.3 50.2 55.1 60.0
PSF OSF HAZ 0.3 0.3 1.0 2.5 5.1 0.3 7.7 11.5 15.3 0.3 20.4 27.4 1.0 0.3 2.5 5.1 7.7 0.3 11.5 15.3 20.4 0.3 27.4
PSF OSF MON 0.3 0.3 1.0 2.5 6.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0 50.0 55.0 60.0
RDU RAH HAZ 0.6 0.3 0.3 1.0 2.3 4.8 0.3 7.2 10.9 14.8 0.3 20.3 27.9 2.3 0.3 4.8 7.2 10.9 0.3 14.8 20.3 27.9 0.3
RDU RAH MON 0.6 0.3 0.3 1.0 2.3 6.1 11.0 15.9 20.8 25.7 30.6 35.5 40.4 45.3 50.2 55.1 60.0
SDF LMK HAZ 0.6 0.3 0.3 1.0 2.0 4.3 0.3 6.6 9.8 13.0 0.3 17.4 23.3 2.0 0.3 4.3 6.6 9.8 0.3 13.0 17.4 23.3 0.3

View file

@ -65,11 +65,12 @@
25 |16 |0 |0.25 |60 |V |Velocity |{S} {T} Velocity {B}bit ({U}) |{S} {T} Vel {B} |Radial |y | | | |V | | | | |1 |kts |
26 |16 |0 |0.50 |115 |V |Velocity |{S} {T} Velocity ({U}) |{S} {T} V |Radial |y | | | |V | | | | |1 |kts |
27 |16 |0 |1.00 |230 |V |Velocity |{S} {T} Velocity ({U}) |{S} {T} V |Radial |y | | | |V | | | | |1 |kts |
184|256 |0 |0.15 |90 |SW |Spectrum Width |{S} {T} Spec Width ({U}) |{S} {T} Spec Width |Radial |y | | | | | | | | |2 |kts | y
185|8 |0 |0.15 |90 |SW |Spectrum Width |{S} {T} Spec Width ({U}) |{S} {T} Spec Width |Radial |y | | | | | | | | |2 |kts |
28 |8 |0 |0.25 |60 |SW |Spectrum Width |{S} {T} Spectrum Width ({U}) {B}bit |{S} {T} SW {B}bit |Radial |y | | | | | | | | |2 |kts |
29 |8 |0 |0.50 |115 |SW |Spectrum Width |{S} {T} Spectrum Width ({U}) {B}bit |{S} {T} SW {B}bit |Radial |y | | | | | | | | |2 |kts |
30 |8 |0 |1.0 |230 |SW |Spectrum Width |{S} {T} Spectrum Width ({U}) {B}bit |{S} {T} SW {B}bit |Radial |y | | | | | | | | |2 |kts |
155|256 |0 |0.25 |300 |HSW |Spec Width |{S} {T} Spectrum Width ({U}) {B}bit |{S} {T} SW {B}bit |Radial |y | | | |5m | | | | |2 |kts/10 | y
155|256 |0 |0.25 |300 |HSW |Spec Width |{S} {T} Spectrum Width ({U}) {B}bit |{S} {T} SW {B}bit |Radial |y | | | |5m | | | | |2 |(m/s)/10| y
31 |16 |0 |2.0 |460 |USP |User Select Precip |{S} User Selectable Precip ({U}) |{S} USP |Radial | | | | | | |y | | |47 |in |
32 |256 |0 |1.0 |230 |DHR |Digital Hybrid Scan Refl |{S} Hybrid Scan Refl ({U}) |{S} DHR |Radial | | | | | | | | | |48 |dBZ/10 | y
33 |16 |0 |1.0 |230 |HSR |Hybrid Scan Reflectivity |{S} {B} bit Hyb Scan Refl ({U}) |{S} HSR |Radial | | | | | | | | | |64 |dBZ |

View file

@ -205,6 +205,7 @@ INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id"
INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id","eqp_elv","name","lon","lat","elevmeter",the_geom) VALUES ('TSTL','3043','3043.0000','LSX','646.6900','Lambert-St. Louis International Airp','-90.48900','38.80500','197.11111',GeometryFromText('POINT(-90.489 38.805)',4326) );
INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id","eqp_elv","name","lon","lat","elevmeter",the_geom) VALUES ('TTPA','3044','3044.0000','TBW','92.5200','Tampa International Airport','-82.51800','27.86000','28.20010',GeometryFromText('POINT(-82.518 27.86)',4326) );
INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id","eqp_elv","name","lon","lat","elevmeter",the_geom) VALUES ('TTUL','3045','3045.0000','TSA','823.2000','Tulsa International Airport','-95.82700','36.07100','250.91136',GeometryFromText('POINT(-95.827 36.071)',4326) );
INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id","eqp_elv","name","lon","lat","elevmeter",the_geom) VALUES ('TPSF','3046','3046.0000','OSF','1392.0604','Program Support Facility','-97.62800','35.39300','424.30000',GeometryFromText('POINT(-97.628 35.393)',4326) );
INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id","eqp_elv","name","lon","lat","elevmeter",the_geom) VALUES ('EERI','4105','4105.0000','CLE','1173.0000','Erie','-80.15700','42.01800','357.53040',GeometryFromText('POINT(-80.157 42.018)',4326) );
INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id","eqp_elv","name","lon","lat","elevmeter",the_geom) VALUES ('FQKW','4020','4020.0000','SEW','1513.0000','Makah','-124.67600','48.37200','461.16240',GeometryFromText('POINT(-124.676 48.372)',4326) );
INSERT INTO "awips"."radar_spatial" ("rda_id","rpg_id_dec","immutablex","wfo_id","eqp_elv","name","lon","lat","elevmeter",the_geom) VALUES ('FQWA','4043','4043.0000','BIS','2575.0000','Watford City','-103.78100','47.67900','784.86000',GeometryFromText('POINT(-103.781 47.679)',4326) );

View file

@ -138,6 +138,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* Jun 11, 2014 2061 bsteffen Remove IDecoderGettable
* Nov 06, 2014 16776 zwang Handle AMDA product
* Mar 25, 2015 4319 bsteffen Add volume scan number.
* Sep 09, 2015 17568 wkwock Fix incorrect 8-bit SW display
*
* </pre>
*
@ -913,7 +914,7 @@ public class RadarRecord extends PersistablePluginDataObject implements
}
double[] pix = { 256 - nLevels, 255 };
if (getProductCode() == 155) {
pix = new double[] { 129, 149 };
pix = new double[] { 129, 171 };
} else if(getProductCode() == 32) {
pix = new double[]{ 2, 256 };
}

View file

@ -28,12 +28,15 @@ import java.util.TimeZone;
public class SHEFTimezone {
public static final HashMap<String, TimeZone> sysTimeZones = new HashMap<String, TimeZone>();
public static final int TZ_NOTFOUND = -9999;
public static final TimeZone GMT_TIMEZONE = TimeZone
.getTimeZone(ShefConstants.Z);
private static final HashMap<String, TimeZoneEntry> timeZoneMap = new HashMap<String, TimeZoneEntry>();
static {
timeZoneMap.put("Z", new TimeZoneEntry("Z", 0, null,
"Zulu time, also Greenwich Mean Time (GMT)"));
@ -122,9 +125,25 @@ public class SHEFTimezone {
timeZoneMap.put("J",
new TimeZoneEntry("J", -480, TimeZone.getTimeZone("PRC"),
"China"));
timeZoneMap.put(
"G",
new TimeZoneEntry("G", -600, TimeZone
.getTimeZone("Pacific/Guam"), "Chamorro local time"));
timeZoneMap
.put("GS",
new TimeZoneEntry("GS", -600, TimeZone
.getTimeZone("Pacific/Guam"),
"Chamorro standard time"));
timeZoneMap.put(
"S",
new TimeZoneEntry("S", 660, TimeZone
.getTimeZone("Pacific/Samoa"), "Samoan local time"));
timeZoneMap.put(
"SS",
new TimeZoneEntry("SS", 660, TimeZone
.getTimeZone("Pacific/Samoa"), "Samoan standard time"));
}
public static final HashMap<String, TimeZone> sysTimeZones = new HashMap<String, TimeZone>();
static {
// Use this timezone to "clone" the daylight savings time rules.
for (String key : timeZoneMap.keySet()) {
@ -187,15 +206,6 @@ public class SHEFTimezone {
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
if(h == 1) {
GregorianCalendar g = (GregorianCalendar) c.clone();
g.set(Calendar.HOUR_OF_DAY, 0);
if(tz.inDaylightTime(g.getTime())) {
}
}
System.out.println(String.format("hour = %2d time = %s", h, sdf.format(c.getTime())));
}

View file

@ -46,7 +46,7 @@ import com.raytheon.uf.edex.database.dao.DaoConfig;
* Feb 13, 2014 #2783 dgilling Refactored to support running as part
* of an EDEX service.
* Jan 07, 2015 3692 bclement AlertalarmRecord is no longer a singleton
*
* Jul 02, 2015 16579 wkwock Add hsa filter
*
* </pre>
*
@ -66,6 +66,8 @@ class RecordMgr {
static final int PEFILTER = 105;
static final int HSAFILTER = 106;
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(RecordMgr.class);
@ -98,6 +100,7 @@ class RecordMgr {
.append(whereSubClauseFor(AA_CAT, opt))
.append(whereSubClauseFor(AA_CHCK, opt))
.append(whereSubClauseFor(PEFILTER, opt))
.append(whereSubClauseFor(HSAFILTER,opt))
.append(" AND (aav.ts NOT LIKE 'F%' OR aav.validtime >= current_timestamp) ")
.append(" ORDER BY aav.lid ASC, aav.pe, aav.ts, aav.aa_check, aav.validtime DESC ");
@ -132,6 +135,8 @@ class RecordMgr {
return aaCheckSubClause(options.getFilter());
case PEFILTER:
return peFilterSubClause(options.getPEfilter());
case HSAFILTER:
return hsaFilterSubClause(options.getHsa());
default:
return null;
}
@ -147,6 +152,10 @@ class RecordMgr {
return pe == null ? "" : " AND pe = " + pe;
}
private static String hsaFilterSubClause (String hsa) {
return hsa == null ? "" : " AND hsa = '" + hsa + "'";
}
private static String modeSubClause(ReportMode mode) {
if (mode == ReportMode.UNREPORTED) {
return " AND action_time IS NULL ";

View file

@ -40,6 +40,7 @@ import com.raytheon.uf.common.util.StringUtil;
* Jun 15, 2011 9377 jnjanga Initial creation
* Jul 12, 2013 15711 wkwock Fix verbose, observe mode, etc
* Feb 12, 2014 #2783 dgilling Major refactor, cleanup.
* Jul 02, 2015 16579 wkwock Add hsa filter
*
* </pre>
*
@ -65,6 +66,8 @@ class ReportOptions {
private static final String VERBOSE_MODE_KEY = "alarm_verbose";
private static final String HSA_KEY = "alarm_hsa_filter";
private static final EnumSet<ReportMode> IGNORE_MINS = EnumSet.of(
ReportMode.ALL, ReportMode.UNREPORTED, ReportMode.NEAREST,
ReportMode.LATEST_MAXFCST);
@ -86,6 +89,8 @@ class ReportOptions {
private boolean verboseFlag;
private String hsa = null;
/**
* @param appsDefaults
* @throws IllegalArgumentException
@ -119,6 +124,10 @@ class ReportOptions {
if (isMinutesGiven() && IGNORE_MINS.contains(this.mode)) {
statusHandler.warn("Minutes value ignored for this report mode.");
}
if (appsDefaults.getTokens().contains(HSA_KEY)) {
setHsa(appsDefaults.getToken(HSA_KEY));
}
}
public String getProductId() {
@ -218,6 +227,14 @@ class ReportOptions {
this.verboseFlag = verboseFlg;
}
public String getHsa() {
return hsa;
}
private void setHsa(String hsa) {
this.hsa = hsa;
}
public String getDbname() {
return DB_NAME;
}

View file

@ -1,8 +0,0 @@
#Wed Jan 11 13:37:48 CST 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -29,5 +29,17 @@
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="gov.noaa.nws.ost.edex.plugin.stq"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="gov.noaa.nws.ost.dataplugin.stq"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7" />
<classpathentry kind="con"
path="org.eclipse.pde.core.requiredPlugins" />
<classpathentry kind="src" path="src" />
<classpathentry kind="output" path="bin" />
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gov.noaa.nws.ost.dataplugin.stq</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,18 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Stq
Bundle-SymbolicName: gov.noaa.nws.ost.dataplugin.stq
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: gov.noaa.nws
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: com.raytheon.edex.common,
com.raytheon.uf.edex.decodertools,
com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.serialization,
com.raytheon.uf.common.pointdata,
com.raytheon.uf.edex.pointdata,
com.raytheon.uf.common.geospatial,
org.geotools,
javax.persistence,
javax.measure
Export-Package: gov.noaa.nws.ost.dataplugin.stq

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,509 @@
package gov.noaa.nws.ost.dataplugin.stq;
import java.util.Calendar;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.xml.bind.annotation.XmlAttribute;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject;
import com.raytheon.uf.common.geospatial.ISpatialEnabled;
import com.raytheon.uf.common.pointdata.IPointData;
import com.raytheon.uf.common.pointdata.PointDataView;
import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.vividsolutions.jts.geom.Geometry;
/**
* SpotRequestRecord is the Data Access component for Spot Forecast Request
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* -------------- ---------- ----------- --------------------------
* July 17, 2015 Pwang Initial creation for STQ: Spot Request
* Data plugin
*
* </pre>
*
* @author pwang
* @version 1.0
*/
@Entity
@SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "stqseq")
@Table(name = "stq", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) })
/*
* Both refTime and forecastTime are included in the refTimeIndex since
* forecastTime is unlikely to be used.
*/
@DynamicSerialize
public class SpotRequestRecord extends PersistablePluginDataObject implements
ISpatialEnabled, IPointData {
private static final long serialVersionUID = 1L;
private static final String pluginName = "stq";
private static final String stqDispSymbol = "S";
/*
* Project key, such as FGOWB, which can be used for identify the STQ requests
* Extract from ofile, 2nd segment, such as
* FGOWB from 20150530.FGOWV.01
*/
@DataURI(position = 1)
@Column(nullable = false)
@DynamicSerializeElement
@XmlAttribute
private String ofileKey;
@DataURI(position = 2)
@Column(nullable = false)
@DynamicSerializeElement
@XmlAttribute
private String ofileVersion;
@Embedded
@DataURI(position = 3, embedded = true)
@DynamicSerializeElement
private SurfaceObsLocation location;
// Site received the request, such as BYZ
@Column(nullable = false)
@DynamicSerializeElement
@XmlAttribute
private String site;
@Embedded
@DynamicSerializeElement
private PointDataView pointDataView;
// Project Name
@Column(length = 32)
@DynamicSerializeElement
@XmlAttribute
private String projectName;
// Text of the WMO header
@Transient
@DynamicSerializeElement
private String wmoHeader = "";
@Transient
@DynamicSerializeElement
private String reqOfficial;
@Transient
@DynamicSerializeElement
private String emPhone;
//Time Zone
@Transient
@DynamicSerializeElement
private String timeZone;
// State
@Transient
@DynamicSerializeElement
private String state;
// bottom elevation
@Transient
@DynamicSerializeElement
private int bottomElevation;
// Top elevation
@Column
@DynamicSerializeElement
@XmlAttribute
private int topElevation;
// size (acres)
@Transient
@DynamicSerializeElement
private int sizeAcres;
@Transient
@DynamicSerializeElement
private String stqSymbol = stqDispSymbol;
/**
*
*/
public SpotRequestRecord() {
}
/**
* Constructor for DataURI construction through base class. This is used by
* the notification service.
*
* @param uri
* A data uri applicable to this class.
* @param tableDef
* The table definitions for this class.
*/
public SpotRequestRecord(String dataUri) {
super(dataUri);
}
/**
* Override method getPluginMNmae
*/
@Override
public String getPluginName() {
return pluginName;
}
/**
* Get OFile Key
* @return
*/
public String getOfileKey() {
return ofileKey;
}
/**
* Set OFile Key
* @param ofileKey
*/
public void setOfileKey(String ofileKey) {
this.ofileKey = ofileKey;
}
/**
* Get OFile Version
* @return
*/
public String getOfileVersion() {
return ofileVersion;
}
/**
* Set OFile Version
* @param ofileVersion
*/
public void setOfileVersion(String ofileVersion) {
this.ofileVersion = ofileVersion;
}
/**
* Get Site
* @return
*/
public String getSite() {
return site;
}
/**
* Set Site
* @param site
*/
public void setSite(String site) {
this.site = site;
}
/**
* Get SpatialObject: SurfaceObsLocation
* @return
*/
@Override
public SurfaceObsLocation getSpatialObject() {
return location;
}
/**
* Get location
* @return
*/
public SurfaceObsLocation getLocation() {
return location;
}
/**
* Set Location
* @param location: SurfaceObsLocation
*/
public void setLocation(SurfaceObsLocation location) {
this.location = location;
}
/**
* Get this observation's geometry.
*
* @return The geometry for this observation.
*/
public Geometry getGeometry() {
return location.getGeometry();
}
/**
* Get the geometry latitude.
*
* @return The geometry latitude.
*/
public double getLatitude() {
return location.getLatitude();
}
/**
* Get the geometry longitude.
*
* @return The geometry longitude.
*/
public double getLongitude() {
return location.getLongitude();
}
/**
* Set latitude
* @param latitude
*/
public void setLatitude(float latitude) {
location.setLatitude(latitude);
}
/**
* Set longitude
* @param longitude
*/
public void setLongitude(float longitude) {
location.setLongitude(longitude);
}
/**
* Get Project Name
* @return
*/
public String getProjectName() {
return projectName;
}
/**
* Set Project name
* @param projectName
*/
public void setProjectName(String projectName) {
this.projectName = projectName;
}
/**
* Get PointDataView
* @return PointDataView
*/
@Override
public PointDataView getPointDataView() {
return pointDataView;
}
@Override
public void setPointDataView(PointDataView pointDataView) {
this.pointDataView = pointDataView;
}
/**
* Get WMO Header
* @return
*/
public String getWmoHeader() {
return wmoHeader;
}
/**
* Set WMO Header
* @param wmoHeader
*/
public void setWmoHeader(String wmoHeader) {
this.wmoHeader = wmoHeader;
}
/**
* Get TimeZone
* @return
*/
public String getTimeZone() {
return timeZone;
}
/**
* Set TimeZone
* @param timeZone
*/
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getState() {
return state;
}
/**
* Set State
* @param state
*/
public void setState(String state) {
this.state = state;
}
/**
* Get Bottom Elevation
* @return
*/
public int getBottomElevation() {
return bottomElevation;
}
/**
* Set Bottom Elevation
* @param bottomElevation
*/
public void setBottomElevation(int bottomElevation) {
this.bottomElevation = bottomElevation;
}
/**
* Get Top Elevation
* @return
*/
public int getTopElevation() {
return topElevation;
}
/**
* Set Top Elevation
* @param topElevation
*/
public void setTopElevation(int topElevation) {
this.topElevation = topElevation;
}
/**
* Get Size of Spot
* @return
*/
public int getSizeAcres() {
return sizeAcres;
}
public void setSizeAcres(int sizeAcres) {
this.sizeAcres = sizeAcres;
}
/**
* Get the station identifier for this observation.
*
* @return the stationId
*/
public String getStationId() {
return location.getStationId();
}
/**
* Get the elevation, in meters, of the observing platform or location.
*
* @return The observation elevation, in meters.
*/
public Integer getElevation() {
return location.getElevation();
}
/**
* Get whether the location for this observation is defined.
*
* @return Is this location defined.
*/
public Boolean getLocationDefined() {
return location.getLocationDefined();
}
/**
* get DataURI
*/
@Override
@Column
@Access(AccessType.PROPERTY)
public String getDataURI() {
return super.getDataURI();
}
/**
* Set the data uri for this observation.
*
* @param dataURI
*/
@Override
public void setDataURI(String dataURI) {
super.setDataURI(dataURI);
identifier = dataURI;
}
/**
* Get Request Official Name
* @return
*/
public String getReqOfficial() {
return reqOfficial;
}
/**
* Set Request Official Name
* @param reqOfficial
*/
public void setReqOfficial(String reqOfficial) {
this.reqOfficial = reqOfficial;
}
/**
* Get Requester's Emergency Phone Number
* @return
*/
public String getEmPhone() {
return emPhone;
}
/**
* Set Requester's Emergency Phone Number
* @param emPhone
*/
public void setEmPhone(String emPhone) {
this.emPhone = emPhone;
}
/**
* Get Symbol
* @return
*/
public String getStqSymbol() {
return stqSymbol;
}
/**
* toString
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Calendar c = getDataTime().getRefTimeAsCalendar();
if (c != null) {
sb.append(String.format("STQ:%1$tY%1$tm%1$td%1$tH%1$tM",
getDataTime().getRefTimeAsCalendar()));
} else {
sb.append("STQ:YYYYMMDDHHmm");
}
sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude()));
return sb.toString();
}
}

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7" />
<classpathentry kind="con"
path="org.eclipse.pde.core.requiredPlugins" />
<classpathentry kind="src" path="src" />
<classpathentry kind="output" path="bin" />
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gov.noaa.nws.ost.edex.plugin.stq</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,22 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Stq
Bundle-SymbolicName: gov.noaa.nws.ost.edex.plugin.stq
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: gov.noaa.nws
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: com.raytheon.edex.common,
com.raytheon.uf.edex.decodertools,
com.raytheon.uf.common.pointdata,
com.raytheon.uf.edex.pointdata,
org.geotools,
org.apache.commons.logging,
org.dom4j,
javax.persistence,
javax.measure
Export-Package: gov.noaa.nws.ost.edex.plugin.stq
Import-Package: com.raytheon.uf.common.status,
com.raytheon.uf.common.wmo,
gov.noaa.nws.ost.dataplugin.stq,
gov.noaa.nws.ost.edex.plugin.stq

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/

View file

@ -0,0 +1,12 @@
<?xml version='1.0' encoding='UTF-8'?>
<pointDataDescription>
<parameter name="projectName" numDims="1" type="STRING" />
<parameter name="reqOfficial" numDims="1" type="STRING" />
<parameter name="emPhone" numDims="1" type="STRING" />
<parameter name="timeZone" numDims="1" type="STRING" />
<parameter name="state" numDims="1" type="STRING" />
<parameter name="bottomElevation" numDims="1" type="INT" />
<parameter name="topElevation" numDims="1" type="INT" />
<parameter name="sizeAcres" numDims="1" type="INT" />
<parameter name="stqSymbol" numDims="1" type="STRING" />
</pointDataDescription>

View file

@ -0,0 +1,10 @@
<?xml version='1.0' encoding='UTF-8'?>
<pointDataDbDescription>
<parameter name="stationId" queryName="location.stationId"
type="STRING" />
<parameter name="latitude" queryName="location.latitude"
type="FLOAT" unit="°" />
<parameter name="longitude" queryName="location.longitude"
type="FLOAT" unit="°" />
<parameter name="dataURI" queryName="dataURI" type="STRING" />
</pointDataDbDescription>

View file

@ -0,0 +1,20 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="stqPluginName" class="java.lang.String">
<constructor-arg type="java.lang.String" value="stq" />
</bean>
<bean id="stqProperties" class="com.raytheon.uf.common.dataplugin.PluginProperties">
<property name="pluginName" ref="stqPluginName" />
<property name="pluginFQN" value="gov.noaa.nws.ost.dataplugin.stq" />
<property name="dao"
value="gov.noaa.nws.ost.edex.plugin.stq.SpotRequestRecordDAO" />
<property name="record"
value="gov.noaa.nws.ost.dataplugin.stq.SpotRequestRecord" />
</bean>
<bean id="stqRegistered" factory-bean="pluginRegistry"
factory-method="register">
<constructor-arg ref="stqPluginName" />
<constructor-arg ref="stqProperties" />
</bean>
</beans>

View file

@ -0,0 +1,41 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean class="com.raytheon.uf.common.logback.appender.ThreadBasedAppender"
factory-method="registerThreadPattern">
<constructor-arg value="stq" />
<constructor-arg value="Ingest.stq.*" />
</bean>
<bean id="stqDecoder" class="gov.noaa.nws.ost.edex.plugin.stq.SpotRequestDecoder">
<constructor-arg ref="stqPluginName" />
</bean>
<bean id="stqDistRegistry" factory-bean="distributionSrv"
factory-method="register">
<constructor-arg ref="stqPluginName" />
<constructor-arg value="jms-durable:queue:Ingest.Stq" />
</bean>
<camelContext id="stq-camel"
xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<!-- Begin STQ routes -->
<route id="stqIngestRoute">
<from uri="jms-durable:queue:Ingest.Stq" />
<setHeader headerName="pluginName">
<constant>stq</constant>
</setHeader>
<doTry>
<pipeline>
<bean ref="stringToFile" />
<pipeline>
<bean ref="stqDecoder" method="decodeFile" />
<to uri="direct-vm:persistIndexAlert" />
</pipeline>
</pipeline>
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:stq?level=ERROR" />
</doCatch>
</doTry>
</route>
</camelContext>
</beans>

View file

@ -0,0 +1,116 @@
package gov.noaa.nws.ost.edex.plugin.stq;
import gov.noaa.nws.ost.dataplugin.stq.SpotRequestRecord;
import java.io.File;
import com.raytheon.edex.esb.Headers;
import com.raytheon.edex.exception.DecoderException;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.pointdata.PointDataDescription;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import gov.noaa.nws.ost.edex.plugin.stq.SpotRequestRecordDAO;
/**
* AWIPS decoder adapter strategy for Spot Forecast Request data.<br/>
*
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* July 23, 2015 17366 pwang Initial implementation of SpotRequestDecoder
* Oct 30, 2015 17366 pwang Added error handling for DAO, PDD creation
*
* </pre>
*
* @author pwang
* @version 1.0
*/
public class SpotRequestDecoder {
private IUFStatusHandler logger = UFStatus
.getHandler(SpotRequestDecoder.class);
private static final String STQ_PDD_RES_FILE = "/res/pointdata/stq.xml";
private final String pluginName;
private PointDataDescription pdd = null;
private SpotRequestRecordDAO dao = null;
/**
* Construct a Spot Request decoder
*/
public SpotRequestDecoder(String pluginName) {
this.pluginName = pluginName;
}
/**
* Get the next decoded data record.
*
* @return One record of decoded data.
* @throws DecoderException
* Thrown if no data is available.
*/
public PluginDataObject[] decodeFile(File inputFile, Headers headers)
throws DecoderException {
logger.debug("STQ Decoder: start decode " + inputFile.getName());
SpotRequestRecord[] records = new SpotRequestRecord[1];
this.createPointDataDescription();
this.createDAO();
SpotRequestParser srp = new SpotRequestParser(inputFile, pdd, dao);
records[0] = srp.parse();
if (records.length > 0) {
SpotRequestRecord r = records[0];
logger.debug("STQ Record: dataURI = " + r.getDataURI());
}
return records;
}
/**
* Create DAO Object
* @throws DecoderException
*/
protected void createDAO()
throws DecoderException {
try {
if(null == dao) {
dao = new SpotRequestRecordDAO(pluginName);
}
} catch (Exception e) {
logger.error("SpotRequestRecordDAO object creation failed", e);
throw new DecoderException("STQ Decoder: create SpotRequestRecordDAO object creation failed", e);
}
}
/**
* Create PointDataDescription
* @throws DecoderException
*/
protected void createPointDataDescription()
throws DecoderException {
try {
if(null == pdd) {
pdd = PointDataDescription.fromStream(this.getClass()
.getResourceAsStream(STQ_PDD_RES_FILE));
}
} catch (Exception e) {
logger.error("STQ PointDataDescription object failed", e);
throw new DecoderException("STQ Decoder: create PointDataDescription object creation failed", e);
}
}
}

View file

@ -0,0 +1,424 @@
package gov.noaa.nws.ost.edex.plugin.stq;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Pattern;
import com.raytheon.edex.exception.DecoderException;
import com.raytheon.uf.common.pointdata.PointDataContainer;
import com.raytheon.uf.common.pointdata.PointDataDescription;
import com.raytheon.uf.common.pointdata.PointDataView;
import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.wmo.WMOHeader;
import gov.noaa.nws.ost.dataplugin.stq.SpotRequestRecord;
/**
* Spot Forecast Request file parser
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* July 29, 2015 DCS17366 pwang Initial creation
*
* </pre>
*
* @author pwang
* @version 1.0
*/
public class SpotRequestParser {
public static final String WMO_HEADER = "[A-Z]{3}[A-Z0-9](?:\\d{0,2}|[A-Z]{0,2})\\s+[A-Z0-9]{4}\\s+\\d{6}(?:[A-Z]{3})?";
private static final Pattern WMO_HEADER_PATTERN = Pattern
.compile(WMO_HEADER);
private static final Pattern STQ_FILE_PATTERN = Pattern
.compile("STQ[A-Z]{3}");
private static final Pattern STQ_PROPERTY_PATTERN = Pattern
.compile(".*:\\s+");
/*
* Reserved patterns
*
* private static final Pattern STQ_WXCOND_PATTERN = Pattern
* .compile("\\.*WEATHER\\s+CONDITIONS"); private static final Pattern
* STQ_REMARK_PATTERN = Pattern .compile("\\.*REMARK"); private static final
* Pattern STQ_WXPARMS_PATTERN = Pattern
* .compile("\\.*WEATHER\\s+PARAMETERS");
*/
private static final String PROPERTY_DELIMINATER = ":\\s+";
private static final String DOT_DELIMINATER = "\\.";
private static final String SLASH_DELIMINATER = "\\/";
private static final Map<String, Integer> TIMEZONE = new HashMap<String, Integer>();
static {
TIMEZONE.put("EDT", 4);
TIMEZONE.put("EST", 5);
TIMEZONE.put("CDT", 5);
TIMEZONE.put("CST", 6);
TIMEZONE.put("MDT", 6);
TIMEZONE.put("MST", 7);
TIMEZONE.put("PDT", 7);
TIMEZONE.put("PST", 8);
TIMEZONE.put("GMT", 0);
}
private static final Map<String, String> PROPERTY_PATTERN_MAP = new HashMap<String, String>();
static {
PROPERTY_PATTERN_MAP.put("DATE_NAME", "DATE");
PROPERTY_PATTERN_MAP.put("DATE_VALUE",
"[0-9]{1,2}\\/[0-9]{1,2}\\/[0-9]{2}");
PROPERTY_PATTERN_MAP.put("TIME_NAME", "TIME");
PROPERTY_PATTERN_MAP.put("TIME_VALUE", "\\d{4}");
PROPERTY_PATTERN_MAP.put("PROJ_NAME", "PROJECT NAME");
PROPERTY_PATTERN_MAP.put("AGENCY_NAME", "REQUESTING\\s+AGENCY");
PROPERTY_PATTERN_MAP.put("OFFICIAL_NAME", "REQUESTING\\s+OFFICIAL");
PROPERTY_PATTERN_MAP.put("PHONE_NAME", "EMERGENCY\\s+PHONE");
PROPERTY_PATTERN_MAP
.put("PHONE_VALUE", "\\(\\d{3}\\)\\s*\\d{3}-\\d{4}");
PROPERTY_PATTERN_MAP.put("STATE_NAME", "STATE");
PROPERTY_PATTERN_MAP.put("DLAT_NAME", "DLAT");
PROPERTY_PATTERN_MAP.put("DLON_NAME", "DLON");
PROPERTY_PATTERN_MAP.put("LATLON_VALUE", "\\d+(\\.\\d+)?");
PROPERTY_PATTERN_MAP.put("BELEV_NAME", "BOTTOM\\s+ELEVATION");
PROPERTY_PATTERN_MAP.put("TELEV_NAME", "TOP\\s+ELEVATION");
PROPERTY_PATTERN_MAP.put("SIZE_NAME", "SIZE\\s*\\(ACRES\\)");
PROPERTY_PATTERN_MAP.put("SITE_NAME", "SITE");
PROPERTY_PATTERN_MAP.put("OFILE_NAME", "OFILE");
PROPERTY_PATTERN_MAP.put("OFILE_VALUE", "\\d{8}\\.\\w{5}\\.\\d{2}");
PROPERTY_PATTERN_MAP.put("TIMEZONE_NAME", "TIMEZONE");
PROPERTY_PATTERN_MAP.put("TIMEZONE_VALUE", "\\w{3}\\d{1}(\\w{3})?");
}
/** The logger */
private static final IUFStatusHandler logger = UFStatus
.getHandler(SpotRequestParser.class);
private File stqIngestFile = null;
private PointDataDescription pdd = null;
private SpotRequestRecordDAO dao = null;
private final Map<File, PointDataContainer> containerMap;
private boolean isSTQFile = false;
private String[] mmddyyyy;
private WMOHeader wmoHeader;
public SpotRequestParser(File stqFile, PointDataDescription pdd,
SpotRequestRecordDAO dao) {
this.stqIngestFile = stqFile;
this.pdd = pdd;
this.dao = dao;
containerMap = new HashMap<File, PointDataContainer>();
}
/**
* parse input stg file
*
* @return
* @throws DecoderException
*/
public SpotRequestRecord parse() throws DecoderException {
SpotRequestRecord srr = new SpotRequestRecord();
SurfaceObsLocation location = new SurfaceObsLocation();
srr.setLocation(location);
BufferedReader br = null;
String oneline = "";
try {
br = new BufferedReader(new FileReader(this.stqIngestFile));
while ((oneline = br.readLine()) != null) {
// Trim spaces of the line
String line = oneline.trim();
// Match WHMHeader
if (WMO_HEADER_PATTERN.matcher(line).matches()) {
wmoHeader = new WMOHeader(line.getBytes(),
stqIngestFile.getName());
if (wmoHeader != null) {
srr.setWmoHeader(wmoHeader.getWmoHeader());
}
} else if (STQ_FILE_PATTERN.matcher(line).matches()) {
/* Just check this marker and make sure it is a right ingest
* file
*/
isSTQFile = true;
} else if (STQ_PROPERTY_PATTERN.matcher(line).lookingAt()) {
// All lines with <nam string>:<space> <value string>
boolean status = parsePropertyLine(line, srr);
if (!status) {
// Missing required property
logger.error("STG Decoder error: invalid property value found");
throw new DecoderException(
"STQ Ingest file contains invalid property value");
}
}
/*
* Reserved else if
* (STQ_WXCOND_PATTERN.matcher(line).lookingAt()) { //Match
* reported weather conditions, reserved //do nothing continue;
* } else if(STQ_REMARK_PATTERN.matcher(line).lookingAt()) {
* //matched Remarks, reserved //do nothing continue; } else
* if(STQ_WXPARMS_PATTERN.matcher(line).lookingAt()) { //matched
* weather conditions, reserved //do nothing continue; }
*/
}
// The file may not be a STQ file
if (!isSTQFile) {
logger.error("STG Decoder error: Ingest File "
+ this.stqIngestFile + " is not a SRQ file!");
throw new DecoderException("STQ Ingest file "
+ this.stqIngestFile + " is not a STQ file");
}
// Build PointDataDescription
PointDataContainer pdc = getContainer(srr);
// Populate the point data.
PointDataView view = pdc.append();
view.setString("projectName", srr.getProjectName());
view.setString("reqOfficial", srr.getReqOfficial());
view.setString("emPhone", srr.getEmPhone());
view.setString("timeZone", srr.getTimeZone());
view.setString("state", srr.getState());
view.setInt("bottomElevation", srr.getBottomElevation());
view.setInt("topElevation", srr.getTopElevation());
view.setInt("sizeAcres", srr.getSizeAcres());
view.setString("stqSymbol", srr.getStqSymbol());
srr.setPointDataView(view);
} catch (FileNotFoundException e) {
throw new DecoderException("STQ Ingest file " + this.stqIngestFile
+ " is not found!", e);
} catch (IOException e) {
throw new DecoderException("I/O exception for reading "
+ this.stqIngestFile, e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
throw new DecoderException("I/O exception for closing "
+ this.stqIngestFile, e);
}
}
}
return srr;
}
/**
* parsePropertyLine to property / value
*
* @param line
* @param stgPDO
* @return false if failed to parse the line
*/
private boolean parsePropertyLine(String line, SpotRequestRecord stgPDO) {
boolean status = true;
String[] property = line.split(PROPERTY_DELIMINATER);
String propertyName = property[0].trim();
String propertyValue;
if (property.length > 1 && property[1] != null
&& property[1].trim().length() > 0) {
// the property has a value
propertyValue = property[1].trim();
} else {
// Invalid property line, something wrong of the ingest file
return false;
}
// match and parse property pairs
if (propertyName.matches(PROPERTY_PATTERN_MAP.get("DATE_NAME"))) {
if (propertyValue.matches(PROPERTY_PATTERN_MAP
.get("DATE_VALUE"))) {
String mmddyyyyString = "";
try {
DateFormat informat = new SimpleDateFormat("MM/dd/yy");
DateFormat outformat = new SimpleDateFormat("MM/dd/yyyy");
mmddyyyyString = outformat.format(informat
.parse(propertyValue));
this.mmddyyyy = mmddyyyyString.split(SLASH_DELIMINATER);
} catch (ParseException pe) {
logger.error("STQ Parser: failed to parse Date string: "
+ pe);
status = false;
}
}
else {
//Date is required, return false to discontinue the parsing
status = false;
}
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("TIME_NAME"))) {
if (propertyValue.matches(PROPERTY_PATTERN_MAP
.get("TIME_VALUE"))) {
String HHs = propertyValue.substring(0, 2);
String MMs = propertyValue.substring(2);
int hours = Integer.parseInt(HHs);
int minutes = Integer.parseInt(MMs);
stgPDO.setDataTime(getRefTime(this.mmddyyyy, hours, minutes));
}
else {
//Time is required, return false to discontinue the parsing
logger.error("STQ Parser: Invalid TIME Value: " + propertyValue);
status = false;
}
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("PROJ_NAME"))) {
//Project Name is required, but valuse is free text
stgPDO.setProjectName(propertyValue);
}
else if (propertyName
.matches(PROPERTY_PATTERN_MAP.get("OFFICIAL_NAME"))) {
stgPDO.setReqOfficial(propertyValue);
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("PHONE_NAME"))) {
if (propertyValue.matches(PROPERTY_PATTERN_MAP
.get("PHONE_VALUE"))) {
stgPDO.setEmPhone(propertyValue);
}
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("STATE_NAME"))) {
stgPDO.setState(propertyValue);
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("DLAT_NAME"))) {
if (propertyValue.matches(PROPERTY_PATTERN_MAP
.get("LATLON_VALUE"))) {
float dlat = Float.parseFloat(propertyValue.trim());
stgPDO.setLatitude(dlat);
}
else {
//DLAT is required, return false to discontinue the parsing
logger.error("STQ Parser: Invalid DLAT Value: " + propertyValue);
status = false;
}
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("DLON_NAME"))) {
if (propertyValue.matches(PROPERTY_PATTERN_MAP
.get("LATLON_VALUE"))) {
float dlon = Float.parseFloat(propertyValue.trim());
//Ensure lon direction is West
dlon = Math.abs(dlon) * -1;
stgPDO.setLongitude(dlon);
}
else {
//DLON is required, return false to discontinue the parsing
logger.error("STQ Parser: Invalid DLON Value: " + propertyValue);
status = false;
}
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("BELEV_NAME"))) {
int bottom_elevation = Integer.parseInt(propertyValue.trim());
stgPDO.setBottomElevation(bottom_elevation);
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("TELEV_NAME"))) {
int top_elevation = Integer.parseInt(propertyValue.trim());
stgPDO.setTopElevation(top_elevation);
stgPDO.getLocation().setElevation(top_elevation);
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("SIZE_NAME"))) {
int size = Integer.parseInt(propertyValue.trim());
stgPDO.setSizeAcres(size);
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("SITE_NAME"))) {
stgPDO.setSite(propertyValue);
} else if (propertyName.matches(PROPERTY_PATTERN_MAP.get("OFILE_NAME"))) {
if (propertyValue.matches(PROPERTY_PATTERN_MAP
.get("OFILE_VALUE"))) {
String[] ofileArray = propertyValue.split(DOT_DELIMINATER);
stgPDO.setOfileKey(ofileArray[1]);
stgPDO.setOfileVersion(ofileArray[2]);
stgPDO.getLocation()
.setStationId(ofileArray[1] + ofileArray[2]);
}
else {
//OFILE is required, return false to discontinue the parsing
logger.error("STQ Parser: Invalid OFILE Value: " + propertyValue);
status = false;
}
} else if (propertyName.matches(PROPERTY_PATTERN_MAP
.get("TIMEZONE_NAME"))) {
if (propertyValue.matches(PROPERTY_PATTERN_MAP
.get("TIMEZONE_VALUE"))) {
stgPDO.setTimeZone(propertyValue);
}
}
return status;
}
/**
* Gets Container
*
* @param obsData
* @return
*/
private PointDataContainer getContainer(SpotRequestRecord stqData) {
File file = dao.getFullFilePath(stqData);
PointDataContainer container = containerMap.get(file);
if (container == null) {
container = PointDataContainer.build(pdd);
containerMap.put(file, container);
}
return container;
}
/**
* Gets the ref time from the time field, month, and year.
*
* @param time
* The time field.
* @param month
* The month.
* @param year
* The year.
* @return The ref time, or null if the time field is null.
*/
private DataTime getRefTime(String[] mmddyyyy, int hour, int minute) {
if (mmddyyyy == null || mmddyyyy.length < 3) {
return null;
}
int year = Integer.parseInt(mmddyyyy[2]);
int month = Integer.parseInt(mmddyyyy[0]);
int day = Integer.parseInt(mmddyyyy[1]);
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1);
cal.set(Calendar.DAY_OF_MONTH, day);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
return new DataTime(cal);
}
}

View file

@ -0,0 +1,122 @@
package gov.noaa.nws.ost.edex.plugin.stq;
import java.util.List;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import gov.noaa.nws.ost.dataplugin.stq.SpotRequestRecord;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.pointdata.PointDataPluginDao;
/**
* SpotRequestRecord Dao
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sept 4, 2015 pwang Initial creation
*
* </pre>
*
* @author pwang
* @version 1.0
*/
public class SpotRequestRecordDAO extends PointDataPluginDao<SpotRequestRecord> {
/** The logger */
private static final IUFStatusHandler logger = UFStatus
.getHandler(SpotRequestRecordDAO.class);
private static final String FILE_NAME_KEY = "dataTime.refTime";
/**
* Creates a new Spot Request Dao
*
* @param pluginName
* @throws PluginException
*/
public SpotRequestRecordDAO(String pluginName) throws PluginException {
super(pluginName);
}
/**
* Retrieves an spot request using the datauri .
*
* @param dataURI
* The dataURI to match against.
* @return The spot request record if it exists.
*/
public SpotRequestRecord queryByDataURI(String dataURI) {
SpotRequestRecord req = null;
List<?> obs = null;
try {
obs = queryBySingleCriteria("dataURI", dataURI);
} catch (DataAccessLayerException e) {
logger.error("STQ DAO: query with criteria: " + dataURI + " failed ! " + e );
}
if ((obs != null) && (obs.size() > 0)) {
req = (SpotRequestRecord) obs.get(0);
}
return req;
}
/**
* Queries for to determine if a given data uri exists on the stq table.
*
* @param dataUri
* The DataURI to find.
* @return An array of objects. If not null, there should only be a single
* element.
*/
public Object[] queryDataUriColumn(final String dataUri) {
String sql = "select datauri from awips.stq where datauri='" + dataUri
+ "';";
Object[] results = executeSQLQuery(sql);
return results;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.pointdata.PointDataPluginDao#getKeysRequiredForFileName
* ()
*/
@Override
public String[] getKeysRequiredForFileName() {
return new String[] { FILE_NAME_KEY };
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.pointdata.PointDataPluginDao#getPointDataFileName
* (com.raytheon.uf.common.dataplugin.PluginDataObject)
*/
@Override
public String getPointDataFileName(SpotRequestRecord p) {
StringBuilder fname = new StringBuilder();
fname.append(this.pluginName);
fname.append(".h5");
return fname.toString();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.edex.pointdata.PointDataPluginDao#newObject()
*/
@Override
public SpotRequestRecord newObject() {
return new SpotRequestRecord();
}
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<purgeRuleSet xmlns:ns2="group">
<defaultRule>
<period>01-00:00:00</period>
</defaultRule>
</purgeRuleSet>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<requestPatterns xmlns:ns2="group">
<regex>^BMBB91.*</regex>
</requestPatterns>