Issue #3419 Refactored watches to use the county table.

Change-Id: Ide7e07813203213511640d5ee515e73b278089c1

Former-commit-id: b991838494 [formerly 86a8ca4a30 [formerly 135d7ffa84af58d7b3c9575e654fa1298b76b2e2]]
Former-commit-id: 86a8ca4a30
Former-commit-id: 997485dd22
This commit is contained in:
Jonathan Sanchez 2014-07-22 15:32:12 -05:00
parent 51f80b4c58
commit c479178882
40 changed files with 994 additions and 1105 deletions

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.warngen.gis;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -45,6 +46,7 @@ import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.raytheon.viz.warngen.util.Abbreviation;
import com.vividsolutions.jts.geom.Geometry;
@ -77,6 +79,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry;
* Apr 29, 2014 3033 jsanchez Updated method to retrieve files in localization.
* May 16, 2014 DR 17365 D. Friedman Reduce precision of warning area to avoid topology errors.
* Jun 30, 2014 DR 17447 Qinglu lin Updated findAffectedAreas().
* Jul 22, 23014 3419 jsanchez Cleaned up converFeAreaToPartList.
* </pre>
*
* @author chammack
@ -92,6 +95,10 @@ public class Area {
*/
public static final double DEFAULT_PORTION_TOLERANCE = 0.60;
private static final List<String> SPECIAL_CASE_FE_AREAS = Arrays
.asList(new String[] { "PA", "MI", "PD", "UP", "BB", "ER", "EU",
"SR", "NR", "WU", "DS" });
private PortionsUtil portionsUtil;
public Area(PortionsUtil portionsUtil) {
@ -259,8 +266,10 @@ public class Area {
area.points = pointList.toArray(new String[pointList.size()]);
}
String countyName = (String)regionFeature.attributes.get("COUNTYNAME");
if (uniqueFips.contains(area.fips) == false || !uniqueCountyname.contains(countyName)) {
String countyName = (String) regionFeature.attributes
.get("COUNTYNAME");
if (uniqueFips.contains(area.fips) == false
|| !uniqueCountyname.contains(countyName)) {
uniqueFips.add(area.fips);
if (countyName != null) {
uniqueCountyname.add(countyName);
@ -300,7 +309,8 @@ public class Area {
Map<String, Object> areasMap = new HashMap<String, Object>();
try {
Geometry precisionReducedArea = PolygonUtil.reducePrecision(warnArea);
Geometry precisionReducedArea = PolygonUtil
.reducePrecision(warnArea);
if (precisionReducedArea.isValid()) {
warnArea = precisionReducedArea;
}
@ -338,66 +348,41 @@ public class Area {
public static List<String> converFeAreaToPartList(String feArea) {
final List<String> partList = new ArrayList<String>();
if (feArea == null) {
// Marine warnings
partList.add("");
} else {
if (feArea.equals("pa"))
partList.add("PA");
else if (feArea.equals("mi"))
partList.add("MI");
else if (feArea.equals("pd"))
partList.add("PD");
else if (feArea.equals("up"))
partList.add("UP");
else if (feArea.equals("bb"))
partList.add("BB");
else if (feArea.equals("er"))
partList.add("ER");
else if (feArea.equals("eu"))
partList.add("EU");
else if (feArea.equals("sr"))
partList.add("SR");
else if (feArea.equals("nr"))
partList.add("NR");
else if (feArea.equals("wu"))
partList.add("WU");
else if (feArea.equals("ds"))
partList.add("DS");
else if (feArea.equals("ne"))
partList.add("NE");
else if (feArea.equals("nw"))
partList.add("NW");
else if (feArea.equals("se"))
partList.add("SE");
else if (feArea.equals("sw"))
partList.add("SW");
else {
if (feArea != null) {
feArea = feArea.toUpperCase();
if (SPECIAL_CASE_FE_AREAS.contains(feArea)) {
partList.add(feArea);
} else {
for (int i = 0; i < feArea.length(); i++) {
char c = feArea.charAt(i);
Direction direction = null;
switch (c) {
case 'c':
partList.add("CENTRAL");
case 'C':
direction = Direction.CENTRAL;
break;
case 'w':
partList.add("WEST");
case 'W':
direction = Direction.WEST;
break;
case 'n':
partList.add("NORTH");
case 'N':
direction = Direction.NORTH;
break;
case 'e':
partList.add("EAST");
case 'E':
direction = Direction.EAST;
break;
case 's':
partList.add("SOUTH");
case 'S':
direction = Direction.SOUTH;
break;
default:
break;
}
if (direction != null) {
partList.add(direction.toString());
}
}
}
}
return partList;
}
}

View file

@ -0,0 +1,191 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
import java.util.Date;
import java.util.List;
/**
* Simple POJO for a watch. The phenSig, action, etn, start time, and end time
* make each watch unique similar to the VTEC.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 16, 2014 3419 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class Watch {
private String phenSig;
private String action;
private String etn;
private Date startTime;
private Date endTime;
private List<String> areas;
private String state;
private List<String> partOfState;
public Watch(String state, String action, String phenSig, String etn,
Date startTime, Date endTime) {
this.state = state;
this.action = action;
this.phenSig = phenSig;
this.etn = etn;
this.startTime = startTime;
this.endTime = endTime;
}
public String getPhenSig() {
return phenSig;
}
public void setPhenSig(String phenSig) {
this.phenSig = phenSig;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public List<String> getAreas() {
return areas;
}
public void setAreas(List<String> areas) {
this.areas = areas;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public List<String> getPartOfState() {
return partOfState;
}
public void setPartOfState(List<String> partOfState) {
this.partOfState = partOfState;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public String getEtn() {
return etn;
}
public void setEtn(String etn) {
this.etn = etn;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((action == null) ? 0 : action.hashCode());
result = prime * result + ((endTime == null) ? 0 : endTime.hashCode());
result = prime * result + ((etn == null) ? 0 : etn.hashCode());
result = prime * result + ((phenSig == null) ? 0 : phenSig.hashCode());
result = prime * result
+ ((startTime == null) ? 0 : startTime.hashCode());
result = prime * result + ((state == null) ? 0 : state.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Watch other = (Watch) obj;
if (action == null) {
if (other.action != null)
return false;
} else if (!action.equals(other.action))
return false;
if (endTime == null) {
if (other.endTime != null)
return false;
} else if (!endTime.equals(other.endTime))
return false;
if (etn == null) {
if (other.etn != null)
return false;
} else if (!etn.equals(other.etn))
return false;
if (phenSig == null) {
if (other.phenSig != null)
return false;
} else if (!phenSig.equals(other.phenSig))
return false;
if (startTime == null) {
if (other.startTime != null)
return false;
} else if (!startTime.equals(other.startTime))
return false;
if (state == null) {
if (other.state != null)
return false;
} else if (!state.equals(other.state))
return false;
return true;
}
}

View file

@ -0,0 +1,536 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import org.apache.commons.lang.Validate;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.activetable.OperationalActiveTableRecord;
import com.raytheon.uf.common.activetable.PracticeActiveTableRecord;
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Polygon;
/**
* Determines the valid watches related to the warning.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 17, 2014 3419 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class WatchUtil {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(WatchUtil.class);
private static final UnitConverter milesToKilometer = NonSI.MILE
.getConverterTo(SI.KILOMETER);
private static final double KmToDegrees = 111.12;
private static final String ISSUE_TIME_FIELD = "issueTime";
private static final String START_TIME_FIELD = "startTime";
private static final String END_TIME_FIELD = "endTime";
private static final String UGC_ZONE_FIELD = "ugcZone";
private static final String PHEN_SIG_FIELD = "phensig";
private static final String ETN = "etn";
private static final String ACTION = "act";
private static final String COUNTY_FIPS_FIELD = "FIPS";
private static final String COUNTY_FE_AREA_FIELD = "FE_AREA";
private static final String STATE_FIELD = "STATE";
private static final String COUNTY_TABLE = "County";
private static final String PARENT_NAME_FIELD = "NAME";
private static final String[] REQUEST_FIELDS = new String[] {
ISSUE_TIME_FIELD, START_TIME_FIELD, END_TIME_FIELD, UGC_ZONE_FIELD,
PHEN_SIG_FIELD, END_TIME_FIELD, ACTION, ETN };
private GeospatialData[] countyGeoData;
private WarngenLayer warngenLayer;
public WatchUtil(WarngenLayer warngenLayer) throws InstantiationException {
countyGeoData = warngenLayer.getGeodataFeatures(COUNTY_TABLE,
warngenLayer.getLocalizedSite());
if ((countyGeoData == null) || (countyGeoData.length == 0)) {
throw new InstantiationException("Cannot get geospatial data for "
+ COUNTY_TABLE + "-based watches");
}
this.warngenLayer = warngenLayer;
}
/**
* Retrieves valid watches based on the constraints in the config, the
* warning polygon, and the current simulated time.
*
* @param config
* @param warningPolygon
* @param simulatedTime
* @return
* @throws Exception
*/
public List<Watch> getWatches(WarngenConfiguration config,
Geometry warningPolygon, Date simulatedTime) throws Exception {
List<Watch> watches = null;
AreaSourceConfiguration hatchedAreaSourceConfig = config
.getHatchedAreaSource();
// Validation check
Validate.notNull(hatchedAreaSourceConfig,
"Cannot process watches: missing HATCHING area source configuration");
double watchAreaBuffer = hatchedAreaSourceConfig
.getIncludedWatchAreaBuffer();
// Validation check
Validate.isTrue(watchAreaBuffer >= 0,
"'includedWatchAreaBuffer' can not be negative in .xml file");
String[] includedWatches = config.getIncludedWatches();
if ((includedWatches != null) && (includedWatches.length > 0)) {
StringBuilder phenSigConstraint = new StringBuilder();
Iterator<String> iterator = Arrays.asList(includedWatches)
.iterator();
while (iterator.hasNext()) {
phenSigConstraint.append(iterator.next());
if (iterator.hasNext()) {
phenSigConstraint.append(",");
}
}
// Determine entity class
Class<? extends ActiveTableRecord> entityClass = OperationalActiveTableRecord.class;
if (CAVEMode.getMode() != CAVEMode.OPERATIONAL) {
entityClass = PracticeActiveTableRecord.class;
}
DbQueryRequest request = buildRequest(simulatedTime,
phenSigConstraint.toString(), warngenLayer.getAllUgcs(),
entityClass);
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
List<ActiveTableRecord> records = convertReponse(entityClass,
response);
if (records.isEmpty() == false) {
try {
long t0 = System.currentTimeMillis();
Polygon watchArea = (Polygon) warningPolygon
.buffer(milesToKilometer.convert(watchAreaBuffer)
/ KmToDegrees);
System.out.println("create watch area buffer time: "
+ (System.currentTimeMillis() - t0));
Set<String> validUgcZones = warngenLayer
.getUgcsForWatches(watchArea);
watches = processRecords(records, validUgcZones);
} catch (RuntimeException e) {
statusHandler
.handle(Priority.ERROR,
"Error determining areas to search for watches.",
e);
}
}
}
return watches;
}
/**
* Builds a DBQueryRequest object.
*
* @param simulatedTime
* @param phenSig
* @param ugcs
* @param entityClass
* @return
*/
private static DbQueryRequest buildRequest(Date simulatedTime,
String phenSig, Set<String> ugcs,
Class<? extends ActiveTableRecord> entityClass) {
// Create start constraint
Calendar cal = Calendar.getInstance();
cal.setTime(simulatedTime);
cal.add(Calendar.MINUTE, 3);
Date startConstraintTime = cal.getTime();
DbQueryRequest request = new DbQueryRequest();
request.setEntityClass(entityClass);
request.addConstraint(START_TIME_FIELD,
new RequestConstraint(TimeUtil.formatDate(startConstraintTime),
ConstraintType.LESS_THAN_EQUALS));
request.addConstraint(END_TIME_FIELD,
new RequestConstraint(TimeUtil.formatDate(simulatedTime),
ConstraintType.GREATER_THAN_EQUALS));
request.addConstraint("phensig",
new RequestConstraint(phenSig.toString(), ConstraintType.IN));
/*
* Get all UGCs in the CWA now so that the watches will be formatted
* with all portions of the affected state(s).
*
* Filtering for valid UGCs is performed in processATEntries
*/
RequestConstraint ugcConstraint = new RequestConstraint("",
ConstraintType.IN);
ugcConstraint.setConstraintValueList(ugcs);
request.addConstraint("ugcZone", ugcConstraint);
// These are the only fields we need for processing watches
request.addFields(REQUEST_FIELDS);
return request;
}
/**
* Converts the results of DbQueryResponse into a list of
* ActiveTableRecords.
*
* @param entityClass
* @param response
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
private static final List<ActiveTableRecord> convertReponse(
Class<? extends ActiveTableRecord> entityClass,
DbQueryResponse response) throws IllegalAccessException,
InstantiationException {
List<ActiveTableRecord> records = new ArrayList<ActiveTableRecord>(
response.getNumResults());
for (Map<String, Object> result : response.getResults()) {
WarningAction action = WarningAction.valueOf(String.valueOf(result
.get(ACTION)));
/*
* TODO: Currently limited to filtering out one of ("CAN","EXP").
* Could use "Act" in addition to "act", but this should really be
* fixed the underlying system. request.addConstraint("act", new
* RequestConstraint("CAN", ConstraintType.NOT_EQUALS));
*/
if (action != WarningAction.CAN || action != WarningAction.EXP) {
ActiveTableRecord record = entityClass.newInstance();
record.setIssueTime((Calendar) result.get(ISSUE_TIME_FIELD));
record.setStartTime((Calendar) result.get(START_TIME_FIELD));
record.setEndTime((Calendar) result.get(END_TIME_FIELD));
record.setEndTime((Calendar) result.get(END_TIME_FIELD));
record.setUgcZone(String.valueOf(result.get(UGC_ZONE_FIELD)));
record.setPhensig(String.valueOf(result.get(PHEN_SIG_FIELD)));
record.setEtn(String.valueOf(result.get(ETN)));
record.setAct(String.valueOf(result.get(ACTION)));
records.add(record);
}
}
return records;
}
/**
* Groups the activeTableRecords into Watch objects that share phenSig,
* action, ETN, start time, and end time. It also determines the part of
* state the watch covers.
*
* @param activeTableRecords
* @param validUgcZones
*
* @return
*/
private List<Watch> processRecords(
List<ActiveTableRecord> activeTableRecords,
Set<String> validUgcZones) {
List<Watch> watches = new ArrayList<Watch>();
/*
* Assumption 1: TO.A and SV.A UGC line will always be in county format
* from WOU.
*/
/*
* Assumption 2: At least 1 warning for the issuing site supports county
* based warnings. This will allow the county geo features to be cached.
*/
Map<Watch, List<String>> map = new HashMap<Watch, List<String>>();
// For each watch event, get the end time and list of active zones
for (ActiveTableRecord ar : activeTableRecords) {
/*
* Currently reports all zones in the watch even if a given zone is
* not in the warning polygon. If the logic is changed to only show
* the portions of the watch near our warning polygon, filter on
* validUgcZones here.
*/
String ugcZone = ar.getUgcZone();
String state = getStateName(ugcZone.substring(0, 2));
String action = ar.getAct();
String phenSig = ar.getPhensig();
String etn = ar.getEtn();
Date startTime = ar.getStartTime().getTime();
Date endTime = ar.getEndTime().getTime();
if (validUgcZones.contains(ugcZone)) {
Watch watch = new Watch(state, action, phenSig, etn, startTime,
endTime);
List<String> areas = map.get(watch);
if (areas == null) {
areas = new ArrayList<String>();
}
areas.add(ugcZone);
map.put(watch, areas);
}
}
// Sets the areas for the watch
for (Entry<Watch, List<String>> entry : map.entrySet()) {
Watch watch = entry.getKey();
watch.setAreas(entry.getValue());
List<String> partOfState = new ArrayList<String>(
determineAffectedPortions(watch.getAreas()));
watch.setPartOfState(partOfState);
watches.add(watch);
}
// Sorts the watches based on state name.
Collections.sort(watches, new Comparator<Watch>() {
@Override
public int compare(Watch watch1, Watch watch2) {
return watch1.getState().compareTo(watch2.getState());
}
});
return watches;
}
/**
* Determines the directional set of a state.
*
* @param ugcs
* @return
*/
private Set<String> determineAffectedPortions(List<String> ugcs) {
Set<String> feAreas = new HashSet<String>();
for (String ugc : ugcs) {
// Want the first 2 letters
String stateAbbrev = ugc.substring(0, 2);
// Want the last 3 digits
String fips = ugc.substring(ugc.length() - 3);
String feArea = getFeArea(stateAbbrev, fips);
// Checks to see if feArea in CWA
if (feArea != null) {
feAreas.add(feArea);
}
}
Set<String> affectedPortions = new HashSet(
Area.converFeAreaToPartList(mungeFeAreas(feAreas)));
return affectedPortions;
}
/**
* Returns the full state name from the state abbreviation.
*
* @param stateAbrev
* @return
*/
private String getStateName(String stateAbrev) {
for (GeospatialData g : countyGeoData) {
if (stateAbrev.equals(g.attributes.get(STATE_FIELD))) {
return (String) g.parent.attributes.get(PARENT_NAME_FIELD);
}
}
return null;
}
/**
* Returns the feArea field in the county table (i.e. n, s, e, w).
*
* @param stateAbbrev
* @param ugc
* @return
*/
private String getFeArea(String stateAbbrev, String ugc) {
for (GeospatialData g : countyGeoData) {
if (stateAbbrev.equals(g.attributes.get(STATE_FIELD))
&& ((String) g.attributes.get(COUNTY_FIPS_FIELD))
.endsWith(ugc)) {
return (String) g.attributes.get(COUNTY_FE_AREA_FIELD);
}
}
return null;
}
// Based on AWIPS 1 SELSparagraphs.C SELSparagraphs::processWOU().
private String mungeFeAreas(Set<String> feAreas) {
String abrev = "";
// If eight or more portions, don't qualify area of state
int m = feAreas.size();
if (m < 8) {
String partAbrev = "";
/*
* TODO: Unused variables should be removed if we are not going to
* improve this in A2.
*/
@SuppressWarnings("unused")
int nw, nc, ne, wc, cc, ec, sw, sc, se, pa;
int eee, www, nnn, sss, ee, ww, nn, ss;
// Identify individual sub areas of this state affected
nw = nc = ne = wc = cc = ec = sw = sc = se = pa = 0;
eee = www = nnn = sss = ee = ww = nn = ss = 0;
for (String part : feAreas) {
if ("pa".equals(part)) {
pa = 1;
continue;
} else if ("nn".equals(part)) {
nnn = nn = 1;
} else if ("ss".equals(part)) {
sss = ss = 1;
} else if ("ee".equals(part)) {
eee = ee = 1;
} else if ("ww".equals(part)) {
www = ww = 1;
} else if ("nw".equals(part)) {
nnn = www = nw = 1;
} else if ("nc".equals(part)) {
nnn = nc = 1;
} else if ("ne".equals(part)) {
nnn = eee = ne = 1;
} else if ("wc".equals(part)) {
www = wc = 1;
} else if ("cc".equals(part)) {
cc = 1;
continue;
} else if ("ec".equals(part)) {
eee = ec = 1;
} else if ("sw".equals(part)) {
sss = www = sw = 1;
} else if ("sc".equals(part)) {
sss = sc = 1;
} else if ("se".equals(part)) {
sss = eee = se = 1;
}
partAbrev = part;
}
// decide how to describe these subareas.
if ((ne > 0) && (nw > 0)) {
nn = 1;
}
if ((se > 0) && (sw > 0)) {
ss = 1;
}
if ((se > 0) && (ne > 0)) {
ee = 1;
}
if ((sw > 0) && (nw > 0)) {
ww = 1;
}
if ((nnn > 0) && (sss > 0) && (eee > 0) && (www > 0)) {
return abrev;
}
if (((nn > 0) && (ss > 0)) || ((ee > 0) && (ww > 0))) {
return abrev;
}
if (nnn + sss + eee + www == 3) {
if (www == 0) {
abrev = "e";
} else if (eee == 0) {
abrev = "w";
} else if (nnn == 0) {
abrev = "s";
} else if (sss == 0) {
abrev = "n";
}
return abrev;
}
if (((nnn == sss) && (eee == www)) || (cc == m)) {
abrev = "c";
return abrev;
}
if ((pa != 0) && (cc == 0)) {
abrev = "pa";
if (--m <= 0) {
return abrev;
}
}
if (m == 1 + cc) {
abrev += partAbrev + " ";
return abrev;
}
if (nnn != sss) {
abrev += nnn != 0 ? "n" : "s";
}
if (eee != www) {
abrev += eee != 0 ? "e" : "w";
}
}
return abrev;
}
}

View file

@ -155,6 +155,7 @@ import com.vividsolutions.jts.geom.Polygon;
* Oct 29, 2013 DR 16734 D. Friedman If redraw-from-hatched-area fails, don't allow the polygon the be used.
* Apr 28, 2014 3033 jsanchez Re-initialized the Velocity Engine when switching back up sites.
* Jul 01, 2014 DR 17450 D. Friedman Use list of templates from backup site.
* Jul 21, 2014 3419 jsanchez Created a hidden button to make recreating polygons easier.
* </pre>
*
* @author chammack
@ -165,6 +166,12 @@ public class WarngenDialog extends CaveSWTDialog implements
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(WarngenDialog.class);
/*
* This flag allows a hidden button to appear to help recreating warning
* polygons that had issues in the feed.
*/
private boolean debug = false;
private static final int BULLET_WIDTH = 390;
private static final int BULLET_HEIGHT = 230;
@ -557,7 +564,8 @@ public class WarngenDialog extends CaveSWTDialog implements
GridData gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
if (updateListCbo == null) {
gd.horizontalIndent = 30;
updateListCbo = new Combo(productType, SWT.READ_ONLY | SWT.DROP_DOWN);
updateListCbo = new Combo(productType, SWT.READ_ONLY
| SWT.DROP_DOWN);
updateListCbo.setLayoutData(gd);
recreateUpdates();
@ -629,7 +637,8 @@ public class WarngenDialog extends CaveSWTDialog implements
});
Composite redrawFrom = new Composite(redrawBox, SWT.NONE);
redrawFrom.setLayout(new GridLayout(3, false));
int columns = debug ? 4 : 3;
redrawFrom.setLayout(new GridLayout(columns, false));
redrawFrom.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false,
true));
@ -664,9 +673,30 @@ public class WarngenDialog extends CaveSWTDialog implements
damBreakThreatArea.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
damBreakThreatAreaPressed();
DamInfoBullet damBullet = bulletListManager
.getSelectedDamInfoBullet();
if (damBullet != null) {
damBreakThreatAreaPressed(damBullet.getCoords(), true);
}
}
});
if (debug) {
Button drawPolygonButton = new Button(redrawFrom, SWT.PUSH);
drawPolygonButton.setText("?");
drawPolygonButton.setEnabled(true);
drawPolygonButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
/*
* Copy/paste the LAT...LON line from the text product to
* quickly recreate the polygon.
*/
String latLon = "LAT...LON 4282 7174 4256 7129 4248 7159 4280 7198";
damBreakThreatAreaPressed(latLon, false);
}
});
}
}
private void createBackupTrackEditGroups(Composite mainComposite) {
@ -1208,7 +1238,11 @@ public class WarngenDialog extends CaveSWTDialog implements
setInstructions();
} else if (bulletListManager.isDamNameSeletcted()
&& bulletListManager.isDamCauseSelected()) {
damBreakThreatAreaPressed();
DamInfoBullet damBullet = bulletListManager
.getSelectedDamInfoBullet();
if (damBullet != null) {
damBreakThreatAreaPressed(damBullet.getCoords(), true);
}
if (damBreakInstruct != null) {
return false;
}
@ -1345,7 +1379,7 @@ public class WarngenDialog extends CaveSWTDialog implements
createMainProductButtons(productType);
createOtherProductsList(productType);
// Don't let errors prevent the new controls from being displayed!
// Don't let errors prevent the new controls from being displayed!
try {
changeTemplate(getDefaultTemplate());
resetPressed();
@ -1440,55 +1474,50 @@ public class WarngenDialog extends CaveSWTDialog implements
}
/**
* This method is responsible for drawing a pre-defined drainage basin on
* the WarnGen layer. The method is called when a drainage basin is selected
* in the WarnGen Dialog Bullet List and the Dam Break Threat Area button is
* pressed. Dam info geometries are defined in the Database so a Spatial
* Query is performed to retrieve the data.
* Responsible for drawing a pre-defined warning polygon (coords) on the
* WarnGen layer.
*
* @param coords
* pre-defined warning polygon coordinates in LAT...LON form.
* @param lockPolygon
* indicates if the polygon should be locked or not.
*/
private void damBreakThreatAreaPressed() {
private void damBreakThreatAreaPressed(String coords, boolean lockPolygon) {
damBreakInstruct = "Either no dam selected, no dam info bullets in .xml file, or no\n"
+ "dam break primary cause selected.";
DamInfoBullet damBullet = bulletListManager.getSelectedDamInfoBullet();
if (damBullet != null) {
if ((damBullet.getCoords() == null)
|| (damBullet.getCoords().length() == 0)) {
damBreakInstruct = "LAT...LON can not be found in 'coords' parameter";
} else {
ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
Pattern coordinatePtrn = Pattern
.compile("LAT...LON+(\\s\\d{3,4}\\s\\d{3,5}){1,}");
Pattern latLonPtrn = Pattern
.compile("\\s(\\d{3,4})\\s(\\d{3,5})");
if ((coords == null) || (coords.length() == 0)) {
damBreakInstruct = "LAT...LON can not be found in 'coords' parameter";
} else {
ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
Pattern coordinatePtrn = Pattern
.compile("LAT...LON+(\\s\\d{3,4}\\s\\d{3,5}){1,}");
Pattern latLonPtrn = Pattern.compile("\\s(\\d{3,4})\\s(\\d{3,5})");
Matcher m = coordinatePtrn.matcher(damBullet.getCoords());
if (m.find()) {
m = latLonPtrn.matcher(damBullet.getCoords());
while (m.find()) {
coordinates.add(new Coordinate((-1 * Double
.parseDouble(m.group(2))) / 100, Double
.parseDouble(m.group(1)) / 100));
}
if (coordinates.size() < 3) {
damBreakInstruct = "Lat/Lon pair for dam break threat area is less than three";
} else {
coordinates.add(coordinates.get(0));
PolygonUtil.truncate(coordinates, 2);
warngenLayer.createDamThreatArea(coordinates
.toArray(new Coordinate[coordinates.size()]));
setPolygonLocked(true);
warngenLayer.issueRefresh();
damBreakInstruct = null;
}
} else {
damBreakInstruct = "The 'coords' parameter maybe be misformatted or the\n"
+ "La/Lon for dam break threat area is not in pairs.";
Matcher m = coordinatePtrn.matcher(coords);
if (m.find()) {
m = latLonPtrn.matcher(coords);
while (m.find()) {
coordinates.add(new Coordinate((-1 * Double.parseDouble(m
.group(2))) / 100,
Double.parseDouble(m.group(1)) / 100));
}
}
if (coordinates.size() < 3) {
damBreakInstruct = "Lat/Lon pair for dam break threat area is less than three";
} else {
coordinates.add(coordinates.get(0));
PolygonUtil.truncate(coordinates, 2);
warngenLayer.createDamThreatArea(coordinates
.toArray(new Coordinate[coordinates.size()]));
setPolygonLocked(lockPolygon);
warngenLayer.issueRefresh();
damBreakInstruct = null;
}
} else {
damBreakInstruct = "The 'coords' parameter maybe be misformatted or the\n"
+ "La/Lon for dam break threat area is not in pairs.";
}
}
if (damBreakInstruct != null) {
setInstructions();
@ -1517,11 +1546,11 @@ public class WarngenDialog extends CaveSWTDialog implements
return result;
}
/** Called by controls that can change the current template. Do not
* do anything if the request template is already selected. This
* check is necessary to prevent certain state being reset if
* a followup has been selected as this is not handled by
* changeTemplate() (DR 14515.)
/**
* Called by controls that can change the current template. Do not do
* anything if the request template is already selected. This check is
* necessary to prevent certain state being reset if a followup has been
* selected as this is not handled by changeTemplate() (DR 14515.)
*/
private void uiChangeTemplate(String templateName) {
if (templateName.equals(warngenLayer.getTemplateName())) {

View file

@ -37,40 +37,23 @@ import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import org.apache.commons.lang.Validate;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.ListTool;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.activetable.OperationalActiveTableRecord;
import com.raytheon.uf.common.activetable.PracticeActiveTableRecord;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.dataplugin.warning.WarningConstants;
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.AreaType;
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
@ -82,11 +65,9 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.awipstools.ToolsDataManager;
import com.raytheon.viz.awipstools.common.StormTrackData;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState;
@ -99,6 +80,8 @@ import com.raytheon.viz.warngen.gis.ClosestPointComparator;
import com.raytheon.viz.warngen.gis.GisUtil;
import com.raytheon.viz.warngen.gis.PathCast;
import com.raytheon.viz.warngen.gis.PortionsUtil;
import com.raytheon.viz.warngen.gis.Watch;
import com.raytheon.viz.warngen.gis.WatchUtil;
import com.raytheon.viz.warngen.gis.Wx;
import com.raytheon.viz.warngen.gui.BackupData;
import com.raytheon.viz.warngen.gui.FollowupData;
@ -111,9 +94,6 @@ import com.raytheon.viz.warngen.util.CurrentWarnings;
import com.raytheon.viz.warngen.util.FipsUtil;
import com.raytheon.viz.warngen.util.FollowUpUtil;
import com.raytheon.viz.warngen.util.WarnGenMathTool;
import com.raytheon.viz.warngen.util.WatchUtil;
import com.raytheon.viz.warngen.util.WeatherAdvisoryWatch;
import com.raytheon.viz.warngen.util.WeatherAdvisoryWatch.Portion;
import com.raytheon.viz.warnings.DateUtil;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
@ -159,6 +139,7 @@ import com.vividsolutions.jts.io.WKTReader;
* Apr 28, 2014 3033 jsanchez Set the site and backup site in Velocity Engine's properties
* Mar 17, 2014 DR 16309 Qinglu Lin Updated getWatches(), processATEntries() and determineAffectedPortions(), and
* added determineAffectedMarinePortions().
* Jul 21, 2014 3419 jsanchez Refactored WatchUtil.
* </pre>
*
* @author njensen
@ -171,16 +152,13 @@ public class TemplateRunner {
private static final String LOGIN_NAME_KEY = "LOGNAME";
private static final UnitConverter milesToKilometer = NonSI.MILE
.getConverterTo(SI.KILOMETER);
private static final double KmToDegrees = 111.12;
private static final Pattern BBB_PATTERN = Pattern
.compile(".*\\sCC([A-Z])");
private static Hashtable<String, DateFormat> dateFormat;
private static WatchUtil watchUtil;
static {
dateFormat = new Hashtable<String, DateFormat>();
dateFormat
@ -873,11 +851,14 @@ public class TemplateRunner {
// Store Watches
try {
t0 = System.currentTimeMillis();
WatchUtil watches = getWatches(warngenLayer, config, warnPolygon,
areas, fourLetterSiteId, simulatedTime);
if (watchUtil == null) {
watchUtil = new WatchUtil(warngenLayer);
}
List<Watch> watches = watchUtil.getWatches(config, warnPolygon,
simulatedTime);
System.out.println("getWatches time: "
+ (System.currentTimeMillis() - t0));
if (watches != null) {
if (watches != null && watches.isEmpty() == false) {
context.put("watches", watches);
}
} catch (Exception e) {
@ -977,574 +958,4 @@ public class TemplateRunner {
return rval;
}
/**
* This method populates a WatchUtil object with tornado and severe
* thunderstorm watches from the active table that are contained by the
* polygon. Furthermore, watches that have not yet expired (current time <
* end time) are only included.
*
* @param config
* WarnGen template configuration settings
* ([template_name_site.xml])
* @param polygon
* The Geometry surrounded by the warning polygon.
* @param simulatedTime
* @return
* @throws Exception
*/
private static WatchUtil getWatches(WarngenLayer warngenLayer,
WarngenConfiguration config, Geometry polygon,
AffectedAreas[] affectedAreas, String fourLetterSiteId,
Date simulatedTime) throws Exception {
Validate.isTrue(config.getHatchedAreaSource()
.getIncludedWatchAreaBuffer() >= 0,
"IncludedWatchAreaBuffer can not be negative");
WatchUtil rval = null;
String[] includedWatches = config.getIncludedWatches();
if ((includedWatches != null) && (includedWatches.length > 0)) {
String phensigList = null;
for (String includedWatch : includedWatches) {
if (includedWatch.equalsIgnoreCase("torWatches")) {
phensigList = phensigList == null ? "TO.A" : phensigList
+ ",TO.A";
} else if (includedWatch.equalsIgnoreCase("svrWatches")) {
phensigList = phensigList == null ? "SV.A" : phensigList
+ ",SV.A";
}
}
if (phensigList != null) {
// Create start/endtime constraints
Date endConstraintTime = simulatedTime;
Calendar cal = Calendar.getInstance();
cal.setTime(simulatedTime);
cal.add(Calendar.MINUTE, 3);
Date startConstraintTime = cal.getTime();
// Get record type
Class<? extends ActiveTableRecord> recordType = CAVEMode
.getMode() == CAVEMode.OPERATIONAL ? OperationalActiveTableRecord.class
: PracticeActiveTableRecord.class;
DbQueryRequest request = new DbQueryRequest();
request.setEntityClass(recordType);
request.addConstraint("startTime", new RequestConstraint(
TimeUtil.formatDate(startConstraintTime),
ConstraintType.LESS_THAN_EQUALS));
request.addConstraint(
"endTime",
new RequestConstraint(TimeUtil
.formatDate(endConstraintTime),
ConstraintType.GREATER_THAN_EQUALS));
/*
* TODO: Currently limited to filtering out one of
* ("CAN","EXP"). Could use "Act" in addition to "act", but this
* should really be fixed the underlying system.
* request.addConstraint("act", new RequestConstraint("CAN",
* ConstraintType.NOT_EQUALS));
*/
request.addConstraint("act", new RequestConstraint("EXP",
ConstraintType.NOT_EQUALS));
request.addConstraint("phensig", new RequestConstraint(
phensigList, ConstraintType.IN));
// TODO: Talk to Jonathan about this... Do I even need officeid
// IN or is ugc zone good enough?
/*
* Get all UGCs in the CWA now so that the watches will be
* formatted with all portions of the affected state(s).
*
* Filtering for valid UGCs is performed in processATEntries
*/
RequestConstraint ugcConstraint = new RequestConstraint("",
ConstraintType.IN);
ugcConstraint.setConstraintValueList(warngenLayer
.getAllUgcs());
request.addConstraint("ugcZone", ugcConstraint);
// These are the only fields we need for processing watches
request.addFields(new String[] { "issueTime", "startTime",
"endTime", "ugcZone", "phensig", "vtecstr", "etn",
"act" });
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
List<ActiveTableRecord> records = new ArrayList<ActiveTableRecord>(
response.getNumResults());
for (Map<String, Object> result : response.getResults()) {
/*
* TODO: Doing this here because only "EXP" is filtered out
* by the query. Remove "act" from the field list once this
* is fixed.
*/
if ("CAN".equals(result.get("act")))
continue;
ActiveTableRecord record = recordType.newInstance();
record.setIssueTime((Calendar) result.get("issueTime"));
record.setStartTime((Calendar) result.get("startTime"));
record.setEndTime((Calendar) result.get("endTime"));
record.setUgcZone((String) result.get("ugcZone"));
record.setPhensig((String) result.get("phensig"));
record.setVtecstr((String) result.get("vtecstr"));
record.setEtn((String) result.get("etn"));
records.add(record);
}
if (records.size() > 0) {
Set<String> validUgcZones;
try {
long t0, t1;
t0 = System.currentTimeMillis();
Polygon watchArea = (Polygon) polygon
.buffer(milesToKilometer.convert(config
.getHatchedAreaSource()
.getIncludedWatchAreaBuffer())
/ KmToDegrees);
t1 = System.currentTimeMillis();
System.out.println("getWatches.polygonBuffer time: "
+ (t1 - t0));
validUgcZones = warngenLayer
.getUgcsForWatches(watchArea);
} catch (RuntimeException e) {
statusHandler
.handle(Priority.ERROR,
"Error determining areas to search for watches.",
e);
return rval;
}
rval = processATEntries(records, warngenLayer,
validUgcZones);
}
}
}
return rval;
}
private static class WatchWork {
public WeatherAdvisoryWatch waw;
public boolean valid;
public ArrayList<String> ugcZone = new ArrayList<String>();
public WatchWork(WeatherAdvisoryWatch waw) {
this.waw = waw;
}
}
/**
* Create the list of objects representing active watches that will be
* passed to the template context.
*
* @param activeTable
* List of entries for active watches
* @param warngenLayer
* @param validUgcZones
* @return
*/
private static WatchUtil processATEntries(
List<ActiveTableRecord> activeTable, WarngenLayer warngenLayer,
Set<String> validUgcZones) {
WatchUtil rval = new WatchUtil();
TreeMap<WeatherAdvisoryWatch, WatchWork> map = new TreeMap<WeatherAdvisoryWatch, TemplateRunner.WatchWork>();
AreaSourceConfiguration asc = null;
for (AreaSourceConfiguration a : warngenLayer.getConfiguration()
.getAreaSources()) {
if (a.getType() == AreaType.HATCHING) {
asc = a;
break;
}
}
if (asc == null) {
statusHandler
.handle(Priority.ERROR,
"Cannot process watches: missing HATCHING area source configuration");
return rval;
}
GeospatialData[] geoData = warngenLayer.getGeodataFeatures(
asc.getAreaSource(), warngenLayer.getLocalizedSite());
if ((geoData == null) || (geoData.length == 0)) {
statusHandler.handle(Priority.ERROR,
"Cannot process watches: cannot get geospatial data");
return rval;
}
// For each watch event, get the end time and list of active zones
for (ActiveTableRecord ar : activeTable) {
/*
* Currently reports all zones in the watch even if a given zone is
* not in the warning polygon. If the logic is changed to only show
* the portions of the watch near our warning polygon, filter on
* validUgcZones here.
*/
WeatherAdvisoryWatch waw = new WeatherAdvisoryWatch();
waw.setPhensig(ar.getPhensig());
try {
waw.setEventId(Integer.parseInt(ar.getEtn()));
} catch (RuntimeException e) {
statusHandler.handle(Priority.ERROR, String.format(
"Watch %s has null end time; not included.",
ar.getVtecstr()));
continue;
}
WatchWork work = map.get(waw);
if (work == null) {
waw.setEndTime(ar.getEndTime().getTime());
work = new WatchWork(waw);
map.put(waw, work);
}
if (validUgcZones.contains(ar.getUgcZone())) {
work.valid = true;
}
/*
* There are no checks here to determine whether or not the given
* zone is in the CWA. That should have already been done the query
* performed in getWatches.
*
* There is also validation performed later in
* determineAffectedPortions.
*/
work.ugcZone.add(ar.getUgcZone());
}
for (WatchWork work : map.values()) {
/*
* If none of the areas in the watch were neer our warning polygon,
* do not included it.
*/
if (!work.valid) {
continue;
}
boolean isMarineZone = warngenLayer.getConfiguration().getGeospatialConfig()
.getAreaSource().equalsIgnoreCase(WarngenLayer.MARINE);
if (!isMarineZone) {
if (determineAffectedPortions(work.ugcZone, asc, geoData, work.waw)) {
rval.addWaw(work.waw);
}
} else {
if (determineAffectedMarinePortions(work.ugcZone, asc, geoData, work.waw)) {
rval.addWaw(work.waw);
}
}
}
return rval;
}
/**
* Given the list of counties in a watch, fill out the "portions" part of
* the given WeatherAdvisoryWatch. Also checks if the given counties are
* actually in the CWA.
*
* @param ugcs
* @param asc
* @param geoData
* @param waw
*/
private static boolean determineAffectedPortions(List<String> ugcs,
AreaSourceConfiguration asc, GeospatialData[] geoData,
WeatherAdvisoryWatch waw) {
// Maps state abbreviation to unique fe_area values
HashMap<String, Set<String>> map = new HashMap<String, Set<String>>();
for (String ugc : ugcs) {
Map<String, String[]> parsed = FipsUtil.parseHeader(ugc, "County");
Entry<String, String[]> e = null;
// Either zero or more than one sates/counties would be wrong
if ((parsed.size() != 1)
|| ((e = parsed.entrySet().iterator().next()).getValue().length != 1)) {
statusHandler.handle(Priority.ERROR,
"Invalid ugczone in active table entry: " + ugc);
continue;
}
String stateAbbrev = e.getKey();
String feArea = null;
try {
feArea = getFeArea(stateAbbrev, e.getValue()[0], asc, geoData);
} catch (RuntimeException exc) {
statusHandler.handle(Priority.ERROR,
"Error generating included watches.", exc);
return false;
}
if (feArea == NOT_IN_CWA) {
continue;
}
Set<String> feAreas = map.get(stateAbbrev);
if (feAreas == null) {
feAreas = new HashSet<String>();
map.put(stateAbbrev, feAreas);
}
if (feArea != null) {
feAreas.add(feArea);
}
}
ArrayList<Portion> portions = new ArrayList<Portion>(map.size());
for (Entry<String, Set<String>> e : map.entrySet()) {
Portion portion = new Portion();
try {
portion.parentRegion = getStateName(e.getKey(), asc, geoData)
.toUpperCase();
} catch (RuntimeException exc) {
statusHandler.handle(Priority.ERROR,
"Error generating included watches.", exc);
return false;
}
portion.partOfParentRegion = Area
.converFeAreaToPartList(mungeFeAreas(e.getValue()));
portions.add(portion);
}
waw.setPortions(portions);
// Set legacy values
if (portions.size() > 0) {
waw.setParentRegion(portions.get(0).parentRegion);
waw.setPartOfParentRegion(portions.get(0).partOfParentRegion);
}
return true;
}
/**
* Given the list of marine zones in a watch, fill out the "portions" part of
* the given WeatherAdvisoryWatch. Also checks if the given marine zones are
* actually in the CWA.
*
* @param ugcs
* @param asc
* @param geoData
* @param waw
*/
@SuppressWarnings("deprecation")
private static boolean determineAffectedMarinePortions(List<String> ugcs,
AreaSourceConfiguration asc, GeospatialData[] geoData,
WeatherAdvisoryWatch waw) {
// Maps state abbreviation to unique fe_area values
HashMap<String, Set<String>> map = new HashMap<String, Set<String>>();
Set<String> marinezonenameSet = new HashSet<String>();
for (String ugc : ugcs) {
for (GeospatialData gd: geoData) {
if (gd.attributes.get("ID").equals(ugc)) {
marinezonenameSet.add((String)gd.attributes.get("NAME"));
}
}
}
String marinezonename = "";
int size = marinezonenameSet.size();
Iterator<String> iter = marinezonenameSet.iterator();
int count = 0;
while (iter.hasNext()) {
String s = iter.next();
marinezonename += s;
count += 1;
if (size > 1) {
if (size == 2 && count < 2) {
marinezonename += " and ";
} else {
if (count == size - 1) {
marinezonename += ", and ";
} else {
if (count < size - 1) {
marinezonename += ", ";
}
}
}
}
}
for (String ugc : ugcs) {
Map<String, String[]> parsed = FipsUtil.parseHeader(ugc, "Marine");
Entry<String, String[]> e = null;
// Either zero or more than one marine zone would be wrong
if ((parsed.size() != 1)
|| ((e = parsed.entrySet().iterator().next()).getValue().length != 1)) {
statusHandler.handle(Priority.ERROR,
"Invalid ugczone in active table entry: " + ugc);
continue;
}
String stateAbbrev = e.getKey();
Set<String> feAreas = map.get(stateAbbrev);
if (feAreas == null) {
feAreas = new HashSet<String>();
map.put(stateAbbrev, feAreas);
}
}
ArrayList<Portion> portions = new ArrayList<Portion>(map.size());
Portion portion = new Portion();
portion.parentRegion = marinezonename;
portion.partOfParentRegion = new ArrayList<String>();
portion.partOfParentRegion.add("");
portions.add(portion);
waw.setPortions(portions);
// Set legacy values
if (portions.size() > 0) {
waw.setParentRegion(portions.get(0).parentRegion);
waw.setPartOfParentRegion(portions.get(0).partOfParentRegion);
}
return true;
}
// Based on AWIPS 1 SELSparagraphs.C SELSparagraphs::processWOU().
private static String mungeFeAreas(Set<String> feAreas) {
String abrev = "";
// If eight or more portions, don't qualify area of state
int m = feAreas.size();
if (m < 8) {
String partAbrev = "";
/*
* TODO: Unused variables should be removed if we are not going to
* improve this in A2.
*/
@SuppressWarnings("unused")
int nw, nc, ne, wc, cc, ec, sw, sc, se, pa;
int eee, www, nnn, sss, ee, ww, nn, ss;
// Identify individual sub areas of this state affected
nw = nc = ne = wc = cc = ec = sw = sc = se = pa = 0;
eee = www = nnn = sss = ee = ww = nn = ss = 0;
for (String part : feAreas) {
if ("pa".equals(part)) {
pa = 1;
continue;
} else if ("nn".equals(part)) {
nnn = nn = 1;
} else if ("ss".equals(part)) {
sss = ss = 1;
} else if ("ee".equals(part)) {
eee = ee = 1;
} else if ("ww".equals(part)) {
www = ww = 1;
} else if ("nw".equals(part)) {
nnn = www = nw = 1;
} else if ("nc".equals(part)) {
nnn = nc = 1;
} else if ("ne".equals(part)) {
nnn = eee = ne = 1;
} else if ("wc".equals(part)) {
www = wc = 1;
} else if ("cc".equals(part)) {
cc = 1;
continue;
} else if ("ec".equals(part)) {
eee = ec = 1;
} else if ("sw".equals(part)) {
sss = www = sw = 1;
} else if ("sc".equals(part)) {
sss = sc = 1;
} else if ("se".equals(part)) {
sss = eee = se = 1;
}
partAbrev = part;
}
// decide how to describe these subareas.
if ((ne > 0) && (nw > 0)) {
nn = 1;
}
if ((se > 0) && (sw > 0)) {
ss = 1;
}
if ((se > 0) && (ne > 0)) {
ee = 1;
}
if ((sw > 0) && (nw > 0)) {
ww = 1;
}
if ((nnn > 0) && (sss > 0) && (eee > 0) && (www > 0)) {
return abrev;
}
if (((nn > 0) && (ss > 0)) || ((ee > 0) && (ww > 0))) {
return abrev;
}
if (nnn + sss + eee + www == 3) {
if (www == 0) {
abrev = "e";
} else if (eee == 0) {
abrev = "w";
} else if (nnn == 0) {
abrev = "s";
} else if (sss == 0) {
abrev = "n";
}
return abrev;
}
if (((nnn == sss) && (eee == www)) || (cc == m)) {
abrev = "c";
return abrev;
}
if ((pa != 0) && (cc == 0)) {
abrev = "pa";
if (--m <= 0) {
return abrev;
}
}
if (m == 1 + cc) {
abrev += partAbrev + " ";
return abrev;
}
if (nnn != sss) {
abrev += nnn != 0 ? "n" : "s";
}
if (eee != www) {
abrev += eee != 0 ? "e" : "w";
}
}
return abrev;
}
private static String getStateName(String key, AreaSourceConfiguration asc,
GeospatialData[] geoData) {
for (GeospatialData g : geoData) {
if (key.equals(g.attributes.get("STATE"))) {
return (String) g.parent.attributes.get("NAME");
}
}
return null;
}
private static String NOT_IN_CWA = new String("NOT_IN_CWA");
/**
* Determines if the given UGC is in the CWA and if it is, returns the
* portion of the CWA.
*
* @param stateAbbrev
* @param ugc
* @param asc
* @param geoData
* @return
*/
private static String getFeArea(String stateAbbrev, String ugc,
AreaSourceConfiguration asc, GeospatialData[] geoData) {
for (GeospatialData g : geoData) {
if (stateAbbrev.equals(g.attributes.get("STATE"))
&& ((String) g.attributes.get(asc.getFipsField()))
.endsWith(ugc)) {
return (String) g.attributes.get(asc.getFeAreaField());
}
}
// TODO: Is this the correct way to determine if the county is in the
// CWA?
return NOT_IN_CWA;
}
}

View file

@ -1,100 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.util;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
/**
* This utility will provide an object to be sent into velocity templates which
* will allow the template to output current Warnings.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 1, 2009 bwoodle Initial creation
*
* </pre>
*
* @author bwoodle
* @version 1.0
*/
public class WatchUtil {
private Date latestTorTime;
private Date latestSvrTime;
private ArrayList<WeatherAdvisoryWatch> torWatches;
private ArrayList<WeatherAdvisoryWatch> svrWatches;
public WatchUtil() {
torWatches = new ArrayList<WeatherAdvisoryWatch>();
svrWatches = new ArrayList<WeatherAdvisoryWatch>();
}
public void addWaw(WeatherAdvisoryWatch watch) {
if (watch.getPhensig().equalsIgnoreCase("SV.A")) {
svrWatches.add(watch);
if (latestSvrTime == null
|| watch.getEndTime().after(latestSvrTime)) {
latestSvrTime = watch.getEndTime();
}
} else if (watch.getPhensig().equalsIgnoreCase("TO.A")) {
torWatches.add(watch);
if (latestTorTime == null
|| watch.getEndTime().after(latestTorTime)) {
latestTorTime = watch.getEndTime();
}
}
}
public ArrayList<WeatherAdvisoryWatch> getTorWatches() {
Set<WeatherAdvisoryWatch> rval = new TreeSet<WeatherAdvisoryWatch>();
for (WeatherAdvisoryWatch w : torWatches) {
w.setEndTime(latestTorTime);
rval.add(w);
}
return new ArrayList<WeatherAdvisoryWatch>(rval);
}
public ArrayList<WeatherAdvisoryWatch> getSvrWatches() {
Set<WeatherAdvisoryWatch> rval = new TreeSet<WeatherAdvisoryWatch>();
for (WeatherAdvisoryWatch w : svrWatches) {
w.setEndTime(latestSvrTime);
rval.add(w);
}
return new ArrayList<WeatherAdvisoryWatch>(rval);
}
public Date getLatestTorTime() {
return latestTorTime;
}
public Date getLatestSvrTime() {
return latestSvrTime;
}
}

View file

@ -1,155 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.util;
import java.util.Date;
import java.util.List;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 1, 2009 bwoodle Initial creation
* Nov 9, 2012 DR 15430 D. Friedman Support proper watch inclusion language
*
* </pre>
*
* @author bwoodle
* @version 1.0
*/
public class WeatherAdvisoryWatch implements Comparable<WeatherAdvisoryWatch> {
public static class Portion {
public String parentRegion;
public List<String> partOfParentRegion;
public String getParentRegion() {
return parentRegion;
}
public void setParentRegion(String parentRegion) {
this.parentRegion = parentRegion;
}
public List<String> getPartOfParentRegion() {
return partOfParentRegion;
}
public void setPartOfParentRegion(List<String> partOfParentRegion) {
this.partOfParentRegion = partOfParentRegion;
}
}
/* TODO: NOTE: There is no site field. We currently only process
* WCNs for the site and not WOUs from the SPC.
*/
private String phensig;
private int eventId;
private Date endTime;
private List<Portion> portions;
@Deprecated
private String parentRegion;
@Deprecated
private List<String> partOfParentRegion;
public String getPhensig() {
return phensig;
}
public void setPhensig(String phensig) {
this.phensig = phensig;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
@Deprecated
public String getParentRegion() {
return parentRegion;
}
@Deprecated
public void setParentRegion(String parentRegion) {
this.parentRegion = parentRegion;
}
@Deprecated
public List<String> getPartOfParentRegion() {
return partOfParentRegion;
}
@Deprecated
public void setPartOfParentRegion(List<String> partOfParentRegion) {
this.partOfParentRegion = partOfParentRegion;
}
@Override
public boolean equals(Object obj) {
return obj instanceof WeatherAdvisoryWatch &&
this.compareTo((WeatherAdvisoryWatch) obj) == 0;
}
public int compareTo(WeatherAdvisoryWatch waw) {
if (this.phensig == null)
return waw.phensig == null ? 0 : -1;
else if (waw.phensig == null)
return 1;
else {
int c = this.phensig.compareTo(waw.phensig);
if (c == 0)
return this.eventId - waw.eventId;
else
return c;
}
}
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
public List<Portion> getPortions() {
return portions;
}
public void setPortions(List<Portion> portions) {
this.portions = portions;
}
}

View file

@ -189,33 +189,35 @@ ${drainage.name}##
########END MACRO
#macro(inserttorwatches $watches $list $secondtimezone $dateUtil $timeFormat)
#set($torWatches = ${watches.getTorWatches()})
#set($torWatchAlso = "")
#set($torWatchFirst = 1)
#foreach(${watch} in ${torWatches})
#if($torWatchFirst)
#set($torWatchFirst = 0)
#else
##
#set($tornadoWatches = [])
#foreach(${watch} in ${watches})
#if(${watch.getPhenSig()} == 'TO.A')
#set($success = $tornadoWatches.add($watch))
#set($endTime = ${watch.endTime})
#if(!$latestEndTime || ${endTime.after($latestEndTime)})
#set($latestEndTime = ${endTime})
#end
A TORNADO WATCH ${torWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${watches.getLatestTorTime()},${timeFormat.plain}, 15, ${localtimezone})}##
#end
#end
#if(!${list.isEmpty($tornadoWatches)})
A TORNADO WATCH REMAINS IN EFFECT UNTIL ${dateUtil.format(${latestEndTime}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${latestEndTime},${timeFormat.plain}, 15, ${localtimezone})}##
#if(${secondtimezone})
/${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/##
#end
FOR ##
#set($numPortions = ${list.size(${watch.getPortions()})})
#set($numPortions = ${list.size(${tornadoWatches})})
#set($count = 0)
#foreach(${portion} in ${watch.getPortions()})
#foreach(${watch} in ${tornadoWatches})
#set($count = $count + 1)
#areaFormat(${portion.partOfParentRegion} true false true)${portion.parentRegion}##
#areaFormat(${watch.partOfState} true false true)${watch.state}##
#if($count == $numPortions - 1)
AND ##
#elseif($count < $numPortions)
...##
#end
#end
#set($torWatchAlso = "ALSO ")
. ##
#end
@ -223,33 +225,35 @@ ${dateUtil.period(${watches.getLatestTorTime()},${timeFormat.plain}, 15, ${local
########END MACRO
#macro(insertsvrwatches $watches $list $secondtimezone $dateUtil $timeFormat)
#set($svrWatches = ${watches.getSvrWatches()})
#set($svrWatchAlso = "")
#set($svrWatchFirst = 1)
#foreach(${watch} in ${svrWatches})
#if($svrWatchFirst)
#set($svrWatchFirst = 0)
#else
##
#set($severeWatches = [])
#foreach(${watch} in ${watches})
#if(${watch.getPhenSig()} == 'SV.A')
#set($success = $severeWatches.add($watch))
#set($endTime = ${watch.endTime})
#if(!$latestEndTime || ${endTime.after($latestEndTime)})
#set($latestEndTime = ${endTime})
#end
A SEVERE THUNDERSTORM WATCH ${svrWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${watches.getLatestSvrTime()},${timeFormat.plain}, 15, ${localtimezone})}##
#end
#end
#if(!${list.isEmpty($severeWatches)})
A SEVERE THUNDERSTORM WATCH REMAINS IN EFFECT UNTIL ${dateUtil.format(${latestEndTime}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${latestEndTime},${timeFormat.plain}, 15, ${localtimezone})}##
#if(${secondtimezone})
/${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/##
#end
FOR ##
#set($numPortions = ${list.size(${watch.getPortions()})})
#set($numPortions = ${list.size(${severeWatches})})
#set($count = 0)
#foreach(${portion} in ${watch.getPortions()})
#foreach(${watch} in ${severeWatches})
#set($count = $count + 1)
#areaFormat(${portion.partOfParentRegion} true false true)${portion.parentRegion}##
#areaFormat(${watch.partOfState} true false true)${watch.state}##
#if($count == $numPortions - 1)
AND ##
#elseif($count < $numPortions)
...##
#end
#end
#set($svrWatchAlso = "ALSO ")
. ##
#end
@ -368,18 +372,6 @@ SOUTH##
#if(${list.contains($directionSet, "WEST")})
#set($output = "${output}WEST")
#end
#if(${list.contains($directionSet, "NE")})
#set($output = "${output}NORTHEAST")
#end
#if(${list.contains($directionSet, "NW")})
#set($output = "${output}NORTHWEST")
#end
#if(${list.contains($directionSet, "SE")})
#set($output = "${output}SOUTHEAST")
#end
#if(${list.contains($directionSet, "SW")})
#set($output = "${output}SOUTHWEST")
#end
#if(${useCentral} && ${list.contains($directionSet, "CENTRAL")})
#if(${list.contains($directionSet, "NORTH")} || ${list.contains($directionSet, "SOUTH")} || ${list.contains($directionSet, "EAST")} || ${list.contains($directionSet, "WEST")})
#set($output = "${output} ")

View file

@ -119,11 +119,11 @@ FOR THE FOLLOWING THREATS...
## If sites do not want watches in their AWW product comment out the
## section below
#######################################################################
#if(${list.contains(${includedWatches}, "torWatches")} && ${list.contains(${bullets}, "includeTorWatches")})
#if(${list.contains(${includedWatches}, "TO.A")} && ${list.contains(${bullets}, "includeTorWatches")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")} && ${list.contains(${bullets}, "includeSvrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")} && ${list.contains(${bullets}, "includeSvrWatches")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -48,11 +48,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -59,11 +59,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<enableDamBreakThreat>true</enableDamBreakThreat>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>.
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
-->

View file

@ -191,10 +191,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -52,11 +52,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -69,10 +69,10 @@ THIS IS A TEST MESSAGE. ##
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -238,10 +238,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -346,10 +346,10 @@ THIS IS A TEST MESSAGE.##
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -468,10 +468,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -512,10 +512,10 @@ THIS IS A TEST MESSAGE.##
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end

View file

@ -57,11 +57,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the svs -->

View file

@ -52,7 +52,7 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
</includedWatches>

View file

@ -67,11 +67,11 @@ Must be paired with proper vm code (also commented out in flashFloodWarning.vm)!
<!-- <trackEnabled>true</trackEnabled> -->
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -624,12 +624,12 @@ TORRENTIAL RAINFALL IS OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FLOODIN
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#* NO NEED TO INCLUDE SVR T-STM WATCHES IN A SVR WARNING!!!!
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#
#end

View file

@ -54,10 +54,10 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -290,10 +290,10 @@ ${expcanPhrase} ${addthreat}
###########################################
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
@ -1180,7 +1180,7 @@ TORRENTIAL RAINFALL IS OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FLOODIN
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")} && ${phenomena}=="SV")
#if(${list.contains(${includedWatches}, "TO.A")} && ${phenomena}=="SV")
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -72,8 +72,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
</phensigs>
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<enableRestart>false</enableRestart>

View file

@ -470,10 +470,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")

View file

@ -52,11 +52,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -397,10 +397,10 @@ ${canwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -571,10 +571,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -679,10 +679,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -880,10 +880,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#elseif(${CORCAN} == "true")
@ -952,10 +952,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -1142,10 +1142,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -1219,10 +1219,10 @@ ${expwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end

View file

@ -52,11 +52,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the svs -->

View file

@ -51,11 +51,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations -->

View file

@ -51,11 +51,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations -->

View file

@ -471,7 +471,7 @@ TORRENTIAL RAINFALL IS ALSO OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FL
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -58,10 +58,10 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -262,10 +262,10 @@ ${expcanPhrase} ${addthreat}
###########################################
## WATCHES ##
#############
###if(${list.contains(${includedWatches}, "torWatches")})
###if(${list.contains(${includedWatches}, "TO.A")})
###inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
###end
###if(${list.contains(${includedWatches}, "svrWatches")})
###if(${list.contains(${includedWatches}, "SV.A")})
###insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
###end
#if(${list.contains(${bullets}, "svrboxactive")})
@ -924,7 +924,7 @@ TORRENTIAL RAINFALL IS ALSO OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FL
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")} && ${phenomena}=="SV")
#if(${list.contains(${includedWatches}, "TO.A")} && ${phenomena}=="SV")
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -69,8 +69,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
</phensigs>
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<enableRestart>false</enableRestart>

View file

@ -230,11 +230,11 @@ LOCATIONS CAN EXPECT !** EXPECTED SNOW **! INCHES OF SNOW.
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")} && ${list.contains(${bullets}, "includeTorWatches")})
#if(${list.contains(${includedWatches}, "TO.A")} && ${list.contains(${bullets}, "includeTorWatches")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")} && ${list.contains(${bullets}, "includeSvrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")} && ${list.contains(${bullets}, "includeSvrWatches")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -54,11 +54,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -309,10 +309,10 @@ IF ON OR NEAR !**Name Of Lake**!...GET OUT OF THE WATER AND MOVE INDOORS OR INSI
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
####################################

View file

@ -50,11 +50,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -431,10 +431,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")

View file

@ -54,11 +54,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -365,10 +365,10 @@ ${canwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -538,10 +538,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -646,10 +646,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -845,10 +845,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#elseif(${CORCAN} == "true")
@ -917,10 +917,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
@ -1104,10 +1104,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -1182,10 +1182,10 @@ ${expwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end

View file

@ -56,11 +56,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the svs -->

View file

@ -49,11 +49,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->