Merge tag 'OB_14.4.1-20m' into master_15.1.1
14.4.1-20m Conflicts: cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/ui/dialogs/MonitoringAreaConfigDlg.java edexOsgi/build.edex/esb/conf/logback.xml edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml rpms/awips2.core/Installer.ldm/patch/etc/pqact.conf.template Former-commit-id: 1d282a64da2998d91040a7c97f2e81beea0a8da4
This commit is contained in:
commit
133a603566
341 changed files with 5474 additions and 75122 deletions
|
@ -124,7 +124,7 @@ public class RadarServer implements RadarEventListener {
|
|||
addListener(new DedicatedRadarActivator(this));
|
||||
addListener(new RequestScheduler(this));
|
||||
addListener(new RadarServerAvailable(this));
|
||||
addListener(new RadarWatchdogListener(configuration));
|
||||
addListener(new RadarWatchdogListener(this));
|
||||
}
|
||||
|
||||
public void addListener(RadarEventListener l) {
|
||||
|
|
|
@ -29,7 +29,8 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.raytheon.rcm.config.Configuration;
|
||||
import com.raytheon.rcm.config.RadarConfig;
|
||||
import com.raytheon.rcm.server.StatusManager.RadarStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -43,6 +44,8 @@ import com.raytheon.rcm.config.Configuration;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------- ---------- ----------- --------------------------
|
||||
* May 12, 2014 DR 16319 dhuffman Initial creation.
|
||||
* Feb 10, 2015 DR 17112 D. Friedman Only alarm on dedicated radars and
|
||||
* once per detected failure.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -56,18 +59,16 @@ public class RadarWatchdog extends Thread {
|
|||
|
||||
protected static class GsmItem {
|
||||
protected String radarID;
|
||||
protected int vcp;
|
||||
protected long time;
|
||||
protected long alarmTime;
|
||||
protected long nextAlarmTime;
|
||||
protected int trackedVcp;
|
||||
protected int currentVcp;
|
||||
protected boolean failed;
|
||||
|
||||
protected GsmItem() {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class RadarItem {
|
||||
protected String radarID;
|
||||
protected String mnemonic;
|
||||
protected boolean isNew;
|
||||
protected long time;
|
||||
protected long messageTime;
|
||||
|
||||
|
@ -75,7 +76,10 @@ public class RadarWatchdog extends Thread {
|
|||
}
|
||||
}
|
||||
|
||||
private long startTime = 0;
|
||||
protected static class WatchedRadar {
|
||||
|
||||
}
|
||||
|
||||
private long shortestWait = 0;
|
||||
private static final long fudgeTime = 30;
|
||||
|
||||
|
@ -84,13 +88,13 @@ public class RadarWatchdog extends Thread {
|
|||
private static Map<Integer, Integer> mapDuration = new ConcurrentHashMap<Integer, Integer>();
|
||||
private static List<String> mapMnemonicProducts = new ArrayList<String>();
|
||||
|
||||
protected Configuration configuration;
|
||||
protected RadarServer radarServer;
|
||||
private static String configFileName = "radarWatchdog.txt";
|
||||
|
||||
protected RadarWatchdog(Configuration conf) {
|
||||
protected RadarWatchdog(RadarServer radarServer) {
|
||||
super("Watchdog");
|
||||
setDaemon(true);
|
||||
startTime = System.currentTimeMillis();
|
||||
configuration = conf;
|
||||
this.radarServer = radarServer;
|
||||
|
||||
loadConfigFile(configFileName);
|
||||
|
||||
|
@ -102,112 +106,145 @@ public class RadarWatchdog extends Thread {
|
|||
}
|
||||
}
|
||||
|
||||
public GsmItem getGSMItem(final String radarID) {
|
||||
return mapGSM.get(radarID);
|
||||
}
|
||||
|
||||
public void putGSMItem(GsmItem gi) {
|
||||
if (gi != null) {
|
||||
mapGSM.put(gi.radarID, gi);
|
||||
}
|
||||
}
|
||||
|
||||
public RadarItem getRadarItem(final String Mnemonic, final String radarID) {
|
||||
Map<String, RadarItem> mapRadar = mapMnemonic.get(Mnemonic);
|
||||
if (mapRadar != null)
|
||||
return mapRadar.get(radarID);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void putRadarItem(RadarItem ri) {
|
||||
if (ri != null) {
|
||||
Map<String, RadarItem> mapRadar = mapMnemonic.get(ri.mnemonic);
|
||||
if (mapRadar != null) {
|
||||
mapRadar.put(ri.radarID, ri);
|
||||
public synchronized void notifyGsm(String radarID, int vcp) {
|
||||
GsmItem item = mapGSM.get(radarID);
|
||||
if (item != null) {
|
||||
item.currentVcp = vcp;
|
||||
notifyWatchdog();
|
||||
} else {
|
||||
if (isTrackedRadar(radarID)) {
|
||||
item = new GsmItem();
|
||||
item.radarID = radarID;
|
||||
item.currentVcp = vcp;
|
||||
mapGSM.put(radarID, item);
|
||||
notifyWatchdog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isTrackedRadar(String radarID) {
|
||||
RadarConfig rc = radarServer.getConfiguration().getConfigForRadar(radarID);
|
||||
return rc != null && rc.isDedicated();
|
||||
}
|
||||
|
||||
public synchronized void notifyRadarItem(String radarID, String mnemonic, long messageTime, long time) {
|
||||
if (! isTrackedRadar(radarID))
|
||||
return;
|
||||
|
||||
RadarItem ri = getRadarItem(mnemonic, radarID);
|
||||
if (ri != null) {
|
||||
ri.isNew = false;
|
||||
ri.messageTime = messageTime;
|
||||
ri.time = time;
|
||||
}
|
||||
}
|
||||
|
||||
private RadarItem getRadarItem(final String mnemonic, final String radarID) {
|
||||
Map<String, RadarItem> mapRadar = mapMnemonic.get(mnemonic);
|
||||
if (mapRadar != null) {
|
||||
RadarItem ri = mapRadar.get(radarID);
|
||||
if (ri == null) {
|
||||
ri = new RadarItem();
|
||||
ri.isNew = true;
|
||||
mapRadar.put(radarID, ri);
|
||||
}
|
||||
return ri;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long currentTime = 0;
|
||||
shortestWait = 0;
|
||||
while (true) {
|
||||
|
||||
try {
|
||||
synchronized (semifore) {
|
||||
semifore.wait(shortestWait < 800 ? 800 : shortestWait);
|
||||
currentTime = System.currentTimeMillis();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
patrol(currentTime);
|
||||
patrol(System.currentTimeMillis());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void patrol(long currentTime) {
|
||||
private synchronized void patrol(long currentTime) {
|
||||
long duration = 0;
|
||||
long adjustedTime = currentTime - fudgeTime;
|
||||
shortestWait = 0;
|
||||
long earliestCheckTime = 0;
|
||||
Iterator<GsmItem> git = mapGSM.values().iterator();
|
||||
while (git.hasNext()) {
|
||||
GsmItem gi = git.next();
|
||||
if (mapDuration.get(gi.vcp) != null) {
|
||||
duration = mapDuration.get(gi.vcp) * 1000;
|
||||
|
||||
Iterator<String> mnem = mapMnemonicProducts.iterator();
|
||||
while (mnem.hasNext()) {
|
||||
String mn = mnem.next();
|
||||
Map<String, RadarItem> mapRadar = mapMnemonic.get(mn);
|
||||
if (mapRadar == null)
|
||||
continue;
|
||||
RadarItem ri = mapRadar.get(gi.radarID);
|
||||
if (! isTrackedRadar(gi.radarID)) {
|
||||
git.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ri == null) {
|
||||
if (duration + startTime < adjustedTime
|
||||
&& gi.alarmTime != startTime) {
|
||||
alert(duration, gi, mn);
|
||||
gi.alarmTime = startTime;
|
||||
gi.nextAlarmTime = startTime + duration;
|
||||
}
|
||||
|
||||
if (shortestWait < 1 || duration < shortestWait)
|
||||
shortestWait = duration;
|
||||
}
|
||||
/* There will be an alarm when the radar connection goes down, so
|
||||
* do not do any additional alarming.
|
||||
*/
|
||||
RadarStatus rs = radarServer.getStatusManager().getRadarStatus(gi.radarID);
|
||||
if (rs != null && rs.getCurrentGSM() == null) {
|
||||
gi.trackedVcp = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gi.currentVcp != gi.trackedVcp) {
|
||||
for (String mn : mapMnemonicProducts) {
|
||||
RadarItem ri = getRadarItem(mn, gi.radarID);
|
||||
if (ri != null) {
|
||||
ri.isNew = true;
|
||||
}
|
||||
}
|
||||
gi.trackedVcp = gi.currentVcp;
|
||||
}
|
||||
|
||||
if (ri.time + duration < adjustedTime) {
|
||||
if (ri.time <= gi.alarmTime
|
||||
&& gi.nextAlarmTime < currentTime) {
|
||||
alert(duration, gi, ri.mnemonic);
|
||||
gi.alarmTime = ri.time;
|
||||
gi.nextAlarmTime = currentTime + duration;
|
||||
}
|
||||
if (gi.nextAlarmTime < currentTime)
|
||||
gi.alarmTime = ri.time;
|
||||
}
|
||||
if (mapDuration.get(gi.trackedVcp) != null) {
|
||||
boolean allOk = true;
|
||||
duration = (mapDuration.get(gi.trackedVcp) + fudgeTime) * 1000;
|
||||
|
||||
if ((duration + ri.time) - adjustedTime < shortestWait
|
||||
&& 1 <= (duration + ri.time) - adjustedTime)
|
||||
shortestWait = (duration + ri.time) - adjustedTime;
|
||||
if (shortestWait < 1)
|
||||
shortestWait = duration;
|
||||
for (String mn : mapMnemonicProducts) {
|
||||
RadarItem ri = getRadarItem(mn, gi.radarID);
|
||||
if (ri == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ri.isNew) {
|
||||
ri.isNew = false;
|
||||
ri.time = currentTime;
|
||||
} else {
|
||||
long diff = currentTime - ri.time;
|
||||
if (diff < duration) {
|
||||
long nextTime = ri.time + duration;
|
||||
if (earliestCheckTime == 0 || nextTime < earliestCheckTime) {
|
||||
earliestCheckTime = nextTime;
|
||||
}
|
||||
} else {
|
||||
allOk = false;
|
||||
alert(duration, gi, mn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allOk) {
|
||||
gi.failed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shortestWait = earliestCheckTime > 0 ? earliestCheckTime - currentTime : 0;
|
||||
}
|
||||
|
||||
private void alert(final long duration, final GsmItem gi, final String mn) {
|
||||
String AlertVizMessage = "Watchdog: Radar ";
|
||||
AlertVizMessage += gi.radarID + " has not produced a '" + mn
|
||||
+ "' product in the last " + duration / 1000 + " seconds.";
|
||||
RadarServerAvailable.sendNotification(gi.radarID, AlertVizMessage);
|
||||
if (! gi.failed) {
|
||||
gi.failed = true;
|
||||
String AlertVizMessage = "Watchdog: Radar ";
|
||||
AlertVizMessage += gi.radarID + " has not produced a '" + mn
|
||||
+ "' product in the last " + duration / 1000 + " seconds.";
|
||||
RadarServerAvailable.sendNotification(gi.radarID, AlertVizMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyWatchdog() {
|
||||
|
@ -218,7 +255,8 @@ public class RadarWatchdog extends Thread {
|
|||
|
||||
private boolean loadConfigFile(final String filename) {
|
||||
try {
|
||||
InputStream inFile = configuration.getDropInData(filename);
|
||||
InputStream inFile = radarServer.getConfiguration().
|
||||
getDropInData(filename);
|
||||
InputStreamReader reader = new InputStreamReader(inFile);
|
||||
BufferedReader in = new BufferedReader(reader);
|
||||
String line;
|
||||
|
|
|
@ -44,6 +44,8 @@ import com.raytheon.rcm.server.RadarWatchdog;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------- ---------- ----------- --------------------------
|
||||
* May 12, 2014 DR 16319 dhuffman Initial creation.
|
||||
* Feb 10, 2015 DR 17112 D. Friedman Only alarm on dedicated radars and
|
||||
* once per detected failure.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -61,8 +63,8 @@ public class RadarWatchdogListener extends RadarEventAdapter {
|
|||
mnemonicMap.put("HSW", "SW");
|
||||
}
|
||||
|
||||
public RadarWatchdogListener(Configuration configuration) {
|
||||
radarWatchdog = new RadarWatchdog(configuration);
|
||||
public RadarWatchdogListener(RadarServer radarServer) {
|
||||
radarWatchdog = new RadarWatchdog(radarServer);
|
||||
radarWatchdog.start();
|
||||
}
|
||||
|
||||
|
@ -81,25 +83,14 @@ public class RadarWatchdogListener extends RadarEventAdapter {
|
|||
}
|
||||
|
||||
if (gsm != null) {
|
||||
RadarWatchdog.GsmItem gi = new RadarWatchdog.GsmItem();
|
||||
gi.radarID = event.getRadarID();
|
||||
gi.vcp = gsm.vcp;
|
||||
gi.time = gsm.time.getTimeInMillis();
|
||||
|
||||
RadarWatchdog.GsmItem oldgi = radarWatchdog
|
||||
.getGSMItem(gi.radarID);
|
||||
if (oldgi == null
|
||||
|| (oldgi != null && oldgi.time <= gi.time)) {
|
||||
radarWatchdog.putGSMItem(gi);
|
||||
}
|
||||
radarWatchdog.notifyGsm(event.getRadarID(), gsm.vcp);
|
||||
}
|
||||
|
||||
} else if (16 <= messageCode) {
|
||||
int mcode = 0;
|
||||
PDB pdb = null;
|
||||
RadarWatchdog.RadarItem ri = new RadarWatchdog.RadarItem();
|
||||
mcode = Message.messageCodeOf(msg);
|
||||
ri.messageTime = (Message.decodeHeader(msg).time)
|
||||
long messageTime = (Message.decodeHeader(msg).time)
|
||||
.getTimeInMillis();
|
||||
|
||||
RadarProduct rp = ProductInfo.getInstance().getPoductForCode(
|
||||
|
@ -107,10 +98,9 @@ public class RadarWatchdogListener extends RadarEventAdapter {
|
|||
if (rp == null)
|
||||
return;
|
||||
|
||||
ri.mnemonic = rp.mnemonic;
|
||||
String newMnemonic = mnemonicMap.get(ri.mnemonic);
|
||||
if (newMnemonic != null)
|
||||
ri.mnemonic = newMnemonic;
|
||||
String mnemonic = mnemonicMap.get(rp.mnemonic);
|
||||
if (mnemonic == null)
|
||||
mnemonic = rp.mnemonic;
|
||||
|
||||
try {
|
||||
pdb = GraphicProduct.pdbOfMessage(msg);
|
||||
|
@ -120,17 +110,8 @@ public class RadarWatchdogListener extends RadarEventAdapter {
|
|||
}
|
||||
|
||||
if (pdb != null) {
|
||||
ri.radarID = event.getRadarID();
|
||||
ri.time = System.currentTimeMillis();
|
||||
|
||||
RadarWatchdog.RadarItem oldri = radarWatchdog.getRadarItem(
|
||||
ri.mnemonic, ri.radarID);
|
||||
|
||||
if (oldri == null
|
||||
|| (oldri != null && oldri.messageTime <= ri.messageTime)) {
|
||||
radarWatchdog.putRadarItem(ri);
|
||||
radarWatchdog.notifyWatchdog();
|
||||
}
|
||||
radarWatchdog.notifyRadarItem(event.getRadarID(), mnemonic,
|
||||
messageTime, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,24 @@
|
|||
<include file="${edex.home}/conf/logback-edex-loggers.xml" />
|
||||
<include file="${edex.home}/conf/logback-edex-hibernate-logger.xml" />
|
||||
|
||||
<!-- activeTableChange log -->
|
||||
<appender name="activeTableChangeLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="com.raytheon.uf.common.status.logback.StdTimeBasedRollingPolicy">
|
||||
<name>activeTableChange</name>
|
||||
</rollingPolicy>
|
||||
<encoder class="com.raytheon.uf.common.status.logback.UFStdEncoder"/>
|
||||
</appender>
|
||||
|
||||
<appender name="activeTableChangeLogAsync" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<appender-ref ref="activeTableChangeLog" />
|
||||
</appender>
|
||||
|
||||
<logger name="ActiveTableChange" additivity="false">
|
||||
<level value="DEBUG"/>
|
||||
<appender-ref ref="activeTableChangeLogAsync" />
|
||||
</logger>
|
||||
|
||||
|
||||
<!-- default logging -->
|
||||
<root>
|
||||
<level value="INFO"/>
|
||||
|
|
|
@ -14,6 +14,7 @@ truststore=truststore.jks
|
|||
|
||||
keystorePw=
|
||||
keyPw=
|
||||
cn=
|
||||
encryptionKey=encrypt
|
||||
truststorePw=password
|
||||
|
||||
|
@ -96,21 +97,36 @@ do
|
|||
fi
|
||||
done
|
||||
|
||||
cn=$(hostname)
|
||||
while [ -z $cn ];
|
||||
do
|
||||
echo -n "Enter canonical name/IP or blank for default [$(hostname)]: "
|
||||
read cn
|
||||
if [ -z $cn ];
|
||||
then
|
||||
echo "Canonical Name defaulting to [$(hostname)];"
|
||||
cn=$(hostname)
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Generating keystore..."
|
||||
keytool -genkeypair -alias $keyAlias -keypass $keyPw -keystore $keystore -storepass $keystorePw -validity 360 -dname "CN=$cn, OU=AWIPS, O=Raytheon, L=Omaha, ST=NE, C=US" -keyalg RSA
|
||||
# get rid of an existing key with same name
|
||||
echo "Check to see if a key with this alias exists.....[$keyAlias]!"
|
||||
keytool -delete -alias $keyAlias -keystore $securityDir/$keystore
|
||||
# create and add key
|
||||
keytool -genkeypair -alias $keyAlias -keypass $keyPw -keystore $keystore -storepass $keystorePw -validity 360 -dname "CN=$cn, OU=AWIPS, O=Raytheon, L=Silver Spring, ST=MD, C=US" -keyalg RSA
|
||||
echo -n "Exporting public key..."
|
||||
exportOutput=`keytool -exportcert -alias $keyAlias -keystore $keystore -file $keyAlias$publicKeyFile -storepass $keystorePw 2>&1`
|
||||
echo "Done!"
|
||||
obfuscatedKeystorePassword=`$JAVA_BIN -cp /awips2/edex/lib/dependencies/org.apache.commons.codec/commons-codec-1.4.jar:/awips2/edex/lib/plugins/com.raytheon.uf.common.security.jar com.raytheon.uf.common.security.encryption.AESEncryptor encrypt $encryptionKey $keystorePw 2>&1`
|
||||
echo "Generating trust store..."
|
||||
|
||||
echo "Check to see if a trusted CA with this alias exists.....[$keyAlias]!"
|
||||
keytool -delete -alias $keyAlias -keystore $securityDir/$truststore
|
||||
keytool -genkey -alias tmp -keypass tempPass -dname CN=foo -keystore $truststore -storepass $truststorePw
|
||||
keytool -delete -alias tmp -keystore $truststore -storepass $truststorePw
|
||||
keytool -import -trustcacerts -file $keyAlias$publicKeyFile -alias $keyAlias -keystore $truststore -storepass $truststorePw
|
||||
|
||||
jettyObscuredPassword=`$JAVA_BIN -cp /awips2/edex/lib/dependencies/org.eclipse.jetty/jetty-http-7.6.14.v20131031.jar:/awips2/edex/lib/dependencies/org.eclipse.jetty/jetty-util-7.6.14.v20131031.jar org.eclipse.jetty.util.security.Password $keystorePw 2>&1 | grep OBF`
|
||||
jettyObscuredPassword=`$JAVA_BIN -cp /awips2/edex/lib/dependencies/org.eclipse.jetty/jetty-http-8.1.15.v20140411.jar:/awips2/edex/lib/dependencies/org.eclipse.jetty/jetty-util-8.1.15.v20140411.jar org.eclipse.jetty.util.security.Password $keystorePw 2>&1 | grep OBF`
|
||||
|
||||
obfuscatedTruststorePassword=`$JAVA_BIN -cp /awips2/edex/lib/dependencies/org.apache.commons.codec/commons-codec-1.4.jar:/awips2/edex/lib/plugins/com.raytheon.uf.common.security.jar com.raytheon.uf.common.security.encryption.AESEncryptor encrypt $encryptionKey $truststorePw 2>&1`
|
||||
|
||||
|
@ -167,6 +183,11 @@ do
|
|||
echo "Alias cannot be empty!"
|
||||
fi
|
||||
done
|
||||
|
||||
# delete any existing cert in the truststore for this alias
|
||||
echo "Check to see if a certificate with this alias exists.....[$userAlias]!"
|
||||
keytool -delete -alias $userAlias -keystore $securityDir/$truststore
|
||||
# add the cert as a Self Signed CA to truststore
|
||||
keytool -import -trustcacerts -file $keyfile -alias $userAlias -keystore $securityDir/$truststore
|
||||
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ import com.raytheon.viz.ui.views.CaveWorkbenchPageManager;
|
|||
* to display messages.
|
||||
* Jun 16, 2014 3288 bclement feed venue configuration changes
|
||||
* Oct 08, 2014 3705 bclement moved venue joining code to CollaborationConnection
|
||||
* Mar 10, 2015 4238 njensen null check in getSessionId()
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -109,12 +110,15 @@ public class DisplayFeedAction extends Action {
|
|||
CollaborationConnection connection = CollaborationConnection
|
||||
.getConnection();
|
||||
String sessionId = null;
|
||||
for (ISession session : connection.getSessions()) {
|
||||
if (session instanceof IVenueSession) {
|
||||
FeedVenueConfig config = FeedVenueConfigManager.getConfig();
|
||||
if (((IVenueSession) session).getVenueName().equalsIgnoreCase(
|
||||
config.getName())) {
|
||||
sessionId = session.getSessionId();
|
||||
// connection can be null in rare cases
|
||||
if (connection != null) {
|
||||
for (ISession session : connection.getSessions()) {
|
||||
if (session instanceof IVenueSession) {
|
||||
FeedVenueConfig config = FeedVenueConfigManager.getConfig();
|
||||
if (((IVenueSession) session).getVenueName()
|
||||
.equalsIgnoreCase(config.getName())) {
|
||||
sessionId = session.getSessionId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ import com.vividsolutions.jts.geom.Geometry;
|
|||
* Apr 28, 2014 3086 skorolev Removed local getMonitorAreaConfig method.
|
||||
* Sep 04, 2014 3220 skorolev Updated configUpdate method and added updateMonitoringArea.
|
||||
* Sep 23, 2014 3356 njensen Remove unnecessary import
|
||||
* Mar 09, 2014 3888 dhladky Stopped processing when dialogs are null or disposed.
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
|
@ -366,14 +367,20 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
|
|||
*/
|
||||
@Override
|
||||
protected void process(ObReport result) throws Exception {
|
||||
obData.addReport(result);
|
||||
String zone = findZone(result.getPlatformId());
|
||||
if (zone != null) {
|
||||
AreaContainer ac = getTableData().getArea(zone);
|
||||
if (ac != null) {
|
||||
ac.addReport(result.getObservationTime(), result);
|
||||
fireMonitorEvent(this);
|
||||
|
||||
if (zoneDialog != null && !zoneDialog.isDisposed()) {
|
||||
|
||||
obData.addReport(result);
|
||||
String zone = findZone(result.getPlatformId());
|
||||
if (zone != null) {
|
||||
AreaContainer ac = getTableData().getArea(zone);
|
||||
if (ac != null) {
|
||||
ac.addReport(result.getObservationTime(), result);
|
||||
fireMonitorEvent(this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
monitor.nullifyMonitor();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.util.Date;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import com.raytheon.uf.common.monitor.data.CommonConfig;
|
||||
|
@ -47,6 +46,7 @@ import com.raytheon.uf.viz.monitor.thresholds.AbstractThresholdMgr;
|
|||
* Oct.29, 2012 1297 skorolev Changed HashMap to Map
|
||||
* Oct.31 2012 1297 skorolev Cleaned code.
|
||||
* Sep 04 2014 3220 skorolev Added updateZones method.
|
||||
* Mar 17 2015 3888 dhladky check for nulls
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -227,8 +227,11 @@ public class ObHourReports {
|
|||
List<String> stations = new CopyOnWriteArrayList<String>(
|
||||
hourReports.get(zone).getZoneHourReports().keySet());
|
||||
for (String stn : stations) {
|
||||
if (!zoneStationMap.get(zone).contains(stn)) {
|
||||
hourReports.get(zone).getZoneHourReports().remove(stn);
|
||||
if (zoneStationMap.get(zone) != null) {
|
||||
if (!zoneStationMap.get(zone).contains(stn)) {
|
||||
hourReports.get(zone).getZoneHourReports()
|
||||
.remove(stn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!zoneStationMap.keySet().contains(zone)) {
|
||||
|
@ -241,14 +244,16 @@ public class ObHourReports {
|
|||
List<String> stations = new CopyOnWriteArrayList<String>(
|
||||
zoneStationMap.get(zone));
|
||||
for (String stn : stations) {
|
||||
if (!hourReports.get(zone).getZoneHourReports()
|
||||
.containsKey(stn)) {
|
||||
hourReports
|
||||
.get(zone)
|
||||
.getZoneHourReports()
|
||||
.put(stn,
|
||||
new ObStnHourReports(nominalTime, zone,
|
||||
stn, appName, thresholdMgr));
|
||||
if (hourReports.get(zone) != null) {
|
||||
if (!hourReports.get(zone).getZoneHourReports()
|
||||
.containsKey(stn)) {
|
||||
hourReports
|
||||
.get(zone)
|
||||
.getZoneHourReports()
|
||||
.put(stn,
|
||||
new ObStnHourReports(nominalTime, zone,
|
||||
stn, appName, thresholdMgr));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hourReports.containsKey(zone)) {
|
||||
|
|
|
@ -78,6 +78,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
* Sep 24, 2014 2757 skorolev Fixed problem with adding and removing zones.
|
||||
* Oct 27, 2014 3667 skorolev Corrected functionality of dialog. Cleaned code.
|
||||
* Nov 12, 2014 3650 skorolev Added confirmation box for unsaved changes in the dialog.
|
||||
* Mar 08, 2015 3888 dhladky Restored threshold pop-up when adding new stations/zones.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -1481,12 +1482,7 @@ public abstract class MonitoringAreaConfigDlg extends CaveSWTDialog implements
|
|||
* Reset data status.
|
||||
*/
|
||||
protected void resetStatus() {
|
||||
if (!configMgr.getAddedZones().isEmpty()) {
|
||||
configMgr.getAddedZones().clear();
|
||||
}
|
||||
if (!configMgr.getAddedStations().isEmpty()) {
|
||||
configMgr.getAddedStations().clear();
|
||||
}
|
||||
|
||||
this.timeWindowChanged = false;
|
||||
this.maZonesRemoved = false;
|
||||
this.maStationsRemoved = false;
|
||||
|
|
|
@ -48,7 +48,7 @@ import com.raytheon.viz.ui.EditorUtil;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* May 2009 # bsteffen Initial creation
|
||||
* Nov 2013 # mccaslin Only one GUI dialog at a time
|
||||
* Oct 2014 # mccaslin Improved error handeling
|
||||
* Oct 2014 # mccaslin Improved error handeling
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -56,7 +56,8 @@ import com.raytheon.viz.ui.EditorUtil;
|
|||
* @version 1.0
|
||||
*/
|
||||
public class LapsToolsAction extends AbstractHandler {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(LapsToolsAction.class);
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(LapsToolsAction.class);
|
||||
|
||||
/**
|
||||
* LAPS Tools dialog.
|
||||
|
@ -65,50 +66,49 @@ public class LapsToolsAction extends AbstractHandler {
|
|||
|
||||
public static LAPSToolsDlg getLapsToolsDlg() {
|
||||
return lapsToolsDlg;
|
||||
}
|
||||
}
|
||||
|
||||
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||
.getShell();
|
||||
|
||||
|
||||
if (lapsToolsDlg == null) {
|
||||
try {
|
||||
lapsToolsDlg = new LAPSToolsDlg(shell);
|
||||
lapsToolsDlg.addListener(SWT.Dispose, new Listener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
lapsToolsDlg = null;
|
||||
}
|
||||
});
|
||||
|
||||
if (lapsToolsDlg.isLapsInstalled()) {
|
||||
lapsToolsDlg.open();
|
||||
} else {
|
||||
String whatLapsIs ="LAPS data assimilation system, system requirements: " +
|
||||
"\n\to LAPS v2.0 installed" +
|
||||
"\n\to EDEX 'SITE' file containing LAPS domain, i.e. domain.xml" +
|
||||
"\n\n\n(Sorry LAPS does not work in the ADAM implementation of AWIPS.)";
|
||||
//Note: Go through the LAPS v2.0 Scripting Interface first, if you find that LAPS is not installed.
|
||||
|
||||
MessageBox mb = new MessageBox(EditorUtil.getActiveEditor().getSite().getShell(), SWT.ICON_WARNING | SWT.OK);
|
||||
mb.setText("Cannot open LAPS V2.0 Tools GUI");
|
||||
mb.setMessage(whatLapsIs);
|
||||
mb.open();
|
||||
lapsToolsDlg = null;
|
||||
lapsToolsDlg = new LAPSToolsDlg(shell);
|
||||
lapsToolsDlg.addListener(SWT.Dispose, new Listener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
lapsToolsDlg = null;
|
||||
}
|
||||
});
|
||||
|
||||
//int val = mb.open();
|
||||
//if (val == SWT.OK) {
|
||||
// AlertViz Customization Update
|
||||
//return false;
|
||||
//}
|
||||
if (lapsToolsDlg.isLapsInstalled()) {
|
||||
lapsToolsDlg.open();
|
||||
} else {
|
||||
String whatLapsIs = "LAPS is not installed. ";
|
||||
// Note: Go through the LAPS v2.0 Scripting Interface first,
|
||||
// if you find that LAPS is not installed.
|
||||
|
||||
}
|
||||
MessageBox mb = new MessageBox(EditorUtil.getActiveEditor()
|
||||
.getSite().getShell(), SWT.ICON_ERROR | SWT.OK);
|
||||
mb.setText("Cannot open the LAPS tool");
|
||||
mb.setMessage(whatLapsIs);
|
||||
mb.open();
|
||||
lapsToolsDlg = null;
|
||||
|
||||
// int val = mb.open();
|
||||
// if (val == SWT.OK) {
|
||||
// AlertViz Customization Update
|
||||
// return false;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error: Cannot open LAPS V2.0 Tools GUI", e);
|
||||
}
|
||||
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error: Cannot open LAPS V2.0 Tools GUI", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.io.File;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -27,6 +28,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel
|
|||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
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.uf.common.time.SimulatedTime;
|
||||
|
@ -36,8 +38,8 @@ import com.raytheon.viz.awipstools.ui.action.LapsToolsData.LapsDomain;
|
|||
import com.vividsolutions.jts.geom.Envelope;
|
||||
|
||||
/**
|
||||
* This class no longer performs all the file system, server input/output for laps.
|
||||
* LAPS support scripts now conduct the localization process.
|
||||
* This class no longer performs all the file system, server input/output for
|
||||
* laps. LAPS support scripts now conduct the localization process.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -55,147 +57,150 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
*/
|
||||
public class LapsToolsIO {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(LapsToolsIO.class);
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(LapsToolsIO.class);
|
||||
|
||||
private static final String WHATGOTIN_FILE_FRMT = "%s/%s.wgi";
|
||||
|
||||
private static File fxaData;
|
||||
|
||||
private static File lapsLogs;
|
||||
|
||||
|
||||
private static List<String> whatgotinFiles;
|
||||
|
||||
private static List<String> dataChoices;
|
||||
|
||||
|
||||
static {
|
||||
// TODO all this configuration should be customizable by the user.
|
||||
// --- For what got in log files ---
|
||||
// --- For what got in log files ---
|
||||
if (System.getenv("FXA_DATA") == null) {
|
||||
fxaData = new File("/data/fxa");
|
||||
fxaData = new File("/data/fxa");
|
||||
} else {
|
||||
fxaData = new File(System.getenv("FXA_DATA"));
|
||||
}
|
||||
lapsLogs = new File(fxaData + "/laps/log/wgi");
|
||||
whatgotinFiles = Arrays.asList("sfc", "wind", "lq3driver", "cloud", "temp");
|
||||
dataChoices = Arrays.asList("Surface Analysis",
|
||||
"Wind Analysis",
|
||||
"Humidity Analysis",
|
||||
"Cloud Analysis",
|
||||
"Temperature Analysis");
|
||||
whatgotinFiles = Arrays.asList("sfc", "wind", "lq3driver", "cloud",
|
||||
"temp");
|
||||
dataChoices = Arrays.asList("Surface Analysis", "Wind Analysis",
|
||||
"Humidity Analysis", "Cloud Analysis", "Temperature Analysis");
|
||||
}
|
||||
|
||||
public static Collection<String> getDataChoices() {
|
||||
return dataChoices;
|
||||
}
|
||||
|
||||
public static String getLogs(String type) throws IOException,
|
||||
VizException {
|
||||
public static String getLogs(String type) throws IOException, VizException {
|
||||
String wgiFile = String.format(WHATGOTIN_FILE_FRMT, lapsLogs,
|
||||
whatgotinFiles.get(dataChoices.indexOf(type)));
|
||||
whatgotinFiles.get(dataChoices.indexOf(type)));
|
||||
String resultIO = loadWhatGotInFile(wgiFile, type);
|
||||
return (resultIO);
|
||||
return (resultIO);
|
||||
}
|
||||
|
||||
private static String loadWhatGotInFile(String wfile, String type)
|
||||
throws IOException {
|
||||
BufferedReader reader;
|
||||
StringBuilder output = new StringBuilder();
|
||||
File file = new File(wfile);
|
||||
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
String arg = String.format("*** Cannot find expected log file for %s." +
|
||||
"\n*** File %s ....does not appear to exist.\n\n",
|
||||
type, file.getAbsolutePath());
|
||||
output.append(arg);
|
||||
return output.toString();
|
||||
}
|
||||
private static String loadWhatGotInFile(String wfile, String type)
|
||||
throws IOException {
|
||||
BufferedReader reader;
|
||||
StringBuilder output = new StringBuilder();
|
||||
File file = new File(wfile);
|
||||
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
String arg = String
|
||||
.format("*** Cannot find expected log file for %s."
|
||||
+ "\n*** File %s ....does not appear to exist.\n\n",
|
||||
type, file.getAbsolutePath());
|
||||
output.append(arg);
|
||||
return output.toString();
|
||||
}
|
||||
String line;
|
||||
int lineNumber = 0;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String arg = String.format("%04d: %s%n", ++lineNumber, line);
|
||||
output.append(arg);
|
||||
output.append(arg);
|
||||
}
|
||||
reader.close();
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
|
||||
public static LapsToolsData loadData() throws IOException, VizException,
|
||||
SpatialException {
|
||||
LapsToolsData data = new LapsToolsData();
|
||||
if(LapsToolsIO.readXmlFile(data)) {
|
||||
LapsToolsIO.readCountyWarningArea(data);
|
||||
if (LapsToolsIO.readXmlFile(data)) {
|
||||
LapsToolsIO.readCountyWarningArea(data);
|
||||
} else {
|
||||
data = null;
|
||||
data = null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static boolean readXmlFile(LapsToolsData data)
|
||||
throws IOException, VizException {
|
||||
|
||||
|
||||
public static boolean readXmlFile(LapsToolsData data) throws IOException,
|
||||
VizException {
|
||||
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
LocalizationContext lc = pm.getContext(LocalizationType.COMMON_STATIC,
|
||||
LocalizationLevel.SITE);
|
||||
LocalizationFile xmlLocalizationFile = pm.getLocalizationFile(lc, "LAPS/domain" +
|
||||
".xml");
|
||||
if(!xmlLocalizationFile.exists()) return false;
|
||||
|
||||
LapsDomain domain = new LapsDomain();
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(LapsDomain.class);
|
||||
//unmarshal XML file to java object
|
||||
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
|
||||
domain = (LapsDomain) jaxbUnmarshaller.unmarshal(xmlLocalizationFile.getFile());
|
||||
|
||||
} catch (JAXBException e) {
|
||||
throw new VizException("xml is unreadable: "+e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
LocalizationContext lc = pm.getContext(LocalizationType.COMMON_STATIC,
|
||||
LocalizationLevel.SITE);
|
||||
LocalizationFile xmlLocalizationFile = pm.getLocalizationFile(lc,
|
||||
"LAPS/domain" + ".xml");
|
||||
if (!xmlLocalizationFile.exists())
|
||||
return false;
|
||||
|
||||
LapsDomain domain = new LapsDomain();
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(LapsDomain.class);
|
||||
// unmarshal XML file to java object
|
||||
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
|
||||
domain = (LapsDomain) jaxbUnmarshaller
|
||||
.unmarshal(xmlLocalizationFile.getFile());
|
||||
|
||||
} catch (JAXBException e) {
|
||||
throw new VizException("xml is unreadable: "
|
||||
+ e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
data.setNx(domain.getNx());
|
||||
data.setNy(domain.getNy());
|
||||
data.setNz(domain.getNz());
|
||||
data.setGridSpacing(domain.getGridSpacing());
|
||||
data.setGridCenterLon(domain.getGridCenLon());
|
||||
data.setGridCenterLat(domain.getGridCenLat());
|
||||
data.setGridCenterLat(domain.getGridCenLat());
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void defaultDomain(LapsToolsData data)
|
||||
throws IOException, VizException {
|
||||
double distance = 111; //111 km per 1 degree
|
||||
double gridSpacingDefault = 3500.;
|
||||
public static void defaultDomain(LapsToolsData data) throws IOException,
|
||||
VizException {
|
||||
double distance = 111; // 111 km per 1 degree
|
||||
double gridSpacingDefault = 3500.;
|
||||
double dim = 200;
|
||||
double N = dim * dim;
|
||||
|
||||
|
||||
Envelope shapeArea = data.getValidAreaOrig();
|
||||
double widthY = Math.abs(shapeArea.getHeight() * distance);
|
||||
double widthX = Math.abs( (shapeArea.getWidth() * distance) * (Math.cos(shapeArea.centre().x) ) );
|
||||
double widthX = Math.abs((shapeArea.getWidth() * distance)
|
||||
* (Math.cos(shapeArea.centre().x)));
|
||||
double aspectRatio = widthY / widthX;
|
||||
double buffer = 0.5;
|
||||
int nX = (int) (Math.sqrt(N/aspectRatio) + buffer);
|
||||
int nX = (int) (Math.sqrt(N / aspectRatio) + buffer);
|
||||
int nY = (int) ((aspectRatio * nX) + buffer);
|
||||
|
||||
System.out.print("LAPS Tools IO:\nheight = "+shapeArea.getHeight()+ " width = "+shapeArea.getWidth());
|
||||
System.out.print("\naspect ratio = "+aspectRatio);
|
||||
System.out.print("\nnX = "+nX+", nY = "+nY+"\n");
|
||||
|
||||
LapsDomain domain = new LapsDomain();
|
||||
System.out.print("LAPS Tools IO:\nheight = " + shapeArea.getHeight()
|
||||
+ " width = " + shapeArea.getWidth());
|
||||
System.out.print("\naspect ratio = " + aspectRatio);
|
||||
System.out.print("\nnX = " + nX + ", nY = " + nY + "\n");
|
||||
|
||||
LapsDomain domain = new LapsDomain();
|
||||
domain.setNx(nX);
|
||||
domain.setNy(nY);
|
||||
domain.setNz(43);
|
||||
domain.setGridSpacing(gridSpacingDefault);
|
||||
domain.setGridCenLon(data.getCwaCenter().x);
|
||||
domain.setGridCenLat(data.getCwaCenter().y);
|
||||
|
||||
domain.setGridCenLat(data.getCwaCenter().y);
|
||||
|
||||
data.setNx(domain.getNx());
|
||||
data.setNy(domain.getNy());
|
||||
data.setNz(domain.getNz());
|
||||
data.setGridSpacing(domain.getGridSpacing());
|
||||
data.setGridCenterLon(data.getCwaCenter().x);
|
||||
data.setGridCenterLat(data.getCwaCenter().y);
|
||||
data.setGridCenterLat(data.getCwaCenter().y);
|
||||
}
|
||||
|
||||
private static void readCountyWarningArea(LapsToolsData data)
|
||||
|
@ -209,23 +214,25 @@ public class LapsToolsIO {
|
|||
return;
|
||||
}
|
||||
data.setCwaArea(result[0].geometry.getEnvelopeInternal());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getWriteXmlQuestion() {
|
||||
String date = new SimpleDateFormat("HH:mm").format(SimulatedTime
|
||||
.getSystemTime().getTime());
|
||||
return String.format("Are you sure you want write domain.xml?" +
|
||||
"\nNote: Its %s and LAPS runs at ~20 minutes after the hour.",date);
|
||||
return String
|
||||
.format("Are you sure you want write domain.xml?"
|
||||
+ "\nNote: Its %s and LAPS runs at ~20 minutes after the hour.",
|
||||
date);
|
||||
}
|
||||
|
||||
public static void writeXmlFile(LapsToolsData data) throws IOException,
|
||||
InterruptedException, VizException {
|
||||
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
LocalizationContext lc = pm.getContext(LocalizationType.COMMON_STATIC,
|
||||
LocalizationLevel.SITE);
|
||||
LocalizationFile xmlLocalizationFile = pm.getLocalizationFile(lc, "LAPS/domain-output" +
|
||||
".xml");
|
||||
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
LocalizationContext lc = pm.getContext(LocalizationType.COMMON_STATIC,
|
||||
LocalizationLevel.USER);
|
||||
LocalizationFile xmlLocalizationFile = pm.getLocalizationFile(lc,
|
||||
"LAPS" + IPathManager.SEPARATOR + "domain.xml");
|
||||
LapsDomain lapsdomain = new LapsDomain();
|
||||
lapsdomain.setNx(data.getNx());
|
||||
lapsdomain.setNy(data.getNy());
|
||||
|
@ -233,7 +240,15 @@ public class LapsToolsIO {
|
|||
lapsdomain.setGridSpacing(data.getGridSpacing());
|
||||
lapsdomain.setGridCenLat(data.getGridCenter().y);
|
||||
lapsdomain.setGridCenLon(data.getGridCenter().x);
|
||||
//marshal java object to XML file
|
||||
JAXB.marshal(lapsdomain, xmlLocalizationFile.getFile());
|
||||
// marshal java object to XML file
|
||||
OutputStream stream;
|
||||
try {
|
||||
stream = xmlLocalizationFile.openOutputStream();
|
||||
JAXB.marshal(lapsdomain, stream);
|
||||
stream.close();
|
||||
xmlLocalizationFile.save();
|
||||
} catch (LocalizationException e) {
|
||||
throw new VizException("Unable to save LapsDomain to xml.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,8 +77,9 @@ import com.raytheon.viz.ui.editor.IMultiPaneEditor;
|
|||
* @version 1.0
|
||||
*/
|
||||
public class LAPSToolsDlg extends CaveSWTDialog {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(LAPSToolsDlg.class);
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(LAPSToolsDlg.class);
|
||||
|
||||
private final LapsToolsData data;
|
||||
|
||||
|
@ -109,7 +110,7 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
*/
|
||||
private boolean isLapsInstalled = false;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Flag indicating which tool is active.
|
||||
*/
|
||||
private boolean isDataUsedByAnalysis = true;
|
||||
|
@ -175,9 +176,9 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
*/
|
||||
private StackLayout stackLayout;
|
||||
|
||||
private MessageBox areaDialog;
|
||||
private MessageBox areaDialog;
|
||||
|
||||
private Label areaStrLbl;
|
||||
private Label areaStrLbl;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -192,16 +193,15 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
|
||||
try {
|
||||
this.data = LapsToolsIO.loadData();
|
||||
if(data==null){
|
||||
isLapsInstalled = false;
|
||||
if (data == null) {
|
||||
isLapsInstalled = false;
|
||||
} else {
|
||||
isLapsInstalled = true;
|
||||
isLapsInstalled = true;
|
||||
}
|
||||
|
||||
|
||||
} catch (VizException e) {
|
||||
MessageDialog
|
||||
.openInformation(shell, "LAPS Tools GUI cannot run.",
|
||||
e.getLocalizedMessage());
|
||||
MessageDialog.openInformation(shell, "LAPS Tools GUI cannot run.",
|
||||
e.getLocalizedMessage());
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new VizException("Laps Dialog Failed to open", e);
|
||||
|
@ -242,8 +242,7 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
createMainControls();
|
||||
|
||||
// create dialog with OK and cancel button and info icon
|
||||
areaDialog =
|
||||
new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
|
||||
areaDialog = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
|
||||
areaDialog.setText("Size of LAPS Domain");
|
||||
}
|
||||
|
||||
|
@ -352,27 +351,27 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
// Create the Help menu item with a Help "dropdown" menu
|
||||
Menu helpMenu = new Menu(menuBar);
|
||||
helpMenuItem.setMenu(helpMenu);
|
||||
|
||||
|
||||
// create dialog with OK and cancel button and info icon
|
||||
final MessageBox dialog =
|
||||
new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
|
||||
final MessageBox dialog = new MessageBox(shell, SWT.ICON_INFORMATION
|
||||
| SWT.OK);
|
||||
dialog.setText("About LAPS details");
|
||||
dialog.setMessage("For additional detailed information about LAPS Tools go to the URL" +
|
||||
"\n\t http://laps.noaa.gov/awipsii/");
|
||||
|
||||
dialog.setMessage("For additional detailed information about LAPS Tools go to the URL"
|
||||
+ "\n\t http://laps.noaa.gov/awipsii/");
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Create all the items in the Help dropdown menu
|
||||
// ------------------------------------------------------
|
||||
|
||||
// Administration menu item
|
||||
// Administration menu item
|
||||
MenuItem aboutMI = new MenuItem(helpMenu, SWT.NONE);
|
||||
aboutMI.setText("About LAPS...");
|
||||
aboutMI.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
dialog.open();
|
||||
dialog.open();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -430,22 +429,24 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
Combo c = (Combo) e.widget;
|
||||
if(c.getSelectionIndex() == 0 && c.getItem(0) == "-- Select a Type --") {
|
||||
//no action
|
||||
} else if(c.getSelectionIndex() != 0 && c.getItem(0) == "-- Select a Type --") {
|
||||
c.remove(0);
|
||||
typeAction((c.getItem(c.getSelectionIndex())));
|
||||
if (c.getSelectionIndex() == 0
|
||||
&& c.getItem(0) == "-- Select a Type --") {
|
||||
// no action
|
||||
} else if (c.getSelectionIndex() != 0
|
||||
&& c.getItem(0) == "-- Select a Type --") {
|
||||
c.remove(0);
|
||||
typeAction((c.getItem(c.getSelectionIndex())));
|
||||
} else {
|
||||
typeAction((c.getItem(c.getSelectionIndex())));
|
||||
typeAction((c.getItem(c.getSelectionIndex())));
|
||||
}
|
||||
}
|
||||
});
|
||||
typeCbo.select(0);
|
||||
typeCbo.setToolTipText("Select one of the options to see what got into this LAPS product." );
|
||||
|
||||
typeCbo.setToolTipText("Select one of the options to see what got into this LAPS product.");
|
||||
|
||||
Label blank = new Label(controlComp, SWT.NONE);
|
||||
blank.setText(" ");
|
||||
|
||||
|
||||
Button clearBtn = new Button(controlComp, SWT.PUSH);
|
||||
clearBtn.setText(" Clear ");
|
||||
clearBtn.addSelectionListener(new SelectionAdapter() {
|
||||
|
@ -455,7 +456,7 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
}
|
||||
});
|
||||
clearBtn.setToolTipText("Clear screen.");
|
||||
|
||||
|
||||
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
|
||||
gd.widthHint = 500;
|
||||
gd.heightHint = 300;
|
||||
|
@ -491,12 +492,13 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
writeDomainBtn.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
writeXmlfileAction();
|
||||
writeXmlfileAction();
|
||||
}
|
||||
});
|
||||
writeDomainBtn.setToolTipText("Write LAPS domain.xml file AND Exit.\n" +
|
||||
"This step will cause scripts to run that redefine the LAPS domain.\n" +
|
||||
"Next cycle of the analysis will show the change in domain made here." );
|
||||
writeDomainBtn
|
||||
.setToolTipText("Write LAPS domain.xml file AND Exit.\n"
|
||||
+ "This step will cause scripts to run that redefine the LAPS domain.\n"
|
||||
+ "Next cycle of the analysis will show the change in domain made here.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -606,36 +608,31 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
nxSpnr.setEnabled(true);
|
||||
nxSpnr.setLayoutData(gd);
|
||||
nxSpnr.addListener(SWT.Verify, new Listener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
data.setNx(nxSpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
data.setNx(nxSpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
});
|
||||
/*nxSpnr.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
data.setNx(nxSpnr.getSelection());
|
||||
//areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
data.setNx(nxSpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
});
|
||||
nxSpnr.addSelectionListener(new SelectionListener() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
data.setNx(nxSpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
/*
|
||||
* nxSpnr.addFocusListener(new FocusListener() {
|
||||
*
|
||||
* @Override public void focusGained(FocusEvent e) {
|
||||
* data.setNx(nxSpnr.getSelection());
|
||||
* //areaStrLbl.setText(data.getAreaCoverageString()); }
|
||||
*
|
||||
* @Override public void focusLost(FocusEvent e) {
|
||||
* data.setNx(nxSpnr.getSelection());
|
||||
* areaStrLbl.setText(data.getAreaCoverageString()); } });
|
||||
* nxSpnr.addSelectionListener(new SelectionListener() {
|
||||
*
|
||||
* @Override public void widgetSelected(SelectionEvent e) {
|
||||
* data.setNx(nxSpnr.getSelection());
|
||||
* areaStrLbl.setText(data.getAreaCoverageString()); }
|
||||
*
|
||||
* @Override public void widgetDefaultSelected(SelectionEvent e) { } });
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ny
|
||||
*/
|
||||
|
@ -655,23 +652,21 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
nySpnr.setEnabled(true);
|
||||
nySpnr.setLayoutData(gd);
|
||||
nySpnr.addListener(SWT.Verify, new Listener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
data.setNy(nySpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
data.setNy(nySpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
});
|
||||
/*nySpnr.addSelectionListener(new SelectionListener() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
data.setNy(nySpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
});
|
||||
*/
|
||||
/*
|
||||
* nySpnr.addSelectionListener(new SelectionListener() {
|
||||
*
|
||||
* @Override public void widgetSelected(SelectionEvent e) {
|
||||
* data.setNy(nySpnr.getSelection());
|
||||
* areaStrLbl.setText(data.getAreaCoverageString()); }
|
||||
*
|
||||
* @Override public void widgetDefaultSelected(SelectionEvent e) { } });
|
||||
*/
|
||||
/*
|
||||
* Dx(m)
|
||||
*/
|
||||
|
@ -691,23 +686,21 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
dxmSpnr.setLayoutData(gd);
|
||||
dxmSpnr.setMinimum(1000);
|
||||
dxmSpnr.addListener(SWT.Verify, new Listener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
data.setGridSpacing((double) dxmSpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
data.setGridSpacing((double) dxmSpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
});
|
||||
/*dxmSpnr.addSelectionListener(new SelectionListener() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
data.setGridSpacing((double) dxmSpnr.getSelection());
|
||||
areaStrLbl.setText(data.getAreaCoverageString());
|
||||
}
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
});
|
||||
*/
|
||||
/*
|
||||
* dxmSpnr.addSelectionListener(new SelectionListener() {
|
||||
*
|
||||
* @Override public void widgetSelected(SelectionEvent e) {
|
||||
* data.setGridSpacing((double) dxmSpnr.getSelection());
|
||||
* areaStrLbl.setText(data.getAreaCoverageString()); }
|
||||
*
|
||||
* @Override public void widgetDefaultSelected(SelectionEvent e) { } });
|
||||
*/
|
||||
/*
|
||||
* Vertical label
|
||||
*/
|
||||
|
@ -744,7 +737,6 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
gridGroup.setLayout(new GridLayout(1, false));
|
||||
gridGroup.setLayoutData(gd);
|
||||
gridGroup.setText(" Area of Coverage ");
|
||||
|
||||
|
||||
/*
|
||||
* Calculated Area label
|
||||
|
@ -768,7 +760,8 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
|
||||
Composite groupComp = new Composite(configureAnalysisComp, SWT.NONE);
|
||||
groupComp.setLayout(gl);
|
||||
groupComp.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
|
||||
groupComp
|
||||
.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
|
||||
|
||||
/*
|
||||
* Settings
|
||||
|
@ -790,8 +783,9 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
setDefaultDomain();
|
||||
}
|
||||
});
|
||||
//defaultBtn.setToolTipText("Set to the default");
|
||||
defaultBtn.setToolTipText("Reset all variables to values so that the LAPS domain will fully include the CWA area");
|
||||
// defaultBtn.setToolTipText("Set to the default");
|
||||
defaultBtn
|
||||
.setToolTipText("Reset all variables to values so that the LAPS domain will fully include the CWA area");
|
||||
|
||||
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
|
||||
gd.widthHint = buttonWidth;
|
||||
|
@ -804,8 +798,8 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
resetDomain();
|
||||
}
|
||||
});
|
||||
resetBtn.setToolTipText("Set to the values that you started with" );
|
||||
|
||||
resetBtn.setToolTipText("Set to the values that you started with");
|
||||
|
||||
/*
|
||||
* LAPS Relocator
|
||||
*/
|
||||
|
@ -826,8 +820,8 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
loadAction();
|
||||
}
|
||||
});
|
||||
loadBtn.setToolTipText("Load the grid info into the display." +
|
||||
"\nRelocate the domain by selecting and moving the grid center.");
|
||||
loadBtn.setToolTipText("Load the grid info into the display."
|
||||
+ "\nRelocate the domain by selecting and moving the grid center.");
|
||||
|
||||
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
|
||||
gd.widthHint = buttonWidth;
|
||||
|
@ -841,8 +835,8 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
applyAction();
|
||||
}
|
||||
});
|
||||
applyBtn.setToolTipText("Fill the selectors with new values, if you" +
|
||||
"\nmoved the domain by relocating the center point." );
|
||||
applyBtn.setToolTipText("Fill the selectors with new values, if you"
|
||||
+ "\nmoved the domain by relocating the center point.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -880,29 +874,29 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
|
||||
private void populateTypeCombo(Combo combo) {
|
||||
combo.add("-- Select a Type --");
|
||||
for (String choice : LapsToolsIO.getDataChoices()) {
|
||||
for (String choice : LapsToolsIO.getDataChoices()) {
|
||||
combo.add(choice);
|
||||
}
|
||||
}
|
||||
|
||||
private void typeAction(String type) {
|
||||
try {
|
||||
stText.append("Begin "+type+"\n");
|
||||
stText.append("Begin " + type + "\n");
|
||||
stText.append(LapsToolsIO.getLogs(type));
|
||||
stText.append("End of "+type);
|
||||
stText.append("End of " + type);
|
||||
stText.append("\n__________________________________________\n\n");
|
||||
stText.setTopIndex(stText.getLineCount());
|
||||
} catch (Exception ex) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
ex.getLocalizedMessage(), ex);
|
||||
statusHandler
|
||||
.handle(Priority.PROBLEM, ex.getLocalizedMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateSpinners() {
|
||||
configureSpinner(cenLatSpnr, data.getGridCenter().y,
|
||||
data.getValidArea().getMinY(), data.getValidArea().getMaxY());
|
||||
configureSpinner(cenLonSpnr, data.getGridCenter().x,
|
||||
data.getValidArea().getMinX(), data.getValidArea().getMaxX());
|
||||
configureSpinner(cenLatSpnr, data.getGridCenter().y, data
|
||||
.getValidArea().getMinY(), data.getValidArea().getMaxY());
|
||||
configureSpinner(cenLonSpnr, data.getGridCenter().x, data
|
||||
.getValidArea().getMinX(), data.getValidArea().getMaxX());
|
||||
configureSpinner(nxSpnr, data.getNx());
|
||||
configureSpinner(nySpnr, data.getNy());
|
||||
configureSpinner(dxmSpnr, data.getGridSpacing());
|
||||
|
@ -945,14 +939,16 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
|
||||
private void setDefaultDomain() {
|
||||
boolean ok = MessageDialog
|
||||
.openConfirm(getShell(), "Confirm Exit",
|
||||
.openConfirm(
|
||||
getShell(),
|
||||
"Confirm Exit",
|
||||
"This will reset all variables to values so that the LAPS domain will fully includes the CWA area.");
|
||||
if (ok) {
|
||||
try {
|
||||
LapsToolsIO.defaultDomain(data);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
populateSpinners();
|
||||
|
@ -967,23 +963,28 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
try {
|
||||
LapsToolsIO.readXmlFile(data);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
populateSpinners();
|
||||
}
|
||||
}
|
||||
|
||||
private void applyAction() {
|
||||
if(data.getLimits()) {
|
||||
System.out.print("LAPS Tools Dlg: problem with domain not covering CWA");
|
||||
if (data.getLimits()) {
|
||||
System.out
|
||||
.print("LAPS Tools Dlg: problem with domain not covering CWA");
|
||||
boolean yes = MessageDialog
|
||||
.openQuestion(getShell(), "Domain Size Error",
|
||||
"The size of the LAPS domain does not cover the entire CWA." +
|
||||
"\nWould you like to move and recenter domain?" +
|
||||
"\n\n(Answering 'No' will allow you to reedit text values, instead.)");
|
||||
if(yes){ return; }
|
||||
}
|
||||
.openQuestion(
|
||||
getShell(),
|
||||
"Domain Size Error",
|
||||
"The size of the LAPS domain does not cover the entire CWA."
|
||||
+ "\nWould you like to move and recenter domain?"
|
||||
+ "\n\n(Answering 'No' will allow you to reedit text values, instead.)");
|
||||
if (yes) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
cenLatSpnr.setEnabled(true);
|
||||
cenLonSpnr.setEnabled(true);
|
||||
nxSpnr.setEnabled(true);
|
||||
|
@ -1011,7 +1012,7 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
}
|
||||
}
|
||||
|
||||
private void loadAction() {
|
||||
private void loadAction() {
|
||||
cenLatSpnr.setEnabled(false);
|
||||
cenLonSpnr.setEnabled(false);
|
||||
nxSpnr.setEnabled(false);
|
||||
|
@ -1023,7 +1024,7 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
defaultBtn.setEnabled(false);
|
||||
writeDomainBtn.setEnabled(false);
|
||||
readSpinners();
|
||||
|
||||
|
||||
GenericToolsResourceData<LapsToolLayer> rd = new GenericToolsResourceData<LapsToolLayer>(
|
||||
LapsToolLayer.DEFAULT_NAME, LapsToolLayer.class);
|
||||
|
||||
|
@ -1047,29 +1048,30 @@ public class LAPSToolsDlg extends CaveSWTDialog {
|
|||
desc.getResourceList().add(rsc);
|
||||
rsc.getCapability(EditableCapability.class).setEditable(true);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeXmlfileAction() {
|
||||
private void writeXmlfileAction() {
|
||||
if (MessageDialog.openQuestion(getShell(), "Confirmation",
|
||||
LapsToolsIO.getWriteXmlQuestion())) {
|
||||
try {
|
||||
LapsToolsIO.writeXmlFile(data);
|
||||
statusHandler.handle(Priority.INFO, //SIGNIFICANT
|
||||
"Write EDEX domain.xml file. This action will initiated a LAPS Localization process.");
|
||||
statusHandler
|
||||
.handle(Priority.INFO, // SIGNIFICANT
|
||||
"Write EDEX domain.xml file. This action will initiate a LAPS Localization process.");
|
||||
close();
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isLapsInstalled() {
|
||||
return isLapsInstalled;
|
||||
}
|
||||
|
||||
return isLapsInstalled;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ Lakes_graphicColor = 'blue'
|
|||
# MAP BACKGROUNDS
|
||||
#MapBackgrounds_default = ['Counties','Marine_Zones_XXX','Interstates']
|
||||
MapBackgrounds_default = ['Zones_XXX','Marine_Zones_XXX','Interstates','States','Lakes']
|
||||
XXX_mask = "XXX_CWA"
|
||||
XXX_mask = "XXX"
|
||||
|
||||
DefaultSamples = ['XXXTornadoThreat']
|
||||
# Customize FONT SIZES here
|
||||
|
|
|
@ -1689,7 +1689,7 @@ Scripts = [
|
|||
"-d {productDB} ",
|
||||
|
||||
"Make and Send HTI:" +
|
||||
"xterm -e ssh px2f /awips2/GFESuite/hti/bin/make_hti.sh",
|
||||
"xterm -e ssh px2f /awips2/GFESuite/hti/bin/make_hti.sh {site}",
|
||||
|
||||
"Official Grids to LDAD: " +
|
||||
"ifpAG -h {host} -r {port} -o - -d {productDB} | gzip -9 > " +
|
||||
|
|
|
@ -213,7 +213,7 @@ class Procedure (SmartScript.SmartScript):
|
|||
elif threatWEName == "FloodingRainThreat":
|
||||
editArea = self.getEditArea("MFL")
|
||||
elif threatWEName == "TornadoThreat":
|
||||
editArea = self.getEditArea("MFL_CWA")
|
||||
editArea = self.getEditArea("MFL")
|
||||
else:
|
||||
editArea = self.getEditArea("Marinezones")
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -43,7 +43,7 @@ VariableList = [("DEFAULT: Typical. Should only be changed in coordination with
|
|||
"Higher (40% Exceedance; for well-behaved systems within 6 hours of the event)",
|
||||
"Highest (50% Exceedance; for well-behaved systems at time of the event)"]),
|
||||
("Grid Smoothing?", "Yes", "radio", ["Yes","No"]),
|
||||
("Make grids from PHISH\n or ICS?\n", "PHISH", "radio", ["PHISH", "ISC"]),
|
||||
("Make grids from PHISH\n or ISC?\n", "PHISH", "radio", ["PHISH", "ISC"]),
|
||||
]
|
||||
|
||||
class Procedure (SmartScript.SmartScript):
|
||||
|
@ -432,7 +432,7 @@ class Procedure (SmartScript.SmartScript):
|
|||
# List of elements
|
||||
# See if we should copy from ISC. If so, do the copy and exit
|
||||
smoothThreatGrid = varDict["Grid Smoothing?"]
|
||||
PHISHorISC = varDict["Make grids from PHISH\n or ICS?\n"]
|
||||
PHISHorISC = varDict["Make grids from PHISH\n or ISC?\n"]
|
||||
#PHISHorISC = "PHISH"
|
||||
topodb = "NED"
|
||||
#topodb = varDict["Topographic Database?"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Version 2014.12.17-0
|
||||
# Version 2015.2.10-1
|
||||
|
||||
import GenericHazards
|
||||
import JsonSupport
|
||||
|
@ -19,7 +19,6 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
def __init__(self):
|
||||
GenericHazards.TextProduct.__init__(self)
|
||||
self._pp = pprint.PrettyPrinter()
|
||||
|
||||
|
||||
###############################################################
|
||||
### Hazards and Additional Hazards
|
||||
|
@ -106,9 +105,9 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
error = self._getVariables(argDict)
|
||||
if error is not None:
|
||||
return error
|
||||
|
||||
self._backupFullStationID = self._fullStationID
|
||||
|
||||
self._argDict = argDict
|
||||
self._productID = self._pil[0:3].upper()
|
||||
|
||||
argDict["definition"] = self._definition
|
||||
|
||||
|
@ -123,6 +122,7 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
# Set up the areaDictionary for all to use
|
||||
accessor = ModuleAccessor.ModuleAccessor()
|
||||
self._areaDict = accessor.variable(self._areaDictionary, "AreaDictionary")
|
||||
|
||||
self._tpc = TextProductCommon()
|
||||
self._tpc.setUp(self._areaDict)
|
||||
|
||||
|
@ -168,7 +168,7 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
def _wmoHeader(self, productDict, productSegmentGroup, arguments=None):
|
||||
headerDict = collections.OrderedDict()
|
||||
headerDict['TTAAii'] = self._wmoID
|
||||
headerDict['originatingOffice'] = self._backupFullStationID # Will be siteID if not in backup mode
|
||||
headerDict['originatingOffice'] = self._fullStationID
|
||||
headerDict['productID'] = self._productID
|
||||
headerDict['siteID'] = self._site
|
||||
headerDict['fullStationID'] = self._fullStationID
|
||||
|
@ -180,6 +180,7 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
headerDict['disclaimer'] = 'This XML wrapped text product should be considered COMPLETELY EXPERIMENTAL. The National Weather Service currently makes NO GUARANTEE WHATSOEVER that this product will continue to be supplied without interruption. The format of this product MAY CHANGE AT ANY TIME without notice.'
|
||||
headerDict['cityState'] = self._wfoCityState
|
||||
headerDict['stormNumber'] = self._getStormNumberStringFromTCP()
|
||||
# Modify the product name to indicate test or experimental mode if necessary
|
||||
self._productName = self.checkTestMode(
|
||||
self._argDict, productSegmentGroup.get('productName') + self._areaName)
|
||||
headerDict['productName'] = self._productName
|
||||
|
@ -194,13 +195,14 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
################# Mixed Level
|
||||
|
||||
def _ugcHeader(self, productDict, productSegmentGroup, productSegment):
|
||||
productDict['ugcCodes'] = self._formatUGC_entries()
|
||||
self._ugcHeader_value = self._tpc.formatUGCs(self._ugcs, self._expireTime)
|
||||
productDict['ugcHeader'] = self._ugcHeader_value
|
||||
# The UGC header is the formatted list of UGCs along with an expire time
|
||||
# For example: 'FLZ066>068-071-072-063-069-073>075-168-172>174-070-230515-'
|
||||
ugcHeader = self._tpc.formatUGCs(self._ugcs, self._expireTime)
|
||||
productDict['ugcHeader'] = ugcHeader
|
||||
|
||||
################# Product Parts Processing
|
||||
|
||||
def _processProductParts(self, productGenerator, productDict, productSegmentGroup, productParts):
|
||||
def _processProductParts(self, productGenerator, productDict, productSegmentGroup, productParts):
|
||||
'''
|
||||
@param productDict
|
||||
@param productSegmentGroup
|
||||
|
@ -249,46 +251,18 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
"Removing product part = %s" % (part), 1)
|
||||
partsList.remove(part)
|
||||
|
||||
################# Product Parts Helper Methods
|
||||
|
||||
def _formatUGC_entries(self):
|
||||
ugcCodeList = []
|
||||
for ugc in self._ugcs:
|
||||
areaDictEntry = self._areaDict.get(ugc)
|
||||
if areaDictEntry is None:
|
||||
# We are not localized correctly for the hazard
|
||||
# So get the first dictionary entry
|
||||
self.logger.info('Not Localized for the hazard area -- ugc' + ugc)
|
||||
keys = self._areaDict.keys()
|
||||
areaDictEntry = self._areaDict.get(keys[0])
|
||||
ugcEntry = collections.OrderedDict()
|
||||
ugcEntry['state'] = areaDictEntry.get('stateAbbr')
|
||||
ugcEntry['type'] = self._getUgcInfo(ugc, 'type')
|
||||
ugcEntry['number'] = self._getUgcInfo(ugc, 'number')
|
||||
ugcEntry['text'] = ugc
|
||||
ugcEntry['subArea'] = ''
|
||||
ugcCodeList.append(ugcEntry)
|
||||
return ugcCodeList
|
||||
|
||||
def _getUgcInfo(self, ugc, part='type'):
|
||||
if part == 'type':
|
||||
if ugc[2] == 'C':
|
||||
return 'County'
|
||||
else:
|
||||
return 'Zone'
|
||||
if part == 'number':
|
||||
return ugc[3:]
|
||||
|
||||
###############################################################
|
||||
### Product Dictionary methods for creating, populating and
|
||||
### formatting the product dictionary
|
||||
|
||||
def _createProductDictionary(self, segmentList):
|
||||
def _createProductDictionary(self, productPartsGenerator, segments, areProductPartsSegmented):
|
||||
# Create the product dictionary
|
||||
productSegmentGroup = self._groupSegments(segmentList)
|
||||
productSegmentGroup = self._groupSegments(productPartsGenerator,
|
||||
segments,
|
||||
areProductPartsSegmented)
|
||||
|
||||
productDict = self._initializeProductDictionary(productSegmentGroup)
|
||||
productParts = productSegmentGroup.get('productParts')
|
||||
productParts = productSegmentGroup.get('productParts')
|
||||
productDict['productParts'] = productParts
|
||||
self._processProductParts(self, productDict, productSegmentGroup, productParts)
|
||||
|
||||
|
@ -323,13 +297,9 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
WGUS63 KBOU 080400
|
||||
FFWBOU
|
||||
|
||||
'''
|
||||
self._productID = productSegmentGroup.get('productID', 'NNN')
|
||||
'''
|
||||
if self._areaName != '':
|
||||
self._areaName = ' FOR ' + self._areaName + '\n'
|
||||
self._geoType = productSegmentGroup.get('geoType')
|
||||
self._mapType = productSegmentGroup.get('mapType')
|
||||
self._productTimeZones = []
|
||||
|
||||
# Fill in product dictionary information
|
||||
productDict = collections.OrderedDict()
|
||||
|
@ -346,14 +316,26 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
### Sampling and Statistics related methods
|
||||
|
||||
def _getStatValue(self, statDict, element, method=None, dataType=None):
|
||||
|
||||
self.debug_print("*"*90, 1)
|
||||
self.debug_print("In _getStatValue looking for '%s'" % (element), 1)
|
||||
self.debug_print("statDict =\n%s" % (pprint.pformat(statDict)), 1)
|
||||
|
||||
stats = statDict.get(element, None)
|
||||
self.debug_print("stats =\n%s" % (pprint.pformat(stats)), 1)
|
||||
|
||||
if stats is None: return None
|
||||
if type(stats) is types.ListType:
|
||||
stats = stats[0]
|
||||
stats, tr = stats
|
||||
if dataType==self.VECTOR():
|
||||
stats, dir = stats
|
||||
|
||||
return self.getValue(stats, method)
|
||||
|
||||
# Define a class to handle missing statistics
|
||||
class StatisticsException(Exception):
|
||||
pass
|
||||
|
||||
###############################################################
|
||||
### Area, Zone and Segment related methods
|
||||
|
@ -361,18 +343,47 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
def _allAreas(self):
|
||||
return self._inlandAreas() + self._coastalAreas()
|
||||
|
||||
def _groupSegments(self, productPartsGenerator, segments, areProductPartsSegmented):
|
||||
'''
|
||||
Group the segments into the products. The TCV and HLS product generators
|
||||
only create a single product each so there is only one product segment group.
|
||||
'''
|
||||
|
||||
segment_vtecRecords_tuples = self._getSegmentVTECRecordsTuples(segments)
|
||||
|
||||
productSegmentGroup = {
|
||||
'productID' : self._productID,
|
||||
'productName': self._productName,
|
||||
'geoType': 'area',
|
||||
'vtecEngine': self._hazardsTable,
|
||||
'mapType': 'publicZones',
|
||||
'segmented': areProductPartsSegmented,
|
||||
'productParts': productPartsGenerator(segment_vtecRecords_tuples),
|
||||
}
|
||||
|
||||
return productSegmentGroup
|
||||
|
||||
def _getSegmentVTECRecordsTuples(self, segments):
|
||||
segment_vtecRecords_tuples = []
|
||||
for segment in segments:
|
||||
vtecRecords = self._getVtecRecords(segment)
|
||||
self.debug_print("vtecRecords for %s =\n\n%s\n" % (segment, self._pp.pformat(vtecRecords)))
|
||||
segment_vtecRecords_tuples.append((segment, vtecRecords))
|
||||
|
||||
return segment_vtecRecords_tuples
|
||||
|
||||
def _computeIntersectAreas(self, editAreas, argDict):
|
||||
editAreaUtils = EditAreaUtils.EditAreaUtils()
|
||||
editAreaUtils.setUp(None, argDict)
|
||||
surgeEditArea = editAreaUtils.getEditArea("StormSurgeWW_EditArea", argDict)
|
||||
intersectAreas =[]
|
||||
intersectAreas = []
|
||||
for (_, editAreaLabel) in editAreas:
|
||||
editArea = editAreaUtils.getEditArea(editAreaLabel, argDict)
|
||||
intersectAreaLabel = "intersect_"+editAreaLabel
|
||||
intersectArea = editAreaUtils.intersectAreas(intersectAreaLabel, editArea, surgeEditArea)
|
||||
grid = intersectArea.getGrid()
|
||||
if grid.isAnyBitsSet():
|
||||
editAreaUtils.saveEditAreas([intersectArea])
|
||||
if grid.isAnyBitsSet(): # Make sure the intersection isn't empty
|
||||
editAreaUtils.saveEditAreas([intersectArea]) # Register the new edit area with the system
|
||||
intersectAreas.append((intersectAreaLabel, intersectAreaLabel))
|
||||
|
||||
return intersectAreas
|
||||
|
@ -382,8 +393,7 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
|
||||
def _initializeHazardsTable(self, argDict):
|
||||
import VTECMessageType
|
||||
productID = self._pil[0:3]
|
||||
vtecMode = VTECMessageType.getVTECMessageType(productID.upper())
|
||||
vtecMode = VTECMessageType.getVTECMessageType(self._productID)
|
||||
argDict["vtecMode"] = vtecMode
|
||||
|
||||
self._setVTECActiveTable(argDict)
|
||||
|
@ -394,10 +404,8 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
self._hazardsTable = self._getHazardsTable(argDict, self.filterMethod)
|
||||
argDict["hazards"] = self._hazardsTable
|
||||
|
||||
def _getHazardsTable(self, argDict, filterMethod, editAreas=None):
|
||||
def _getHazardsTable(self, argDict, filterMethod):
|
||||
# Set up edit areas as list of lists
|
||||
# Need to check hazards against all edit areas in the CWA MAOR
|
||||
argDict["combinations"]= [(self._allAreas(),"Region1")]
|
||||
dfEditAreas = argDict["combinations"]
|
||||
editAreas = []
|
||||
for area, label in dfEditAreas:
|
||||
|
@ -408,21 +416,19 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
else:
|
||||
editAreas.append([area])
|
||||
# Get Product ID and other info for HazardsTable
|
||||
pil = self._pil.upper() # Ensure PIL is in UPPERCASE
|
||||
stationID4 = self._fullStationID
|
||||
productCategory = pil[0:3] #part of the pil
|
||||
productCategory = self._productID
|
||||
definition = argDict['definition']
|
||||
sampleThreshold = definition.get("hazardSamplingThreshold", (10, None))
|
||||
# Process the hazards
|
||||
accurateCities = definition.get('accurateCities', 0)
|
||||
cityRefData = []
|
||||
import HazardsTable
|
||||
hazards = HazardsTable.HazardsTable(
|
||||
argDict["ifpClient"], editAreas, productCategory, filterMethod,
|
||||
argDict["databaseID"],
|
||||
stationID4, argDict["vtecActiveTable"], argDict["vtecMode"], sampleThreshold,
|
||||
creationTime=argDict["creationTime"], accurateCities=accurateCities,
|
||||
cityEditAreas=cityRefData, dataMgr=argDict['dataMgr'])
|
||||
cityEditAreas=[], dataMgr=argDict['dataMgr'])
|
||||
return hazards
|
||||
|
||||
def _ignoreActions(self):
|
||||
|
@ -443,11 +449,20 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
else:
|
||||
argDict["vtecActiveTable"] = "active"
|
||||
|
||||
def _getVtecRecords(self, segment, vtecEngine=None):
|
||||
def _getVtecRecords(self, segment):
|
||||
vtecRecords = self._hazardsTable.getHazardList(segment)
|
||||
# Tropical hazards shouldn't ever have EXT and EXB actions since
|
||||
# they are "until further notice"
|
||||
for record in vtecRecords:
|
||||
if record['act'] == "EXT":
|
||||
record['act'] = "CON"
|
||||
elif record['act'] == "EXB":
|
||||
record['act'] = "EXA"
|
||||
|
||||
return vtecRecords
|
||||
|
||||
def _getAllowedHazardList(self, allowedHazardList=None):
|
||||
# Get the list of allowed phenSigs (ie. "HU.W")
|
||||
if allowedHazardList is None:
|
||||
allowedHazardList = self.allowedHazards()
|
||||
hazardList = []
|
||||
|
@ -588,8 +603,8 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
|
||||
self._ddhhmmTime = self.getCurrentTime(
|
||||
argDict, "%d%H%M", shiftToLocal=0, stripLeading=0)
|
||||
self._currentTime = self._issueTime_secs
|
||||
self._expireTime = self._issueTime_secs + self._purgeTime*3600
|
||||
self._purgeHours = self._purgeTime
|
||||
self._expireTime = self._issueTime_secs + self._purgeHours*3600
|
||||
self._timeLabel = self.getCurrentTime(
|
||||
argDict, "%l%M %p %Z %a %b %e %Y", stripLeading=1)
|
||||
|
||||
|
@ -600,14 +615,13 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
startTime = self._calculateStartTime(time.gmtime(self._issueTime_secs))
|
||||
self._timeRange = self.makeTimeRange(startTime, startTime+120*3600)
|
||||
|
||||
# Create a time range to look from the current time back 12 hours
|
||||
# We will use this are to determine if we need to use "additional"
|
||||
# wording with rainfall
|
||||
# Create a time range to look from the current time back 12 hours.
|
||||
# We will use this to determine if we need to use "additional"
|
||||
# wording with rainfall for the TCV
|
||||
self._extraSampleTimeRange = self.makeTimeRange(startTime-12*3600,
|
||||
startTime)
|
||||
|
||||
# Determine the time range list, making sure they are on hour boundaries
|
||||
# w.r.t. midnight today according to the resolution
|
||||
# Determine the time range list according to the resolution
|
||||
subRanges = self.divideRange(self._timeRange, self._resolution())
|
||||
trList = []
|
||||
self._periodList = []
|
||||
|
@ -617,6 +631,7 @@ class TextProduct(GenericHazards.TextProduct):
|
|||
trList.append((tr, "Label"))
|
||||
|
||||
if index == 0:
|
||||
# Create the 10 periods
|
||||
startTime = tr.startTime()
|
||||
localtime = time.localtime(startTime.unixTime())
|
||||
|
||||
|
@ -1027,8 +1042,9 @@ FORECASTER STEWART"""
|
|||
self._loadLastTwoAdvisories()
|
||||
|
||||
def _synchronizeAdvisories(self):
|
||||
|
||||
# Retrieving a directory causes synching to occur
|
||||
# Retrieving a directory causes synching to occur.
|
||||
# This code can throw an exception but don't catch it
|
||||
# so that forecasters can be made aware of the issue.
|
||||
file = LocalizationSupport.getLocalizationFile(LocalizationSupport.CAVE_STATIC,
|
||||
LocalizationSupport.SITE, self._site,
|
||||
self._getAdvisoryPath()).getFile()
|
||||
|
@ -1091,7 +1107,7 @@ FORECASTER STEWART"""
|
|||
self._previousPreviousAdvisory = None
|
||||
if len(lastTwoAdvisories) >= 2:
|
||||
self._previousPreviousAdvisory = self._loadAdvisory(lastTwoAdvisories[1])
|
||||
|
||||
|
||||
def _loadAdvisory(self, advisoryName):
|
||||
self._synchronizeAdvisories()
|
||||
fileName = self._getAdvisoryFilename(advisoryName)
|
||||
|
@ -1370,10 +1386,10 @@ class TextProductCommon(DiscretePhrases.DiscretePhrases):
|
|||
if laterActive is not None:
|
||||
expireTime = min(expireTime, laterActive)
|
||||
elif canExpFound and not activeFound:
|
||||
expireTime = min(expireTime, issueTime+3600) #1hr from now
|
||||
expireTime = min(expireTime, issueTime+3600*1000) #1hr from now
|
||||
|
||||
#ensure expireTime is not before issueTime, and is at least 1 hour
|
||||
if expireTime - issueTime < 3600:
|
||||
if expireTime - issueTime < 3600*1000:
|
||||
expireTime = issueTime + 3600*1000
|
||||
|
||||
#round to next 'roundMinutes'
|
||||
|
@ -1449,7 +1465,9 @@ class TextProductCommon(DiscretePhrases.DiscretePhrases):
|
|||
def formatUGCs(self, ugcs, expireTime):
|
||||
'''
|
||||
Create ugc header with expire time
|
||||
'COC123-112330-'
|
||||
Examples:
|
||||
'COC123-112330-'
|
||||
'FLZ066>068-071-072-063-069-073>075-168-172>174-070-230515-'
|
||||
'''
|
||||
ugcStr = self.makeUGCString(ugcs)
|
||||
ddhhmmTime = self.getFormattedTime(
|
||||
|
@ -1546,6 +1564,10 @@ class TextProductCommon(DiscretePhrases.DiscretePhrases):
|
|||
def makeUGCString(self, ugcs):
|
||||
'''
|
||||
Create the UGC string for product / segment headers.
|
||||
|
||||
Examples:
|
||||
FLZ173-
|
||||
FLZ066>068-071-072-063-069-073>075-168-172>174-070-
|
||||
'''
|
||||
# if nothing in the list, return empty string
|
||||
if len(ugcs) == 0:
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
# __warnETNduplication() and
|
||||
# __highestETNActiveTable.
|
||||
# 11/11/14 4953 randerso Changed type of endTime from float to int
|
||||
# 02/05/15 4099 randerso Fixed exception handling in __getActiveTable
|
||||
#
|
||||
|
||||
|
||||
|
@ -933,7 +934,7 @@ class HazardsTable(VTECTableUtil.VTECTableUtil):
|
|||
|
||||
except:
|
||||
self.log.exception("Unable to access VTEC Active Table: ")
|
||||
raise Exception, s
|
||||
raise
|
||||
|
||||
def __createCityHazards(self):
|
||||
if not self.__accurateCities:
|
||||
|
|
|
@ -675,10 +675,11 @@ class TextUtils:
|
|||
def getPreviousProduct(self, productID, searchString="", version=0):
|
||||
# gets a previous product from the AWIPS database
|
||||
|
||||
from com.raytheon.viz.gfe.core import DataManagerUIFactory
|
||||
from com.raytheon.viz.gfe.product import TextDBUtil
|
||||
|
||||
# DR 15703 - always retrieve operational products
|
||||
opMode = True
|
||||
# Redmine #17120 - return to pre-DR 15703 behavior.
|
||||
opMode = DataManagerUIFactory.getCurrentInstance().getOpMode().name() == "OPERATIONAL"
|
||||
previousProduct = TextDBUtil.retrieveProduct(productID, version, opMode)
|
||||
previousProduct = string.strip(previousProduct)
|
||||
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# This software is in the public domain, furnished "as is", without technical
|
||||
# support, and with no warranty, express or implied, as to its usefulness for
|
||||
# any purpose.
|
||||
#
|
||||
# DefineMaxWindGUI
|
||||
#
|
||||
# Author:
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
try: # See if this is the AWIPS I environment
|
||||
from Numeric import *
|
||||
import AFPS
|
||||
AWIPS_ENVIRON = "AWIPS1"
|
||||
except: # Must be the AWIPS II environment
|
||||
from numpy import *
|
||||
import AbsTime
|
||||
import TimeRange
|
||||
AWIPS_ENVIRON = "AWIPS2"
|
||||
|
||||
import SmartScript
|
||||
import Tkinter
|
||||
import tkFont
|
||||
|
||||
|
||||
class DefineMaxWindGUI(SmartScript.SmartScript):
|
||||
|
||||
def __init__(self, dbss, eaMgr=None):
|
||||
SmartScript.SmartScript.__init__(self, dbss)
|
||||
|
||||
if AWIPS_ENVIRON == "AWIPS1":
|
||||
self.setUp(eaMgr)
|
||||
|
||||
def reportQuadError(self):
|
||||
self.statusBarMsg("Only three quadants at a time may be reduced.\n" + \
|
||||
"...Please toggle another quadrant off first.","S")
|
||||
return
|
||||
|
||||
def toggleButton(self, buttonLabel):
|
||||
b = self._buttonLabels.index(buttonLabel)
|
||||
if self._buttonState[b]: # button was on
|
||||
self._buttonState[b] = False
|
||||
self._buttonList[b].configure(background="gray", activebackground="gray")
|
||||
else: # button was off
|
||||
if sum(self._buttonState) > 2: # only three at a time allowed
|
||||
self.reportQuadError()
|
||||
return
|
||||
self._buttonState[b] = True
|
||||
self._buttonList[b].configure(background="green", activebackground="green")
|
||||
|
||||
|
||||
def NEClick(self):
|
||||
self.toggleButton("NE")
|
||||
return
|
||||
|
||||
def SEClick(self):
|
||||
self.toggleButton("SE")
|
||||
return
|
||||
|
||||
def SWClick(self):
|
||||
self.toggleButton("SW")
|
||||
return
|
||||
|
||||
def NWClick(self):
|
||||
self.toggleButton("NW")
|
||||
return
|
||||
|
||||
def makeLabel(self, frame):
|
||||
|
||||
label = Tkinter.Label(frame, fg="red", font=self._boldFont,
|
||||
text="Max winds will be reduced by\n 20% in selected quadrants")
|
||||
label.grid(row=0)
|
||||
|
||||
return
|
||||
|
||||
def makeBottomButtons(self, frame):
|
||||
# Create the Execute/Cancel buttons
|
||||
self._doneButton = Tkinter.Button(frame, text="Done",
|
||||
command=self.doneCommand)
|
||||
self._doneButton.grid(row=3, column=0, padx=20, pady=5, sticky=Tkinter.W)
|
||||
|
||||
self._cancelButton = Tkinter.Button(frame, text="Cancel",
|
||||
command=self.cancelCommand)
|
||||
self._cancelButton.grid(row=3, column=2, padx=20, pady=5, sticky=Tkinter.E)
|
||||
|
||||
frame.grid(columnspan=3, sticky=Tkinter.EW)
|
||||
|
||||
return
|
||||
|
||||
def makeQuadButtons(self, frame):
|
||||
# Create the quadrant buttons
|
||||
commandList = [self.NWClick, self.SWClick, self.SEClick, self.NEClick]
|
||||
self._buttonLabels = ["NW", "SW", "SE", "NE"]
|
||||
|
||||
# define the button position in geometric order
|
||||
buttonPos = [(0, 0), (1, 0), (1, 1), (0, 1)]
|
||||
for b in range(len(self._buttonLabels)):
|
||||
label = self._buttonLabels[b]
|
||||
|
||||
self._buttonList[b] = Tkinter.Button(frame, text=label,
|
||||
command=commandList[b],
|
||||
font=self._bigFont, width=3)
|
||||
rowPos, colPos = buttonPos[b]
|
||||
self._buttonList[b].grid(row=rowPos, column=colPos, padx=30, pady=10)
|
||||
|
||||
return
|
||||
|
||||
def setUpUI(self):
|
||||
|
||||
self._labelFrame = Tkinter.Frame(self._master)
|
||||
|
||||
self._labelFrame.grid(row=0)
|
||||
|
||||
|
||||
self._buttonFrame = Tkinter.Frame(self._master, borderwidth=3,
|
||||
relief=Tkinter.RIDGE, bd=2, pady=5)
|
||||
self._buttonFrame.grid(row=1, column=0,padx=25,
|
||||
sticky=Tkinter.E+Tkinter.W, pady=5)
|
||||
|
||||
|
||||
self._bottomFrame = Tkinter.Frame(self._master, borderwidth=3,
|
||||
relief=Tkinter.RIDGE, bd=2)
|
||||
self._bottomFrame.grid(row=2, column=0, columnspan=2, padx=25)
|
||||
|
||||
self._master.title("Reduce Max Wind by Quadrant")
|
||||
|
||||
self.makeLabel(self._labelFrame)
|
||||
|
||||
self.makeQuadButtons(self._buttonFrame)
|
||||
|
||||
self.makeBottomButtons(self._bottomFrame)
|
||||
|
||||
return
|
||||
|
||||
def doneCommand(self):
|
||||
self._master.quit()
|
||||
|
||||
quadCount = 4
|
||||
reducePct = 0.80
|
||||
|
||||
# Gather up the maxWind info to return to the main tool
|
||||
self._maxWindDict = {}
|
||||
for h in range(len(self._hourList)):
|
||||
windList = []
|
||||
for quad in range(quadCount):
|
||||
|
||||
# Reduce the value if that quadrant was selected
|
||||
if self._buttonState[quad]:
|
||||
windValue = self._maxWind[quad][h] * self._allTimeMaxWind * reducePct
|
||||
else:
|
||||
windValue = self._maxWind[quad][h] * self._allTimeMaxWind
|
||||
|
||||
windList.append(windValue)
|
||||
|
||||
windList.reverse()
|
||||
self._maxWindDict[self._hourList[h]] = windList
|
||||
|
||||
return
|
||||
|
||||
def cancelCommand(self):
|
||||
self._master.destroy()
|
||||
|
||||
return None
|
||||
|
||||
def displayGUI(self, windDict):
|
||||
|
||||
self._windDict = windDict
|
||||
self._maxWindDict = None
|
||||
self._quadCount = 4
|
||||
|
||||
hourKeys = self._windDict.keys()
|
||||
hourKeys.sort()
|
||||
self._hourList = hourKeys
|
||||
self._initialMinWind = []
|
||||
self._initialMaxWind = []
|
||||
for hour in hourKeys:
|
||||
minWind, maxWind = windDict[hour]
|
||||
self._initialMinWind.append(minWind)
|
||||
self._initialMaxWind.append(maxWind)
|
||||
|
||||
self._hourCount = len(hourKeys)
|
||||
|
||||
if AWIPS_ENVIRON == "AWIPS1":
|
||||
self._allTimeMaxWind = max(self._initialMaxWind)
|
||||
else: # numpy uses "amax"
|
||||
self._allTimeMaxWind = amax(self._initialMaxWind)
|
||||
|
||||
|
||||
|
||||
# Make the topLevel window - different for A1 and A2
|
||||
if AWIPS_ENVIRON == 'AWIPS1':
|
||||
self._master = Tkinter.Toplevel(self.eaMgr().root())
|
||||
self._master.transient(self.eaMgr().root()) # always draw on top of GFE
|
||||
else:
|
||||
self._tkmaster = Tkinter.Tk()
|
||||
self._master = Tkinter.Toplevel(self._tkmaster)
|
||||
self._tkmaster.withdraw()
|
||||
|
||||
self._buttonLabels = ["NW", "SW", "SE", "NE"]
|
||||
|
||||
self._buttonState = [False, False, False, False]
|
||||
self._buttonList = [None, None, None, None]
|
||||
|
||||
self._boldFont = tkFont.Font(family="Helvetica", size=12, weight="bold")
|
||||
self._bigFont = tkFont.Font(family="Helvetica", size=16)
|
||||
|
||||
self.setUpUI()
|
||||
|
||||
self._maxWind = zeros((self._quadCount, self._hourCount)) * 1.0
|
||||
|
||||
for hour in range(len(hourKeys)):
|
||||
for quad in range(self._quadCount):
|
||||
minWind, maxWind = self._windDict[hourKeys[hour]]
|
||||
self._maxWind[quad][hour] = maxWind / self._allTimeMaxWind
|
||||
|
||||
|
||||
#self.updateDisplay() # Draws everything
|
||||
|
||||
|
||||
self._master.mainloop()
|
||||
|
||||
self._master.withdraw()
|
||||
self._master.destroy()
|
||||
|
||||
return self._maxWindDict
|
|
@ -5,6 +5,7 @@
|
|||
# TCV_Dictionary
|
||||
# TCV_Dictionary file
|
||||
# Author: GFE Installation Script
|
||||
# Last Modified: Feb 13, 2015
|
||||
# ----------------------------------------------------------------------------
|
||||
# Needed to prevent an error from the SmartTool module
|
||||
WeatherElementEdited = None
|
||||
|
@ -13,83 +14,83 @@ ThreatStatements = {
|
|||
"Wind": {
|
||||
"Extreme": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3, 4, or 5 intensity.",
|
||||
"planning": "Emergency planning should include a reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3 intensity or higher.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic wind impacts. Efforts should now be underway to secure all properties.",
|
||||
"action": "Life threatening wind is possible. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering.",
|
||||
"action": "Extremely Dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Adjustments to emergency plans should include a reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3, 4, or 5 intensity.",
|
||||
"planning": "Emergency plans should include a reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3 intensity or higher.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic wind impacts. Remaining efforts to secure properties should now be brought to completion.",
|
||||
"action": "Life threatening wind is possible. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering. Move to safe shelter before the wind becomes hazardous.",
|
||||
"action": "Extremely dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering. Move to safe shelter before the wind becomes hazardous.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Brace against the reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3, 4, or 5 intensity. Maintain readiness for emergency response.",
|
||||
"preparation": "To be safe, last minute efforts should fully focus on protecting life. Efforts to secure properties against devastating to catastrophic wind impacts should now be complete.",
|
||||
"action": "Life threatening wind is imminent or ongoing. Now is the time to urgently hide from the wind. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering. Remain sheltered until the hazardous wind subsides. Be ready to quickly move to the safest place within your shelter if extreme wind warnings are issued.",
|
||||
"planning": "Remain braced against the reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3 intensity or higher.",
|
||||
"preparation": "To be safe, efforts should fully focus on protecting life. Properties remain subject to devastating to catastrophic wind impacts.",
|
||||
"action": "Now is the time to urgently hide from the wind. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering. Remain sheltered until the hazardous wind subsides. Be ready to quickly move to the safest place within your shelter if extreme wind warnings are issued.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat of hazardous wind has subsided.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injuries or loss of life.",
|
||||
"planning": "The threat for hazardous wind has subsided.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injury or loss of life. If you have a life-threatening emergency dial 9 1 1.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3 or higher.",
|
||||
"preparation": "Be safe and aggressively protect against the potential of devastating to catastrophic wind impacts.",
|
||||
"action": "Extremely dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering.",
|
||||
},
|
||||
},
|
||||
"High": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for hurricane force wind of 74 to 110 MPH of equivalent Category 1 or 2 intensity.",
|
||||
"planning": "Emergency planning should include a reasonable threat for hurricane force wind of 74 to 110 MPH of equivalent Category 1 to 2 intensity.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive wind impacts. Efforts should now be underway to secure all properties.",
|
||||
"action": "Life threatening wind is possible. Failure to adequately shelter may result in serious injury or loss of life.",
|
||||
"action": "Dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury or loss of life.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Adjustments to emergency plans should include a reasonable threat for hurricane force wind of 74 to 110 MPH of equivalent Category 1 or 2 intensity.",
|
||||
"planning": "Emergency plans should include a reasonable threat for hurricane force wind of 74 to 110 MPH of equivalent Category 1 to 2 intensity.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive wind impacts. Remaining efforts to secure properties should now be brought to completion.",
|
||||
"action": "Life threatening wind is possible. Failure to adequately shelter may result in serious injury or loss of life. Move to safe shelter before the wind becomes hazardous.",
|
||||
"action": "Dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury or loss of life. Move to safe shelter before the wind becomes hazardous.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Brace against the reasonable threat for hurricane force wind of 74 to 110 MPH of equivalent Category 1 or 2 intensity.",
|
||||
"preparation": "To be safe, last minute efforts should fully focus on protecting life. Efforts to secure properties against extensive wind impacts should now be complete.",
|
||||
"action": "Life threatening wind is imminent or ongoing. Now is the time to urgently hide from the wind. Failure to adequately shelter may result in serious injury or loss of life. Remain sheltered until the hazardous wind subsides.",
|
||||
"planning": "Remain braced against the reasonable threat for hurricane force wind of 74 to 110 MPH of equivalent Category 1 to 2 intensity.",
|
||||
"preparation": "To be safe, efforts should fully focus on protecting life. Properties remain subject to extensive wind impacts.",
|
||||
"action": "Now is the time to urgently hide from the wind. Failure to adequately shelter may result in serious injury or loss of life. Remain sheltered until the hazardous wind subsides.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat for hazardous wind has subsided.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injuries or loss of life.",
|
||||
"planning": "The threat for hazardous wind has subsided.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injury or loss of life. If you have a life-threatening emergency dial 9 1 1." ,
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for hurricane force wind of 74 to 110 MPH of equivalent Category 1 to 2 intensity.",
|
||||
"preparation": "Be safe and aggressively protect against for the potential of extensive wind impacts.",
|
||||
"action": "Dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury or loss of life.",
|
||||
},
|
||||
},
|
||||
"Mod": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for strong tropical storm force wind of 58 to 73 MPH.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant wind impacts. Efforts should now be underway to secure all properties.",
|
||||
"action": "Failure to adequately shelter may result in serious injury, or in some cases loss of life.",
|
||||
"action": "Dangerous wind is possible. Failure to adequately shelter may result in serious injury, or in some cases loss of life.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Adjustments to emergency plans should include a reasonable threat for strong tropical storm force wind of 58 to 73 MPH.",
|
||||
"planning": "Emergency plans should include a reasonable threat for strong tropical storm force wind of 58 to 73 MPH.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant wind impacts. Remaining efforts to secure properties should now be brought to completion.",
|
||||
"action": "Dangerous wind is possible. Failure to adequately shelter may result in serious injury, or in some cases loss of life. Move to safe shelter before the wind becomes hazardous.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Brace against the reasonable threat for strong tropical storm force wind of 58 to 73 MPH.",
|
||||
"preparation": "To be safe, last minute efforts should fully focus on protecting life. Efforts to secure properties against significant wind impacts should now be complete.",
|
||||
"action": "Dangerous wind is imminent or ongoing. Now is the time to hide from the wind. Failure to adequately shelter may result in serious injury, or in some cases loss of life. Remain sheltered until the hazardous wind subsides.",
|
||||
"planning": "Remain braced against the reasonable threat for strong tropical storm force wind of 58 to 73 MPH.",
|
||||
"preparation": "To be safe, efforts should fully focus on protecting life. Properties remain subject to significant wind impacts.",
|
||||
"action": "Now is the time to hide from the wind. Failure to adequately shelter may result in serious injury, or in some cases loss of life. Remain sheltered until the hazardous wind subsides.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat for hazardous wind has subsided.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injuries, or in some cases loss of life.",
|
||||
"planning": "The threat for hazardous wind has subsided.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injury, or in some cases loss of life. If you have a life-threatening emergency dial 9 1 1.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for strong tropical storm force wind of 58 to 73 MPH.",
|
||||
"preparation": "Be safe and earnestly protect against the potential of significant wind impacts.",
|
||||
"action": "Dangerous wind is possible. Failure to adequately shelter may result in serious injury, or in some cases loss of life.",
|
||||
},
|
||||
},
|
||||
"Elevated": {
|
||||
|
@ -99,49 +100,49 @@ ThreatStatements = {
|
|||
"action": "Hazardous wind is possible. Failure to adequately shelter may result in serious injury.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Adjustments to emergency plans should include a reasonable threat for tropical storm force wind of 39 to 57 MPH.",
|
||||
"planning": "Emergency plans should include a reasonable threat for tropical storm force wind of 39 to 57 MPH.",
|
||||
"preparation": "To be safe, prepare for the potential of limited wind impacts. Remaining efforts to secure properties should now be brought to completion.",
|
||||
"action": "Hazardous wind is possible. Failure to adequately shelter may result in serious injury. Move to safe shelter before the wind becomes hazardous.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Brace against the reasonable threat for tropical storm force wind of 39 to 57 MPH. Maintain a readiness for emergency response.",
|
||||
"preparation": "To be safe, last minute efforts should fully focus on avoiding injury. Efforts to secure properties against limited wind impacts should now be complete.",
|
||||
"action": "Hazardous wind is imminent or ongoing. Now is the time to hide from the wind. Failure to adequately shelter may result in serious injury. Remain sheltered until the hazardous wind subsides.",
|
||||
"planning": "Remain braced against the reasonable threat for tropical storm force wind of 39 to 57 MPH.",
|
||||
"preparation": "To be safe, efforts should fully focus on avoiding injury. Properties remain subject to limited wind impacts.",
|
||||
"action": "Now is the time to hide from the wind. Failure to adequately shelter may result in serious injury. Remain sheltered until the hazardous wind subsides.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat for hazardous wind has subsided.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injuries.",
|
||||
"planning": "The threat for hazardous wind has subsided.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Stay out of restricted areas.",
|
||||
"action": "Failure to exercise due safety may result in additional injury. If you have a life-threatening emergency dial 9 1 1.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for tropical storm force wind of 39 to 57 MPH.",
|
||||
"preparation": "Be safe and protect against the potential of limited wind impacts.",
|
||||
"action": "Hazardous wind is possible. Failure to adequately shelter may result in serious injury.",
|
||||
},
|
||||
},
|
||||
"None": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning for this event need not include a threat for tropical storm force wind. The wind will remain less than 39 MPH, but conditions may still be breezy to windy.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical wind.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical wind event.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical winds at this time.",
|
||||
"action": "Ensure readiness for the next tropical wind event.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning for this event need not include a threat for tropical storm force wind. The wind will remain less than 39 MPH, but conditions may still be breezy to windy.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical wind.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical wind event.",
|
||||
"planning": "Emergency plans for this event need not include a threat for tropical storm force wind. The wind will remain less than 39 MPH, but conditions may still be breezy to windy.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical winds at this time.",
|
||||
"action": "Ensure readiness for the next tropical wind event.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "The wind will remain less than 39 MPH, but conditions may still be breezy to windy.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical wind.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical wind event.",
|
||||
"planning": "Emergency considerations need not include a threat for tropical storm force wind. The wind will remain less than 39 MPH, but conditions may still be breezy to windy.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical winds at this time.",
|
||||
"action": "Ensure readiness for the next tropical wind event.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Conditions may be still breezy to windy.",
|
||||
"planning": "Conditions may still be breezy to windy.",
|
||||
"preparation": "Exercise due safety when moving about.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical wind event.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "Conditions may be breezy to windy.",
|
||||
"default": {
|
||||
"planning": "Conditions may still be breezy to windy.",
|
||||
"preparation": "Exercise due safety when moving about.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical wind event.",
|
||||
},
|
||||
|
@ -152,134 +153,134 @@ ThreatStatements = {
|
|||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for extreme storm surge flooding greater than 9 feet above ground.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic storm surge flooding impacts. Evacuation efforts should now be underway.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury, significant loss of life, or immense human suffering. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury, significant loss of life, or immense human suffering. Leave immediately if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Adjustments to emergency plans should include a reasonable threat for extreme storm surge flooding greater than 9 feet above ground.",
|
||||
"planning": "Emergency plans should include a reasonable threat for extreme storm surge flooding greater than 9 feet above ground.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic storm surge flooding impacts. Evacuation efforts should now be brought to completion. Evacuations must be complete before driving conditions become unsafe.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury, significant loss of life, or immense human suffering. Leave immediately if evacuation orders have been given for your area. Consider voluntary evacuation if recommended. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury, significant loss of life, or immense human suffering. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency response should posture for a reasonable threat for extreme storm surge flooding greater than 9 feet above ground.",
|
||||
"preparation": "To be safe, evacuees should now be located within prescribed shelters and well away from deadly storm surge flooding capable of devastating to catastrophic impacts.",
|
||||
"action": "Life threatening inundation is imminent or ongoing. Failure to have heeded evacuation orders may result in serious injury, significant loss of life, or immense human suffering.",
|
||||
"planning": "Emergency considerations should posture for a reasonable threat for extreme storm surge flooding greater than 9 feet above ground.",
|
||||
"preparation": "To be safe, evacuees should be located within prescribed shelters and well away from deadly storm surge flooding capable of devastating to catastrophic impacts.",
|
||||
"action": "Life threatening inundation is possible. Those who failed to heed evacuation orders risk serious injury, significant loss of life, or immense human suffering.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat of deadly storm surge is abating as flood waters recede.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Do not return to evacuated areas until flood waters completely recede and the all-clear is officially given.",
|
||||
"action": "Failure to exercise due safety may result in additional injuries or loss of life.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Do not return to evacuated areas until flood waters completely recede and the all-clear is officially given.",
|
||||
"action": "Failure to exercise due safety may result in additional injury or loss of life. If you have a life-threatening emergency dial 9 1 1.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for extreme storm surge flooding greater than 9 feet above ground.",
|
||||
"preparation": "Be safe and aggressively guard against the potential of devastating to catastrophic storm surge flooding impacts.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed official instructions may result in serious injury, significant loss of life, or immense human suffering. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
},
|
||||
},
|
||||
"High": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for major storm surge flooding of 6 to 9 feet above ground.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive storm surge flooding impacts. Evacuate efforts should now be underway.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury, significant loss of life, or human suffering. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive storm surge flooding impacts. Evacuation efforts should now be underway.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury, significant loss of life, or human suffering. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Adjustments to emergency plans should include a reasonable threat for major storm surge flooding of 6 to 9 feet above ground.",
|
||||
"planning": "Emergency plans should include a reasonable threat for major storm surge flooding of 6 to 9 feet above ground.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive storm surge flooding impacts. Evacuation efforts should now be brought to completion. Evacuations must be complete before driving conditions become unsafe.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury, significant loss of life, or human suffering. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency response should posture for a reasonable threat for major storm surge flooding of 6 to 9 feet above ground.",
|
||||
"preparation": "To be safe, evacuees should now be located within prescribed shelters and well away from deadly storm surge flooding capable of extensive impacts.",
|
||||
"action": "Life threatening inundation is imminent or ongoing. Failure to have heeded evacuation orders may result in serious injury, significant loss of life, or human suffering.",
|
||||
"planning": "Emergency considerations should posture for a reasonable threat for major storm surge flooding of 6 to 9 feet above ground.",
|
||||
"preparation": "To be safe, evacuees should be located within prescribed shelters and well away from deadly storm surge flooding capable of extensive impacts.",
|
||||
"action": "Life threatening inundation is possible. Those who failed to heed evacuation orders risk serious injury, significant loss of life, or human suffering.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat of deadly storm surge is abating as flood waters recede.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Do not return to evacuated areas until flood waters completely recede and the all-clear is officially given.",
|
||||
"action": "Failure to exercise due safety may result in additional injuries or loss of life.",
|
||||
"planning": "The threat of deadly storm surge is abating as flood waters recede.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Do not return to evacuated areas until flood waters completely recede and the all-clear is officially given.",
|
||||
"action": "Failure to exercise due safety may result in additional injury or loss of life. If you have a life-threatening emergency dial 9 1 1.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for major storm surge flooding of 6 to 9 feet above ground.",
|
||||
"preparation": "Be safe and aggressively guard against the potential of extensive storm surge flooding impacts.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed official instructions may result in serious injury, significant loss of life, or human suffering. Poor decisions may result in being cut off or needlessly risk lives.",
|
||||
},
|
||||
},
|
||||
"Mod": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for dangerous storm surge flooding of 3 to 6 feet above ground.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant storm surge flooding impacts. Evacuation efforts should now be underway.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders or instructions from local officials may result in serious injury or loss of life. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may needlessly risk lives.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury or loss of life. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may needlessly risk lives.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for dangerous storm surge flooding of 3 to 6 feet above ground.",
|
||||
"planning": "Emergency plans should include a reasonable threat for dangerous storm surge flooding of 3 to 6 feet above ground.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant storm surge flooding impacts. Evacuation efforts should now be brought to completion. Evacuations must be complete before driving conditions become unsafe.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders or instructions from local officials may result in serious injury or loss of life. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may needlessly risk lives.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed evacuation orders may result in serious injury or loss of life. Leave if evacuation orders are given for your area. Consider voluntary evacuation if recommended. Poor decisions may needlessly risk lives.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency response should posture for a reasonable threat for dangerous storm surge flooding of 3 to 6 feet above ground.",
|
||||
"preparation": "To be safe, evacuees should now be located within prescribed shelters and well away from storm surge flooding capable of significant impacts.",
|
||||
"action": "Life threatening inundation is imminent or ongoing. Failure to have heeded evacuation orders or instructions from local officials may result in serious injury or loss of life.",
|
||||
"planning": "Emergency considerations should posture for a reasonable threat for dangerous storm surge flooding of 3 to 6 feet above ground.",
|
||||
"preparation": "To be safe, evacuees should be located within prescribed shelters and well away from storm surge flooding capable of significant impacts.",
|
||||
"action": "Life threatening inundation is possible. Those who failed to heed evacuation orders risk serious injury or loss of life.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat of dangerous storm surge is abating as flood waters recede.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Do not return to evacuated areas until flood waters completely recede and the all-clear is officially given.",
|
||||
"action": "Failure to exercise due safety may result in additional injuries or loss of life.",
|
||||
"planning": "The threat of dangerous storm surge is abating as flood waters recede.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Do not return to evacuated areas until flood waters completely recede and the all-clear is officially given.",
|
||||
"action": "Failure to exercise due safety may result in additional injury or loss of life. If you have a life-threatening emergency dial 9 1 1.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for dangerous storm surge flooding of 3 to 6 feet above ground.",
|
||||
"preparation": "Be safe and earnestly guard against the potential of significant storm surge flooding impacts.",
|
||||
"action": "Life threatening inundation is possible. Failure to heed official instructions may result in serious injury or loss of life. Poor decisions may needlessly risk lives.",
|
||||
},
|
||||
},
|
||||
"Elevated": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for peak storm surge flooding of 1 to 3 feet above ground.",
|
||||
"preparation": "To be safe, prepare for the potential of limited storm surge flooding impacts. Preparedness efforts should be underway.",
|
||||
"action": "Localized inundation is possible. Follow the instructions of local officials. Consider voluntary evacuation if recommended. Leave if evacuation orders are issued.",
|
||||
"planning": "Emergency planning should include a reasonable threat for peak storm surge flooding of 1 to 3 feet above ground.",
|
||||
"preparation": "To be safe, prepare for the potential of limited storm surge flooding impacts. Efforts should now be underway.",
|
||||
"action": "Localized inundation is possible. Follow the instructions of local officials. Consider voluntary evacuation if recommended. Leave if evacuation orders are issued.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Adjustments to emergency plans should include a reasonable threat for peak storm surge flooding of 1 to 3 feet above ground.",
|
||||
"preparation": "To be safe, prepare for the potential of limited storm surge flooding impacts. Preparedness efforts should now be brought to completion before conditions deteriorate.",
|
||||
"planning": "Emergency plans should include a reasonable threat for peak storm surge flooding of 1 to 3 feet above ground.",
|
||||
"preparation": "To be safe, prepare for the potential of limited storm surge flooding impacts. Efforts should now be brought to completion before conditions deteriorate.",
|
||||
"action": "Localized inundation is possible. Follow the instructions of local officials. Consider voluntary evacuation if recommended. Leave immediately if evacuation orders are issued.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency response should posture for a reasonable threat for peak storm surge flooding of 1 to 3 feet above ground.",
|
||||
"planning": "Emergency considerations should posture for a reasonable threat for peak storm surge flooding of 1 to 3 feet above ground.",
|
||||
"preparation": "To be safe, stay away from storm surge flooding capable of limited impacts.",
|
||||
"action": "Localized inundation is imminent or ongoing. Continue to follow the instructions of local officials.",
|
||||
"action": "Localized inundation is possible. Continue to follow the instructions of local officials.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "The threat of hazardous storm surge is abating as flood waters recede.",
|
||||
"preparation": "To be safe, heed the instructions of local officials when moving about. Do not return to flooded areas until the all-clear is officially given.",
|
||||
"action": "Exercise due safety.",
|
||||
"planning": "The threat of hazardous storm surge is abating as flood waters recede.",
|
||||
"preparation": "Be safe and heed the instructions of local officials when moving about. Do not enter flooded areas.",
|
||||
"action": "Exercise due safety.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for peak storm surge flooding of 1 to 3 feet above ground.",
|
||||
"preparation": "Be safe and guard against the potential of limited storm surge flooding impacts.",
|
||||
"action": "Localized inundation is possible. Follow the instructions of local officials.",
|
||||
},
|
||||
},
|
||||
"None": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning for this event need not include a threat for storm surge flooding. The ground will remain largely unflooded from surge water or only have spots minimally affected by surge encroachment. Surf conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Little to no preparations needed to guard against storm surge flooding.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next storm surge event.",
|
||||
"planning": "Emergency planning for this event need not include a threat for storm surge flooding. The ground will remain largely unflooded from surge water or only have spots minimally affected by surge water encroachment. Surf conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Little to no preparations needed to guard against storm surge flooding at this time.",
|
||||
"action": "Ensure readiness for the next storm surge event.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning for this event need not include a threat for storm surge flooding. The ground will remain largely unflooded from surge water or only have spots minimally affected by surge encroachment. Surf conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Little to no preparations needed to guard against storm surge flooding.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next storm surge event.",
|
||||
"planning": "Emergency plans for this event need not include a threat for storm surge flooding. The ground will remain largely unflooded from surge water or only have spots minimally affected by surge water encroachment. Surf conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Little to no preparations needed to guard against storm surge flooding at this time.",
|
||||
"action": "Ensure readiness for the next storm surge event.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "The ground will remain largely unflooded from surge water or only have spots minimally affected by surge encroachment. Surg conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Little to no preparations needed to guard against storm surge flooding.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next storm surge event.",
|
||||
"planning": "Emergency considerations for this event need not include a threat for storm surge flooding. The ground will remain largely unflooded from surge water or only have spots minimally affected by surge water encroachment. Surf conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Little to no preparations needed to guard against storm surge flooding at this time.",
|
||||
"action": "Ensure readiness for the next storm surge event.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Surf conditions may be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Exercise due safety.",
|
||||
"planning": "Surf conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Exercise due safety.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next storm surge event.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "Surf conditions may be rough with some beach erosion. Stronger than normal rip currents may also be present. ",
|
||||
"preparation": "Exercise due safety.",
|
||||
"default": {
|
||||
"planning": "Surf conditions may still be rough with some beach erosion. Stronger than normal rip currents may also be present.",
|
||||
"preparation": "Exercise due safety.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next storm surge event.",
|
||||
},
|
||||
},
|
||||
|
@ -287,273 +288,270 @@ ThreatStatements = {
|
|||
"Flooding Rain": {
|
||||
"Extreme": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat of extreme flooding where peak rainfall totals vastly exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are very likely. ",
|
||||
"planning": "Emergency planning should include a reasonable threat of extreme flooding where peak rainfall totals vastly exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are very likely.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury, significant loss of life, or human suffering. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury, significant loss of life, or human suffering. If flood related watches and warnings are issued, heed recommended actions. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground before flood waters arrive.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for extreme flooding where peak rainfall totals vastly exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are very likely.",
|
||||
"planning": "Emergency plans should include a reasonable threat of extreme flooding where peak rainfall totals vastly exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are very likely.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury, significant loss of life, and human suffering. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury, significant loss of life, or human suffering. If flood related watches and warnings are issued, heed recommended actions. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground before flood waters arrive.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency plans should include a reasonable threat for extreme flooding where peak rainfall totals vastly exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are very likely.",
|
||||
"preparation": "To be safe, remain prepared for the potential of devastating to catastrophic flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury, significant loss of life, and human suffering. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. ",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency plans should include a reasonable threat for extreme flooding where peak rainfall totals vastly exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are very likely.",
|
||||
"preparation": "To be safe, remain prepared for the potential of devastating to catastrophic flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury, significant loss of life, and human suffering. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed and do not let down your guard.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Do not drive through existing flood waters that cover the road.",
|
||||
},
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.", },
|
||||
},
|
||||
"High": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for major flooding where peak rainfall totals well exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are likely.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury or significant loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury or significant loss of life. If flood related watches and warnings are issued, heed recommended actions. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground before flood waters arrive.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for major flooding where peak rainfall totals well exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are likely.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive flooding rain impacts. Life threatening flooding possible from excessive tropical rain.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury or significant loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground.",
|
||||
"planning": "Emergency plans should include a reasonable threat for major flooding where peak rainfall totals well exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are likely.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury or significant loss of life. If flood related watches and warnings are issued, heed recommended actions. Poor decisions may result in being cut off or needlessly risk lives. If vulnerable, relocate to safe shelter on higher ground before flood waters arrive.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency plans should include a reasonable threat for major flooding where peak rainfall totals well exceed amounts conducive for flash flooding and rapid inundation.",
|
||||
"preparation": "To be safe, remain prepared for the potential of extensive flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury or significant loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency plans should continue to include a reasonable threat for major flooding where peak rainfall totals well exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are likely.",
|
||||
"preparation": "To be safe, remain prepared for the potential of extensive flooding rain impacts.",
|
||||
"action": "Life threatening flooding is possible. Failure to take action may result in serious injury or significant loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed and do not let down your guard.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Do not drive through existing flood waters that cover the road.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
},
|
||||
},
|
||||
"Mod": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for moderate flooding where peak rainfall totals notably exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are possible.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant flooding rain impacts.",
|
||||
"action": "Dangerous flooding is possible. Failure to take action may result in serious injury or loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
"action": "Dangerous flooding is possible. Failure to take action may result in serious injury or loss of life. If flood related watches and warnings are issued, heed recommended actions.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for moderate flooding where peak rainfall totals notably exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are possible.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant flooding rain impacts.",
|
||||
"action": "Dangerous flooding is possible. Failure to take action may result in serious injury or loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency plans should include a reasonable threat for moderate flooding where peak rainfall totals notably exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are possible.",
|
||||
"preparation": "To be safe, remain prepared for the potential of significant flooding rain impacts.",
|
||||
"action": "Dangerous flooding is possible. Failure to take action may result in serious injury or loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant flooding rain impacts.",
|
||||
"action": "Dangerous flooding is possible. Failure to take action may result in serious injury or loss of life. If flood related watches and warnings are issued, heed recommended actions.", },
|
||||
"hunker down": {
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency plans should include a reasonable threat for moderate flooding where peak rainfall totals notably exceed amounts conducive for flash flooding and rapid inundation. Rescues and emergency evacuations are possible.",
|
||||
"preparation": "To be safe, remain prepared for the potential of significant flooding rain impacts.",
|
||||
"action": "Dangerous flooding is possible. Failure to take action may result in serious injury or loss of life. If flash flood watches and warnings are issued, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed and do not let down your guard.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Do not drive through existing flood waters that cover the road.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
},
|
||||
},
|
||||
"Elevated": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for minor flooding where peak rainfall totals are near amounts conducive for flash flooding and rapid inundation.",
|
||||
"planning": "Emergency planning should include a reasonable threat for minor flooding where peak rainfall totals are near amounts conducive for localized flash flooding and rapid inundation.",
|
||||
"preparation": "To be safe, prepare for the potential of limited flooding rain impacts.",
|
||||
"action": "Localized flooding is possible. If flash flood watches and warnings are issued, heed recommended actions.",
|
||||
"action": "Localized flooding is possible. If flood related watches and warnings are issued, heed recommended actions.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for minor flooding where peak rainfall totals are near amounts conducive for flash flooding and rapid inundation.",
|
||||
"planning": "Emergency plans should include a reasonable threat for minor flooding where peak rainfall totals are near amounts conducive for localized flash flooding and rapid inundation.",
|
||||
"preparation": "To be safe, prepare for the potential of limited flooding rain impacts.",
|
||||
"action": "Localized flooding is possible. If flash flood watches and warnings are issued, heed recommended actions.",
|
||||
"action": "Localized flooding is possible. If flood related watches and warnings are issued, heed recommended actions.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency plans should include a reasonable threat for minor flooding where peak rainfall totals are near amounts conducive for flash flooding and rapid inundation.",
|
||||
"preparation": "To be safe, remain prepared for the potential of limited flooding rain impacts.",
|
||||
"action": "Localized flooding is possible. If flash flood watches and warnings are issued, heed recommended actions.",
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency plans should include a reasonable threat for minor flooding where peak rainfall totals are near amounts conducive for flash flooding and rapid inundation.",
|
||||
"preparation": "To be safe, remain prepared for the potential of limited flooding rain impacts.",
|
||||
"action": "Localized flooding is possible. If flash flood watches and warnings are issued, heed recommended actions.",
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed and do not let down your guard.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers. Do not drive through existing flood waters that cover the road.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a threat of flooding.",
|
||||
"preparation": "Be safe and remain ready to protect against flooding rain impacts. Stay informed.",
|
||||
"action": "If flood related watches and warnings are in effect, heed recommended actions. Also listen for possible river flood warnings for longer-term impacts along rivers.",
|
||||
},
|
||||
},
|
||||
"None": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning for this event need not include a threat for rainfall flooding. Heavy rain and nuisance flooding may still occur.",
|
||||
"planning": "Emergency planning need not include a threat for rainfall flooding. Locally heavy rain and nuisance flooding may still occur.",
|
||||
"preparation": "Little to no preparations needed to guard against excessive tropical rainfall.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical rainfall flooding event.",
|
||||
"action": "Ensure readiness for the next tropical rainfall event.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning for this event need not include a threat for rainfall flooding. Heavy rain and nuisance flooding may still occur.",
|
||||
"planning": "Emergency plans need not include a threat for rainfall flooding. Locally heavy rain and nuisance flooding may still occur.",
|
||||
"preparation": "Little to no preparations needed to guard against excessive tropical rainfall.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical rainfall flooding event.",
|
||||
"action": "Ensure readiness for the next tropical rainfall event.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency planning for this event need not include a threat for rainfall flooding. Heavy rain and nuisance flooding may still occur.",
|
||||
"planning": "Emergency considerations need not include a threat for rainfall flooding. Locally heavy rain and nuisance flooding may still occur.",
|
||||
"preparation": "Little to no preparations needed to guard against excessive tropical rainfall.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical rainfall flooding event.",
|
||||
"action": "Ensure readiness for the next tropical rainfall event.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Heavy rain and nuisance flooding may still occur. ",
|
||||
"planning": "Locally heavy rain and nuisance flooding may still occur.",
|
||||
"preparation": "Exercise due safety.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical rainfall flooding event.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical rainfall event.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "Heavy rain and nuisance flooding may still occur.",
|
||||
"default": {
|
||||
"planning": "Locally Heavy rain and nuisance flooding may still occur.",
|
||||
"preparation": "Exercise due safety.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical rainfall flooding event.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical rainfall event.",
|
||||
},
|
||||
},
|
||||
},
|
||||
"Tornado": {
|
||||
"Extreme": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for an outbreak of tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths. Numerous tornadoes may occur within short periods of time and in close proximity of one another.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic tornado impacts. Those living in mobile homes should relocate to more substantial shelter. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
"planning": "Emergency planning should include a reasonable threat for an outbreak of tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths. Numerous tornadoes may occur within short periods of time and in close proximity of one another.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic tornado impacts. Those living in mobile homes should relocate to more substantial shelter before severe weather arrives.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for an outbreak of tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths. Numerous tornadoes may occur within short periods of time and in close proximity of one another.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic tornado impacts. Those living in mobile homes should relocate to more substantial shelter. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
"planning": "When implementing emergency plans, include a reasonable threat for an outbreak of tornadoes." ,
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic tornado impacts. Those living in mobile homes should relocate to more substantial shelter before severe weather arrives.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency plans should include a reasonable threat for an outbreak of tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths. Numerous tornadoes may occur within short periods of time and in close proximity of one another.",
|
||||
"preparation": "To be safe, remain prepared for the potential of devastating to catastrophic tornado impacts. Stay informed and listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. If tornado warnings are issued for your area, quickly move to the safest place within your shelter. Seconds can save lives.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. If a tornado approaches, quickly move to the safest place within your shelter.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency plans should continue to include a reasonable threat for an outbreak of tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths. Numerous tornadoes may occur within short periods of time and in close proximity of one another.",
|
||||
"preparation": "To be safe, remain prepared for the potential of devastating to catastrophic tornado impacts. Stay informed and do not let down your guard/",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. If tornado watches and warnings are issued, heed recommended actions.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed and do not let down your guard.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for an outbreak of tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against the potential of devastating to catastrophic tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
},
|
||||
"High": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for numerous tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive tornado impacts. Those living in mobile homes should relocate to more substantial shelter. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive tornado impacts. Those living in mobile homes should relocate to more substantial shelter before severe weather arrives.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for numerous tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive tornado impacts. Those living in mobile homes should relocate to more substantial shelter. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
"planning": "When implementing emergency plans, include a reasonable threat for numerous tornadoes.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of extensive tornado impacts. Those living in mobile homes should relocate to more substantial shelter before severe weather arrives.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency plans should include a reasonable threat for numerous tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths.",
|
||||
"preparation": "To be safe, remain prepared for the potential of extensive tornado impacts. Stay informed and listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. If tornado warnings are issued for your area, quickly move to the safest place within your shelter. Seconds can save lives.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. If a tornado approaches, quickly move to the safest place within your shelter.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency plans should include a reasonable threat for numerous tornadoes, with several possibly strong or violent in intensity and with longer and wider damage paths.",
|
||||
"preparation": "To be safe, remain prepared for the potential of extensive tornado impacts. Stay informed and do not let down your guard.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or significant loss of life. If tornado watches and warnings are issued, heed recommended actions.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed and do not let down your guard.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for numerous tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against the potential of extensive tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
},
|
||||
"Mod": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for scattered tornadoes, with a few possibly strong in intensity.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant tornado impacts. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant tornado impacts.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for scattered tornadoes, with a few possibly strong in intensity.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant tornado impacts. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
},
|
||||
"planning": "When implementing emergency plans, include should include a reasonable threat for scattered tornadoes.",
|
||||
"preparation": "To be safe, earnestly prepare for the potential of significant tornado impacts.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.", },
|
||||
"hunker down": {
|
||||
"planning": "Emergency planning should continue to include a reasonable threat for scattered tornadoes, with a few possibly strong in intensity.",
|
||||
"preparation": "To be safe, remain prepared for the potential of significant tornado impacts. Stay informed and listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or loss of life. If tornado warnings are issued for your area, quickly move to the safest place within your shelter. Seconds can save lives.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. If a tornado approaches, quickly move to the safest place within your shelter.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency planning should include a reasonable threat for scattered tornadoes, with a few possibly strong in intensity.",
|
||||
"preparation": "To be safe, remain prepared prepare for the potential of significant tornado impacts. Stay informed and do not let down your guard.",
|
||||
"action": "Failure to adequately shelter may result in serious injury or loss of life. If tornado watches and warnings are issued for your area, heed recommended actions.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed and do not let down your guard.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for scattered tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against the potential of significant tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
},
|
||||
"Elevated": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for isolated tornadoes, mostly with shorter and narrower damage paths.",
|
||||
"preparation": "To be safe, prepare for the potential of limited tornado impacts. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury, and in some cases loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
"planning": "Emergency planning should include a reasonable threat for isolated tornadoes, mostly with shorter and narrower damage paths.",
|
||||
"preparation": "To be safe, prepare for the potential of limited tornado impacts.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning should include a reasonable threat for isolated tornadoes, mostly with shorter and narrower damage paths.",
|
||||
"preparation": "To be safe, prepare for the potential of limited tornado impacts. Listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury, and in some cases loss of life. Keep a watchful eye to the sky and a listening ear for warning alerts. Be ready to find shelter quickly.",
|
||||
"planning": "When implementing emergency plans, include a reasonable threat for isolated tornadoes.",
|
||||
"preparation": "To be safe, prepare for the potential of limited tornado impacts.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency planning should include a reasonable threat for isolated tornadoes, mostly with shorter and narrower damage paths.",
|
||||
"preparation": "To be safe, remain prepared for the potential of limited tornado impacts. Stay informed and listen for tornado watches and warnings.",
|
||||
"action": "Failure to adequately shelter may result in serious injury, and in some cases loss of life. If tornado warnings are issued for your area, quickly move to the safest place within your shelter. Seconds can save lives.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. If a tornado approaches, quickly move to the safest place within your shelter.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Emergency planning should continue to include a reasonable threat for isolated tornadoes, mostly with shorter and narrower damage paths.",
|
||||
"preparation": "To be safe, remain prepared for the potential of limited tornado impacts. Stay informed and do not let down your guard.",
|
||||
"action": "Failure to adequately shelter may result in serious injury, and in some cases loss of life. If tornado watches and warnings are issued for your area, heed recommended actions.",
|
||||
"planning": "Emergency considerations should include a reasonable threat for tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against tornado impacts. Stay informed and do not let down your guard.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "",
|
||||
"preparation": "",
|
||||
"action": "",
|
||||
"default": {
|
||||
"planning": "Emergency considerations should include a reasonable threat for isolated tornadoes.",
|
||||
"preparation": "Be safe and remain ready to protect against the potential of limited tornado impacts. Stay informed.",
|
||||
"action": "Listen for tornado watches and warnings. Be ready to shelter quickly if a tornado approaches.",
|
||||
},
|
||||
},
|
||||
"None": {
|
||||
"check plans": {
|
||||
"planning": "Emergency planning for this event need not include a threat for tornadoes. Showers and thunderstorms with strong wind gusts may still occur.",
|
||||
"planning": "Emergency planning need not include a threat for tornadoes. Showers and thunderstorms with strong gusty winds may still occur.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical tornadoes.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical tornado event.",
|
||||
"action": "Ensure readiness for the next tropical tornado event.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency planning for this event need not include a threat for tornadoes. Showers and thunderstorms with strong wind gusts may still occur.",
|
||||
"planning": "Emergency plans need not include a threat for tornadoes. Showers and thunderstorms with strong gusty winds may still occur.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical tornadoes.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical tornado event.",
|
||||
"action": "Ensure readiness for the next tropical tornado event.",
|
||||
},
|
||||
"hunker down": {
|
||||
"planning": "Emergency plans for this event need not include a threat for tornadoes. Showers and thunderstorms with strong wind gusts may still occur.",
|
||||
"planning": "Emergency considerations need not include a threat for tornadoes. Showers and thunderstorms with strong gusty winds may still occur.",
|
||||
"preparation": "Little to no preparations needed to guard against tropical tornadoes.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical tornado event.",
|
||||
"action": "Ensure readiness for the next tropical tornado event.",
|
||||
},
|
||||
"recovery": {
|
||||
"planning": "Showers and thunderstorms with strong wind gusts may still occur.",
|
||||
"preparation": "Exercise due safety when moving about.",
|
||||
"planning": "Showers and thunderstorms with strong gusty winds may still occur.",
|
||||
"preparation": "Exercise due safety.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical tornado event.",
|
||||
},
|
||||
"nothing to see here": {
|
||||
"planning": "Showers and thunderstorms with strong wind gusts may occur.",
|
||||
"preparation": "Exercise due safety when moving about.",
|
||||
"default": {
|
||||
"planning": "Showers and thunderstorms with strong gusty winds may still occur.",
|
||||
"preparation": "Exercise due safety.",
|
||||
"action": "Review your seasonal plan and ensure readiness for the next tropical tornado event.",
|
||||
},
|
||||
},
|
||||
|
@ -561,21 +559,21 @@ ThreatStatements = {
|
|||
}
|
||||
PotentialImpactStatements = {
|
||||
"Wind": {
|
||||
"Extreme": ["Structural damage to sturdy buildings with some experiencing complete roof and wall failures. Complete destruction of mobile homes. Damage greatly accentuated by large airborne projectiles. Locations may be uninhabitable for weeks or months.",
|
||||
"Extreme": ["Structural damage to sturdy buildings, some with complete roof and wall failures. Complete destruction of mobile homes. Damage greatly accentuated by large airborne projectiles. Locations may be uninhabitable for weeks or months.",
|
||||
"Numerous large trees snapped or uprooted along with fences and roadway signs blown over.",
|
||||
"Many roads impassible from large debris, and more within urban or heavily wooded places. Many bridges, causeways, and access routes impassible.",
|
||||
"Many roads impassable from large debris, and more within urban or heavily wooded places. Many bridges, causeways, and access routes impassable.",
|
||||
"Widespread power and communications outages."],
|
||||
"High": ["Considerable roof damage to sturdy buildings, with some having window, door, and garage door failures leading to structural damage. Mobile homes severely damaged, with some destroyed. Damage accentuated by airborne projectiles. Locations may be uninhabitable for weeks.",
|
||||
"High": ["Considerable roof damage to sturdy buildings, with some having window, door, and garage door failures leading to structural damage. Mobile homes severely damaged, with some destroyed. Damage accentuated by airborne projectiles. Locations may be uninhabitable for weeks.",
|
||||
"Many large trees snapped or uprooted along with fences and roadway signs blown over.",
|
||||
"Some roads impassible from large debris, and more within urban or heavily wooded places. Several bridges, causeways, and access routes impassible.",
|
||||
"Some roads impassable from large debris, and more within urban or heavily wooded places. Several bridges, causeways, and access routes impassable.",
|
||||
"Large areas with power and communications outages."],
|
||||
"Mod": ["Some damage to roofing and siding materials, along with damage to porches, awnings, carports, and sheds. A few buildings experiencing window, door, and garage door failures. Mobile homes damaged, especially if unanchored. Unsecured lightweight objects become dangerous projectiles.",
|
||||
"Several large trees snapped or uprooted, but with greater numbers in places where trees are shallow rooted. Several fences and roadway signs blown over.",
|
||||
"Some roads impassible from large debris, and more within urban or heavily wooded places. A few bridges, causeways, and access routes impassible.",
|
||||
"Some roads impassable from large debris, and more within urban or heavily wooded places. A few bridges, causeways, and access routes impassable.",
|
||||
"Scattered power and communications outages, but more prevalent in areas with above ground lines."],
|
||||
"Elevated": ["Damage to porches, awnings, carports, sheds, and unanchored mobile homes. Unsecured lightweight objects blown about.",
|
||||
"Many large tree limbs broken off. A few trees snapped or uprooted, but with greater numbers in places where trees are shallow rooted. Some fences and roadway signs blown over.",
|
||||
"A few roads impassible from debris, particularly within urban or heavily wooded places. Hazardous driving conditions on bridges and other elevated roadways.",
|
||||
"A few roads impassable from debris, particularly within urban or heavily wooded places. Hazardous driving conditions on bridges and other elevated roadways.",
|
||||
"Scattered power and communications outages."],
|
||||
"None": ["Little to no potential impacts from wind."],
|
||||
},
|
||||
|
@ -584,7 +582,7 @@ PotentialImpactStatements = {
|
|||
"Near-shore escape routes and secondary roads washed out or severely flooded. Flood control systems and barriers may become stressed.",
|
||||
"Extreme beach erosion. New shoreline cuts possible.",
|
||||
"Massive damage to marinas, docks, boardwalks, and piers. Numerous small craft broken away from moorings with many lifted onshore and stranded."],
|
||||
"High": ["Large areas of deep inundation, with storm surge flooding accentuated by battering waves. Structural damage to buildings, with several washing away. Damage compounded by floating debris. Locations may be uninhabitable for an extended period.",
|
||||
"High": ["Large areas of deep inundation with storm surge flooding accentuated by battering waves. Structural damage to buildings, with several washing away. Damage compounded by floating debris. Locations may be uninhabitable for an extended period.",
|
||||
"Large sections of near-shore escape routes and secondary roads washed out or severely flooded. Flood control systems and barriers may become stressed.",
|
||||
"Severe beach erosion with significant dune loss.",
|
||||
"Major damage to marinas, docks, boardwalks, and piers. Many small craft broken away from moorings, especially in unprotected anchorages with some lifted onshore and stranded."],
|
||||
|
@ -601,20 +599,20 @@ PotentialImpactStatements = {
|
|||
"Flooding Rain": {
|
||||
"Extreme": ["Extreme rainfall flooding may prompt numerous evacuations and rescues.",
|
||||
"Rivers and tributaries may overwhelmingly overflow their banks in many places with deep moving water. Small streams, creeks, canals, arroyos, and ditches may become raging rivers. In mountain areas, deadly runoff may rage down valleys while increasing susceptibility to rockslides and mudslides. Flood control systems and barriers may become stressed.",
|
||||
"Flood waters can enter numerous structures within multiple communities, with some structures becoming uninhabitable or washed away. Numerous places where flood waters may cover escape routes. Streets and parking lots become rivers of raging water with underpasses submerged. Driving conditions become very dangerous. Numerous road and bridge closures with some weakened or washed out."],
|
||||
"Flood waters can enter numerous structures within multiple communities, some structures becoming uninhabitable or washed away. Numerous places where flood waters may cover escape routes. Streets and parking lots become rivers of raging water with underpasses submerged. Driving conditions become very dangerous. Numerous road and bridge closures with some weakened or washed out."],
|
||||
"High": ["Major rainfall flooding may prompt many evacuations and rescues.",
|
||||
"Rivers and tributaries may rapidly overflow their banks in multiple places. Small streams, creeks, canals, arroyos, and ditches may become dangerous rivers. In mountain areas, destructive runoff may run quickly down valleys while increasing susceptibility to rockslides and mudslides. Flood control systems and barriers may become stressed.",
|
||||
"Flood waters can enter many structures within multiple communities, with some structures becoming uninhabitable or washed away. Many places where flood waters may cover escape routes. Streets and parking lots become rivers of moving water with underpasses submerged. Driving conditions become dangerous. Many road and bridge closures with some weakened or washed out."],
|
||||
"Flood waters can enter many structures within multiple communities, some structures becoming uninhabitable or washed away. Many places where flood waters may cover escape routes. Streets and parking lots become rivers of moving water with underpasses submerged. Driving conditions become dangerous. Many road and bridge closures with some weakened or washed out."],
|
||||
"Mod": ["Moderate rainfall flooding may prompt several evacuations and rescues.",
|
||||
"Rivers and tributaries may quickly become swollen with swifter currents and overspill their banks in a few places, especially in usually vulnerable spots. Small streams, creeks, canals, arroyos, and ditches overflow.",
|
||||
"Flood waters can enter some structures or weaken foundations. Several places may experience expanded areas of rapid inundation at underpasses, low-lying spots, and poor drainage areas. Some streets and parking lots take on moving water as storm drains and retention ponds overflow. Driving conditions become hazardous. Some road and bridge closures."],
|
||||
"Elevated": ["Localized rainfall flooding may prompt a few evacuations.",
|
||||
"Rivers and tributaries may quickly rise with swifter currents. Small streams, creeks, canals, arroyos, and ditches may become swollen and overflow in spots.",
|
||||
"Flood waters can enter a few structures, especially in usually vulnerable spots. A few places where rapid ponding of water occurs at underpasses, low-lying spots, and poor drainage areas. Several storm drains and retention ponds may become near-full and begin to overflow. Some brief road and bridge closures."],
|
||||
"Flood waters can enter a few structures, especially in usually vulnerable spots. A few places where rapid ponding of water occurs at underpasses, low-lying spots, and poor drainage areas. Several storm drains and retention ponds become near-full and begin to overflow. Some brief road and bridge closures."],
|
||||
"None": ["Little to no potential impacts from flooding rain."],
|
||||
},
|
||||
"Tornado": {
|
||||
"Extreme": ["The occurrence of an outbreak of tornadoes can greatly hinder the execution of emergency plans during tropical events.",
|
||||
"Extreme": ["The occurrence of an outbreak of tornadoes can greatly hinder the execution of emergency plans during tropical events. ",
|
||||
"Many places may experience tornado damage, with several spots of immense destruction, power loss, and communications failures.",
|
||||
"Locations could realize sturdy buildings demolished, structures upon weak foundations swept away, mobile homes obliterated, large trees twisted and snapped with some debarked, vehicles lifted off the ground and thrown with distance, and small boats destroyed. Large and deadly projectiles can add considerably to the toll."],
|
||||
"High": ["The occurrence of numerous tornadoes can greatly hinder the execution of emergency plans during tropical events.",
|
||||
|
@ -630,9 +628,13 @@ PotentialImpactStatements = {
|
|||
},
|
||||
}
|
||||
|
||||
EvacuationStatements = ["For those under evacuation orders, leave as soon as practical with a destination in mind. Gas up your vehicle well ahead of time. Be sure that you take essential materials from your Emergency Supplies Kit. Let others know where you are going and when you intend to arrive.",
|
||||
"If evacuating the area, stick to prescribed evacuation routes. Look for additional traffic information on roadway smart signs and listen to select radio channels for further travel instructions. Do not use your cell phone while driving."
|
||||
"For those not under evacuation orders, understand that there are inherent risks to evacuation (such as traffic congestion, accidents, and driving in bad weather), so evacuate only if necessary. Help keep roadways open for those that are under evacuation orders."]
|
||||
EvacuationStatements = ["WATCH/WARNING PHASE - For those under evacuation orders, leave as soon as practical with a destination in mind. Gas up your vehicle well ahead of time. Be sure that you take all essential materials from your emergency supplies kit. Let others know where you are going and when you intend to arrive.",
|
||||
"WATCH/WARNING PHASE - If evacuating the area, stick to prescribed evacuation routes. Look for additional traffic information on roadway smart signs and listen to select radio channels for further travel instructions. Drivers should not use cell phones while operating vehicles.",
|
||||
"WATCH/WARNING PHASE - For those not under evacuation orders, understand that there are inherent risks to evacuation (such as traffic congestion, accidents, and driving in bad weather), so evacuate only if necessary. Help keep roadways open for those that are under evacuation orders.",
|
||||
"WATCH/WARNING PHASE - If you are exceptionally vulnerable to wind or water hazards from tropical systems, consider voluntary evacuation, especially if being officially recommended. Relocate to a predetermined shelter or safe destination.",
|
||||
"WATCH/WARNING PHASE - If evacuating away from the area or relocating to a nearby shelter, leave early before weather conditions become hazardous.",
|
||||
"IMMINENT/ONGOING PHASE - Do not return to evacuated areas until hazardous winds diminish and flood waters abate.",
|
||||
"RECOVERY PHASE - Do not return to evacuated areas until it is safe. Listen for the all-clear signal from local authorities."]
|
||||
|
||||
OtherPreparednessActions = {
|
||||
|
||||
|
@ -650,7 +652,7 @@ OtherPreparednessActions = {
|
|||
"Outside preparations should be wrapped up as soon as possible before weather conditions completely deteriorate. Any remaining evacuations and relocations should be expedited before the onset of tropical storm force wind.",
|
||||
"If you are relocating to safe shelter, leave as early as possible. If heading to a community shelter, become familiar with the shelter rules before arrival, especially if you have special needs or own a pet. Take essential items with you from your Emergency Supplies Kit. Check the latest weather forecast before departing.",
|
||||
"Failure to adequately shelter may result in serious injury or loss of life. Always heed the advice of local officials and comply with any orders that are issued. Remember, during the storm 9 1 1 Emergency Services may not be able to immediately respond if conditions are unsafe. This should be a big factor in your decision making.",
|
||||
"Check-in with your Emergency Points of Contact among family, friends, and workmates. Inform them of your status and well-being. Let them know how you intend to ride out the storm and when you plan to check-in again.",
|
||||
"Check-in with your emergency points of contact among family, friends, and workmates. Inform them of your status and well-being. Let them know how you intend to ride out the storm and when you plan to check-in again.",
|
||||
"Keep cell phones well charged and handy. Also, cell phone chargers for automobiles can be helpful after the storm. Locate your chargers and keep them with your cell phone.",
|
||||
"In emergencies it is best to remain calm. Stay informed and focused on the situation at hand. Exercise patience with those you encounter. Be a Good Samaritan and helpful to others.",
|
||||
"If relocating to a nearby shelter or to the home of a family member or friend, drive with extra caution, especially on secondary roads. Remember, many bridges and causeways will be closed once higher winds arrive. Also, if you encounter water covering the road, seek an alternate route. Always obey official road signs for closures and detours.",
|
||||
|
@ -662,20 +664,20 @@ OtherPreparednessActions = {
|
|||
"Do not venture outside while in the eye of a hurricane. Within the eye, weather conditions may temporarily improve which can be misleading. Once the eye passes, the wind will change direction and return to dangerous speeds. Heavy rain will also return. Be smart and remain safely hidden from the storm.",
|
||||
"Do not be a thrill seeker or risk your life for senseless photos or videos. Be wise and avoid becoming another statistic.",
|
||||
"Be ready to move to the identified safe room if your home or shelter begins to fail. Quickly move to an interior room on the lowest floor. Put as many sturdy walls between you and the storm as you can. Protect your head and body.",
|
||||
"When major hurricanes make landfall, extreme winds bring a tremendous threat to life and cause devastating to catastrophic damage. The extent of these extreme winds is usually confined to locations near the coast and does not tend to cover an overly large area. Yet, this area will realize the brunt of the storm. At the onset of landfall, listen for extreme wind warnings. If issued for you area, move to the safest place within your home or shelter. Take the same life-saving actions as if it were a violent tornado."],
|
||||
"When major hurricanes make landfall, extreme winds bring a tremendous threat to life and cause devastating to catastrophic damage. During landfall, listen for extreme wind warnings which indicate the exact timing and location of these incredible life-threatening winds. If issued for you area, move to the safest place within your home or shelter. Take the same life-saving actions as if it were a violent tornado."],
|
||||
"recovery": ["Remain safely sheltered until the storm fully passes. Once conditions improve, be careful going outside. Stay away from downed power lines and hazardous debris.",
|
||||
"If your home or shelter was damaged, be alert to the smell of natural gas leaks and cautious around exposed electrical wiring, broken glass, jagged metal and wood, and protruding nails and screws.",
|
||||
"Check to see if everyone in your group is OK. Administer first aid to those who are injured. Call 9 1 1 for any serious injuries. Remember, it may be more difficult for emergency responders to arrive quickly in the time period immediately following the storm.",
|
||||
"Check-in with your Emergency Points of Contact. Let them know of your status and well-being. Keep conversations short and to the point. Do not tie up communications systems.",
|
||||
"Check-in with your emergency points of contact. Let them know of your status and well-being. Keep conversations short and to the point. Do not tie up communications systems.",
|
||||
"Be a good neighbor and check on those living next to you. Be neighborly and lend a helping hand.",
|
||||
"Those who rode out the storm away from their home or business are likely anxious to return. However, allow some time for work crews to make a clear path for emergency vehicles. Downed power lines and trees may be blocking roads and flood waters may have washed out or overspread sections of key travel routes. Traffic lights may also be out of service.",
|
||||
"Do not attempt to return to evacuated areas until local authorities give the All-Clear signal.",
|
||||
"Do not go sightseeing within impacted communities simply to observe storm damage. Sightseers can interfere with the timeliness of rescuers and first responders while needlessly jeopardizing their own lives and the lives of others.",
|
||||
"Do not go sightseeing within impacted communities simply to observe storm damage. Sightseers can interfere with the timeliness of rescuers and first responders to needlessly jeopardize lives.",
|
||||
"When inspecting damage, use flashlights rather than candles or flamed lighting. Be aware of sparks that can ignite leaking gas or other flammables.",
|
||||
"Do not go up on your roof until the rain and strong winds have subsided. Ladders can be slippery in the rain and unexpected wind gusts can blow you off of the roof. Do not risk bodily harm in an attempt to reduce property damage.",
|
||||
"When clearing out fallen trees, be careful with chain saws and axes. Always wear protective gear and keep others at a safe distance. Use these tools according to operating manuals and safety instruction. Leaning trees and those which have fallen on roof tops can be especially challenging. If you are not in good health or unsure about what you are doing, have someone else with tree cutting experience do the job. Never cut trees without a partner.",
|
||||
"If using a generator, avoid carbon monoxide poisoning by following instructions by the manufacturer. Make sure that the generator is run in a well ventilated space.",
|
||||
"Problems with sewer backups can contaminate standing flood waters. Keep children away. Also, listen for boil water alerts relative to communities whose tap water may have become temporarily non-potable."],
|
||||
"Problems with sewer backups can further contaminate standing flood waters. Keep children away. Also, listen for boil water alerts relative to communities whose tap water may have become non-potable."],
|
||||
}
|
||||
|
||||
AdditionalSources = ["- For information on appropriate preparations see ready.gov",
|
||||
|
|
|
@ -55,6 +55,7 @@ Definition = {
|
|||
|
||||
## General Set-Up
|
||||
|
||||
"fullStationID": "KXXX",
|
||||
"type": "table",
|
||||
"displayName": "${itemName}", # for Product Generation Menu
|
||||
# if displayName == None or "None", this product will NOT
|
||||
|
|
|
@ -53,6 +53,7 @@ import com.raytheon.viz.ui.dialogs.CaveJFACEDialog;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Sept 25, 2008 1562 askripsky Initial creation.
|
||||
* Nov 12, 2012 1298 rferrel Changes for non-blocking dialog.
|
||||
* Mar 17, 2015 17217 ryu Set smart product as the default type.
|
||||
* </pre>
|
||||
*
|
||||
* @author askripsky
|
||||
|
@ -267,13 +268,13 @@ public class NewTextProductDialog extends CaveJFACEDialog {
|
|||
buttonComp.setLayout(new GridLayout());
|
||||
buttonComp.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true));
|
||||
|
||||
tableTypeButton = new Button(buttonComp, SWT.RADIO);
|
||||
tableTypeButton.setText("Table");
|
||||
smartTypeButton = new Button(buttonComp, SWT.RADIO);
|
||||
smartTypeButton.setText("Smart");
|
||||
tableTypeButton = new Button(buttonComp, SWT.RADIO);
|
||||
tableTypeButton.setText("Table");
|
||||
|
||||
// Default to table type
|
||||
tableTypeButton.setSelection(true);
|
||||
// Default to smart type
|
||||
smartTypeButton.setSelection(true);
|
||||
}
|
||||
|
||||
private void initNameSelection() {
|
||||
|
|
|
@ -8,243 +8,243 @@
|
|||
<contribute xsi:type="subMenu" menuText="Hail Products" id="MRMS_HAIL">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Maximum Estimated Size of Hail (MESH)" id="MESH">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MESH"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="MESH Tracks (30 min. accum.)" id="MESH30">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MESHTrack30min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="MESH Tracks (60 min. accum.)" id="MESH60">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MESHTrack60min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="MESH Tracks (120 min. accum.)" id="MESH120">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MESHTrack120min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="MESH Tracks (240 min. accum.)" id="MESH240">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MESHTrack240min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="MESH Tracks (360 min. accum.)" id="MESH360">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MESHTrack360min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="MESH Tracks (1440 min. accum.)" id="MESH1440">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MESHTrack1440min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Probability Of Severe Hail (POSH)" id="POSH">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="POSH"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Severe Hail Index (SHI)" id="SHI">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="SHI"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="Lightning Products" id="MRMS_LIGHTNING">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Cloud-to-Ground Lightning Density (1 min.)" id="LightDensity1min">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="LightningDensity1min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Cloud-to-Ground Lightning Density (5 min.)" id="LightDensity5min">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="LightningDensity5min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Cloud-to-Ground Lightning Density (15 min.)" id="LightDensity15min">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="LightningDensity15min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Cloud-to-Ground Lightning Density (30 min.)" id="LightDensity30min">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="LightningDensity30min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Cloud-to-Ground Lightning Probability (0-30 min.)" id="LightProb30min">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="LightningProbabilityNext30min"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="Precipitation Products" id="MRMS_PRECIPITATION">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Surface Precipitation Type (SPT)" id="SfcPrecipType">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="PrecipType"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Surface Precipitation Rate (SPR)" id="RadarPrecipRate">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="PrecipRate"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Radar Quality Index (RQI)" id="RadarQualityIndex">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarQualityIndex"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Seamless Hybrid Scan Reflectivity (SHSR)" id="SHSRVPR">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="SeamlessHSR"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="QPE - Radar Only">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="1 hour Accumulation" id="RadarOnly01hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarOnlyQPE01H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="3 hour Accumulation" id="RadarOnly03hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarOnlyQPE03H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="6 hour Accumulation" id="RadarOnly06hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarOnlyQPE06H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="12 hour Accumulation" id="RadarOnly12hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarOnlyQPE12H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="24 hour Accumulation" id="RadarOnly24hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarOnlyQPE24H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="48 hour Accumulation" id="RadarOnly48hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarOnlyQPE48H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="72 hour Accumulation" id="RadarOnly72hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="RadarOnlyQPE72H"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="QPE - Gauge Only">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="1 hour Accumulation" id="GaugeOnly01hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeOnlyQPE01H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="3 hour Accumulation" id="GaugeOnly03hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeOnlyQPE03H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="6 hour Accumulation" id="GaugeOnly06hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeOnlyQPE06H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="12 hour Accumulation" id="GaugeOnly12hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeOnlyQPE12H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="24 hour Accumulation" id="GaugeOnly24hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeOnlyQPE24H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="48 hour Accumulation" id="GaugeOnly48hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeOnlyQPE48H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="72 hour Accumulation" id="GaugeOnly72hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeOnlyQPE72H"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="QPE - Radar w/ Gauge Bias Correction">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="1 hour Accumulation" id="GaugeCorr01hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeCorrQPE01H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="3 hour Accumulation" id="GaugeCorr03hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeCorrQPE03H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="6 hour Accumulation" id="GaugeCorr06hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeCorrQPE06H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="12 hour Accumulation" id="GaugeCorr12hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeCorrQPE12H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="24 hour Accumulation" id="GaugeCorr24hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeCorrQPE24H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="48 hour Accumulation" id="GaugeCorr48hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeCorrQPE48H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="72 hour Accumulation" id="GaugeCorr72hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="GaugeCorrQPE72H"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="QPE - Mountain Mapper">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="1 hour Accumulation" id="MountainMapper01hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MountainMapperQPE01H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="3 hour Accumulation" id="MountainMapper03hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MountainMapperQPE03H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="6 hour Accumulation" id="MountainMapper06hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MountainMapperQPE06H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="12 hour Accumulation" id="MountainMapper12hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MountainMapperQPE12H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="24 hour Accumulation" id="MountainMapper24hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MountainMapperQPE24H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="48 hour Accumulation" id="MountainMapper48hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MountainMapperQPE48H"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="72 hour Accumulation" id="MountainMapper72hr">
|
||||
<substitute key="levelOneValue" value="0.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MountainMapperQPE72H"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
|
@ -252,97 +252,97 @@
|
|||
<contribute xsi:type="subMenu" menuText="Reflectivity Products" id="MRMS_REFLECTIVITY">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Composite Reflectivity" id="CompZ">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MergedReflectivityQCComposite"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Composite Reflectivity Height" id="CompZH">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="HeightCompositeReflectivity"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Reflectivity At Lowest Altitude (RALA)" id="REFLA">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="ReflectivityAtLowestAltitude"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Vertically Integrated Ice (VII)" id="VII">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="VII"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Vertically Integrated Liquid (VIL)" id="MRMSVIL">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="MRMSVIL"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="Echo Tops" id="MRMS_ECHO">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="18 dBZ Echo Top" id="18ET">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="EchoTop18"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="30 dBZ Echo Top" id="30ET">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="EchoTop30"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="50 dBZ Echo Top" id="50ET">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="EchoTop50"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="60 dBZ Echo Top" id="60ET">
|
||||
<substitute key="levelOneValue" value="500.0" />
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="EchoTop60"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="Isothermal Reflectivity" id="REF_ISOTHERMAL">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Reflectivity at 0°C" id="REF0C">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="Reflectivity0C"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Reflectivity at -5°C" id="REFM5C">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="ReflectivityM5C"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Reflectivity at -10°C" id="REFM10C">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="ReflectivityM10C"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Reflectivity at -15°C" id="REFM15C">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="ReflectivityM15C"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Reflectivity at -20°C" id="REFM20C">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="ReflectivityM20C"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="Thickness" id="REF_THICKNESS">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Height of 50dBZ Echo Above -20°C" id="H50253">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="H50AboveM20C"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Height of 60dBZ Echo Above -20°C" id="H60253">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="H60AboveM20C"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Height of 50dBZ Echo Above 0°C" id="H50273">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="H50Above0C"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Height of 60dBZ Echo Above 0°C" id="H60273">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_1000"/>
|
||||
<substitute key="parameterID" value="H60Above0C"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
|
@ -350,73 +350,73 @@
|
|||
<contribute xsi:type="subMenu" menuText="Velocity Products" id="MRMS_VELOCITY">
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Low-Level Azimuthal Shear (0-2km AGL)" id="AZ02">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="MergedAzShear02kmAGL"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Low-Level Rotation Tracks (30 min. accum.)" id="ROTLL30">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackLL30min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Low-Level Rotation Tracks (60 min. accum.)" id="ROTLL60">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackLL60min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Low-Level Rotation Tracks (120 min. accum.)" id="ROTLL120">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackLL120min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Low-Level Rotation Tracks (240 min. accum.)" id="ROTLL240">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackLL240min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Low-Level Rotation Tracks (360 min. accum.)" id="ROTLL360">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackLL360min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Low-Level Rotation Tracks (1440 min. accum.)" id="ROTLL1440">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackLL1440min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Mid-Level Azimuthal Shear (3-6km AGL)" id="AZ36">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="MergedAzShear36kmAGL"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Mid-Level Rotation Tracks (30 min. accum.)" id="ROTML30">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackML30min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Mid-Level Rotation Tracks (60 min. accum.)" id="ROTML60">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackML60min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Mid-Level Rotation Tracks (120 min. accum.)" id="ROTML120">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackML120min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Mid-Level Rotation Tracks (240 min. accum.)" id="ROTML240">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackML240min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Mid-Level Rotation Tracks (360 min. accum.)" id="ROTML360">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackML360min"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/mrms/mrms2D.xml" menuText="Mid-Level Rotation Tracks (1440 min. accum.)" id="ROTML1440">
|
||||
<substitute key="levelOneValue" value="500.0"/>
|
||||
<substitute key="datasetID" value="MRMS"/>
|
||||
<substitute key="datasetID" value="MRMS_0500"/>
|
||||
<substitute key="parameterID" value="RotationTrackML1440min"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
</menuTemplate>
|
||||
</menuTemplate>
|
||||
|
|
|
@ -42,48 +42,6 @@
|
|||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
</displayList>
|
||||
|
|
|
@ -64,48 +64,6 @@
|
|||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true"/>
|
||||
<properties isSystemResource="false" isBlinking="false"
|
||||
isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0" />
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning"
|
||||
constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
</displayList>
|
||||
|
|
|
@ -42,48 +42,6 @@
|
|||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
</displayList>
|
||||
|
|
|
@ -41,48 +41,6 @@
|
|||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="3600" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="3600" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<bundle>
|
||||
<displayList>
|
||||
<displays xsi:type="d2DMapRenderableDisplay" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<descriptor xsi:type="mapDescriptor">
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="true" handlingNegativeStrikes="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
</displayList>
|
||||
</bundle>
|
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<bundle>
|
||||
<displayList>
|
||||
<displays xsi:type="d2DMapRenderableDisplay"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<descriptor xsi:type="mapDescriptor">
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false" isBlinking="false"
|
||||
isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="true" handlingNegativeStrikes="false">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0" />
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning"
|
||||
constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true"/>
|
||||
<properties isSystemResource="false" isBlinking="false"
|
||||
isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0" />
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning"
|
||||
constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true"/>
|
||||
<properties isSystemResource="false" isBlinking="false"
|
||||
isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0" />
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning"
|
||||
constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="900" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
</displayList>
|
||||
</bundle>
|
|
@ -0,0 +1,90 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<bundle>
|
||||
<displayList>
|
||||
<displays xsi:type="d2DMapRenderableDisplay" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<descriptor xsi:type="mapDescriptor">
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="true" handlingNegativeStrikes="true">
|
||||
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
</displayList>
|
||||
</bundle>
|
|
@ -0,0 +1,90 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<bundle>
|
||||
<displayList>
|
||||
<displays xsi:type="d2DMapRenderableDisplay" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<descriptor xsi:type="mapDescriptor">
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="true" handlingNegativeStrikes="true">
|
||||
<binOffset posOffset="0" negOffset="3600" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="true" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingCloudFlashes="true">
|
||||
<binOffset posOffset="0" negOffset="3600" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
<resource>
|
||||
<loadProperties loadWithoutData="true">
|
||||
</loadProperties>
|
||||
<properties isSystemResource="false"
|
||||
isBlinking="false" isMapLayer="false" isHoverOn="false"
|
||||
isVisible="false" />
|
||||
<resourceData xsi:type="lightningResourceData"
|
||||
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
|
||||
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
|
||||
handlingPulses="true">
|
||||
<binOffset posOffset="0" negOffset="3600" virtualOffset="0"/>
|
||||
<metadataMap>
|
||||
<mapping key="pluginName">
|
||||
<constraint constraintValue="binlightning" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
<mapping key="source">
|
||||
<constraint constraintValue="${source}" constraintType="EQUALS" />
|
||||
</mapping>
|
||||
</metadataMap>
|
||||
</resourceData>
|
||||
</resource>
|
||||
</descriptor>
|
||||
</displays>
|
||||
</displayList>
|
||||
</bundle>
|
|
@ -19,16 +19,16 @@
|
|||
further_licensing_information.
|
||||
-->
|
||||
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml"
|
||||
<contribute xsi:type="bundleItem" file="bundles/TotalLightningPlot60Min.xml"
|
||||
menuText="1hr plot" id="1HrLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml"
|
||||
<contribute xsi:type="bundleItem" file="bundles/TotalLightningPlot15Min.xml"
|
||||
menuText="15min plot" id="15MinLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml"
|
||||
<contribute xsi:type="bundleItem" file="bundles/TotalLightningPlot15MinPN.xml"
|
||||
menuText="15min Pos/Neg plot" id="15MinPNLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml"
|
||||
<contribute xsi:type="bundleItem" file="bundles/TotalLightningPlot5Min.xml"
|
||||
menuText="5min plot" id="5MinLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
|
||||
|
|
|
@ -24,51 +24,13 @@
|
|||
menuText="60min cloud to ground density" id="1HrGridLightningCGPlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCloudFlashPlot.xml"
|
||||
menuText="60min cloud flash density" id="1HrGridLightningCloudFlashPlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningTotalFlashPlot.xml"
|
||||
menuText="60min total flash density" id="1HrGridLightningFlashPlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningPulsePlot.xml"
|
||||
menuText="60min pulse density" id="1HrGridLightningPulsePlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCGPlot.xml"
|
||||
menuText="15min cloud to ground density" id="1HrGridLightningCGPlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCloudFlashPlot.xml"
|
||||
menuText="15min cloud flash density" id="1HrGridLightningCloudFlashPlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningTotalFlashPlot.xml"
|
||||
menuText="15min total flash density" id="1HrGridLightningFlashPlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningPulsePlot.xml"
|
||||
menuText="15min pulse density" id="1HrGridLightningPulsePlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCGPlot.xml"
|
||||
menuText="5min cloud to ground density" id="1HrGridLightningCGPlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCloudFlashPlot.xml"
|
||||
menuText="5min cloud flash density" id="1HrGridLightningCloudFlashPlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningTotalFlashPlot.xml"
|
||||
menuText="5min total flash density" id="1HrGridLightningFlashPlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningPulsePlot.xml"
|
||||
menuText="5min pulse density" id="1HrGridLightningPulsePlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
|
||||
</menuTemplate>
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCGPlot.xml"
|
||||
menuText="60min cloud to ground density" id="1HrGridLightningCGPlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCloudFlashPlot.xml"
|
||||
menuText="60min cloud flash density" id="1HrGridLightningCloudFlashPlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningTotalFlashPlot.xml"
|
||||
menuText="60min total flash density" id="1HrGridLightningFlashPlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningPulsePlot.xml"
|
||||
menuText="60min pulse density" id="1HrGridLightningPulsePlot">
|
||||
<substitute key="negOffset" value="3600"/>
|
||||
</contribute>
|
||||
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCGPlot.xml"
|
||||
menuText="15min cloud to ground density" id="1HrGridLightningCGPlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCloudFlashPlot.xml"
|
||||
menuText="15min cloud flash density" id="1HrGridLightningCloudFlashPlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningTotalFlashPlot.xml"
|
||||
menuText="15min total flash density" id="1HrGridLightningFlashPlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningPulsePlot.xml"
|
||||
menuText="15min pulse density" id="1HrGridLightningPulsePlot">
|
||||
<substitute key="negOffset" value="900"/>
|
||||
</contribute>
|
||||
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCGPlot.xml"
|
||||
menuText="5min cloud to ground density" id="1HrGridLightningCGPlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningCloudFlashPlot.xml"
|
||||
menuText="5min cloud flash density" id="1HrGridLightningCloudFlashPlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningTotalFlashPlot.xml"
|
||||
menuText="5min total flash density" id="1HrGridLightningFlashPlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/GridLightningPulsePlot.xml"
|
||||
menuText="5min pulse density" id="1HrGridLightningPulsePlot">
|
||||
<substitute key="negOffset" value="300"/>
|
||||
</contribute>
|
||||
|
||||
</menuTemplate>
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<contribute xsi:type="subMenu" menuText="1km" id="${source}1kmLightningGridSubmenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridTotalLightningBundleItems.xml">
|
||||
<substitute key="resolution" value="1" />
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="3km" id="${source}3kmLightningGridSubmenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridTotalLightningBundleItems.xml">
|
||||
<substitute key="resolution" value="3" />
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="5km" id="${source}5kmLightningGridSubmenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridTotalLightningBundleItems.xml">
|
||||
<substitute key="resolution" value="5" />
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="8km" id="${source}8kmLightningGridSubmenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridTotalLightningBundleItems.xml">
|
||||
<substitute key="resolution" value="8" />
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="20km" id="${source}20kmLightningGridSubmenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridTotalLightningBundleItems.xml">
|
||||
<substitute key="resolution" value="20" />
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="40km" id="${source}40kmLightningGridSubmenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridTotalLightningBundleItems.xml">
|
||||
<substitute key="resolution" value="40" />
|
||||
</contribute>
|
||||
</contribute>
|
||||
</menuTemplate>
|
|
@ -45,8 +45,9 @@
|
|||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="Total Lightning Grid" id="entlnGridSubmenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridLightningMenuItems.xml">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/gridTotalLightningMenuItems.xml">
|
||||
<substitute key="source" value="ENTLN"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="separator" id="LMATotalLightning" visible="false" />
|
||||
</menuTemplate>
|
|
@ -34,7 +34,4 @@
|
|||
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
|
||||
menuText="1min Lgtng Seq Plot" id="1MinLightningFlashSeq">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningCloudSeq.xml"
|
||||
menuText="1min Cloud Flash Seq Plot" id="1MinLightningCloudFlashSeq">
|
||||
</contribute>
|
||||
</menuTemplate>
|
|
@ -75,6 +75,7 @@ import com.raytheon.viz.lightning.cache.LightningFrameRetriever;
|
|||
* Jul 22, 2014 3333 bclement ignores strikes that aren't on map
|
||||
* Jul 28, 2014 3451 bclement uses intended range min
|
||||
* Jul 29, 2014 3463 bclement uses sparse data source
|
||||
* Mar 05, 2015 4233 bsteffen include source in cache key.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -274,7 +275,8 @@ public class GridLightningResource extends
|
|||
* no local reference to cache object, create key and get cache
|
||||
* object which may be new or from another resource
|
||||
*/
|
||||
LightningFrameMetadata key = new LightningFrameMetadata(time,
|
||||
LightningFrameMetadata key = new LightningFrameMetadata(
|
||||
resourceData.getSource(), time,
|
||||
resourceData.getBinOffset());
|
||||
co = CacheObject.newCacheObject(key, retriever);
|
||||
cacheObjectMap.put(time, co);
|
||||
|
|
|
@ -32,8 +32,6 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
|||
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.LightningConstants;
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
|
@ -92,6 +90,7 @@ import com.raytheon.viz.lightning.cache.LightningFrameRetriever;
|
|||
* moved name formatting to static method
|
||||
* Aug 04, 2014 3488 bclement added sanity check for record bin range
|
||||
* Aug 19, 2014 3542 bclement fixed strike count clipping issue
|
||||
* Mar 05, 2015 4233 bsteffen include source in cache key.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -111,7 +110,7 @@ public class LightningResource extends
|
|||
private boolean needsUpdate;
|
||||
|
||||
private String resourceName;
|
||||
|
||||
|
||||
private int posAdj;
|
||||
|
||||
private IFont font;
|
||||
|
@ -222,11 +221,9 @@ public class LightningResource extends
|
|||
rval += modifier;
|
||||
}
|
||||
|
||||
HashMap<String, RequestConstraint> metadata = resourceData
|
||||
.getMetadataMap();
|
||||
if (metadata != null && metadata.containsKey(LightningConstants.SOURCE)) {
|
||||
rval += metadata.get(LightningConstants.SOURCE)
|
||||
.getConstraintValue() + " ";
|
||||
String source = resourceData.getSource();
|
||||
if (source != null) {
|
||||
rval += source + " ";
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
@ -283,9 +280,10 @@ public class LightningResource extends
|
|||
int negCount = 0;
|
||||
int cloudCount = 0;
|
||||
int pulseCount = 0;
|
||||
|
||||
if (magnification == 0.0) magnification=(float) 0.01;
|
||||
|
||||
|
||||
if (magnification == 0.0)
|
||||
magnification = (float) 0.01;
|
||||
|
||||
/*
|
||||
* we only want strikes that are visible so we have to filter any
|
||||
* strikes that aren't in both the clipping pane and the view
|
||||
|
@ -448,7 +446,8 @@ public class LightningResource extends
|
|||
* we know about, return without removing the time.
|
||||
*/
|
||||
if (dataTimes.indexOf(dataTime) == dataTimes.size() - 1) {
|
||||
CacheObject<LightningFrameMetadata, LightningFrame> co = cacheObjectMap.get(dataTime);
|
||||
CacheObject<LightningFrameMetadata, LightningFrame> co = cacheObjectMap
|
||||
.get(dataTime);
|
||||
if (co != null) {
|
||||
LightningFrameMetadata metadata = co.getMetadata();
|
||||
synchronized (metadata) {
|
||||
|
@ -468,13 +467,12 @@ public class LightningResource extends
|
|||
Map<DataTime, List<BinLightningRecord>> recordMap = new HashMap<DataTime, List<BinLightningRecord>>();
|
||||
|
||||
for (BinLightningRecord obj : objs) {
|
||||
long duration = obj.getDataTime().getValidPeriod()
|
||||
.getDuration();
|
||||
if (duration > MAX_RECORD_BIN_MILLIS) {
|
||||
statusHandler.error("Record bin time larger than maximum "
|
||||
+ "supported period. Skipping record: " + obj);
|
||||
continue;
|
||||
}
|
||||
long duration = obj.getDataTime().getValidPeriod().getDuration();
|
||||
if (duration > MAX_RECORD_BIN_MILLIS) {
|
||||
statusHandler.error("Record bin time larger than maximum "
|
||||
+ "supported period. Skipping record: " + obj);
|
||||
continue;
|
||||
}
|
||||
DataTime time = new DataTime(obj.getStartTime());
|
||||
DataTime end = new DataTime(obj.getStopTime());
|
||||
time = this.getResourceData().getBinOffset()
|
||||
|
@ -518,7 +516,8 @@ public class LightningResource extends
|
|||
* no local reference to cache object, create key and get
|
||||
* cache object which may be new or from another resource
|
||||
*/
|
||||
LightningFrameMetadata key = new LightningFrameMetadata(dt,
|
||||
LightningFrameMetadata key = new LightningFrameMetadata(
|
||||
resourceData.getSource(), dt,
|
||||
resourceData.getBinOffset());
|
||||
co = CacheObject.newCacheObject(key, retriever);
|
||||
cacheObjectMap.put(dt, co);
|
||||
|
|
|
@ -28,6 +28,7 @@ import javax.xml.bind.annotation.XmlAttribute;
|
|||
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.LightningConstants;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
@ -47,7 +48,7 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
|||
* Feb 27, 2013 DCS 152 jgerth Support for WWLLN and multiple sources
|
||||
* Jun 19, 2014 3214 bclement added pulse and cloud flash support
|
||||
* Jul 07, 2014 3333 bclement removed plotLightSource field
|
||||
*
|
||||
* Mar 05, 2015 4233 bsteffen include source in cache key.
|
||||
* </pre>
|
||||
*
|
||||
* @author chammack
|
||||
|
@ -208,6 +209,15 @@ public class LightningResourceData extends AbstractRequestableResourceData {
|
|||
this.countPosition = countPosition;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
if (metadataMap != null
|
||||
&& metadataMap.containsKey(LightningConstants.SOURCE)) {
|
||||
return metadataMap.get(LightningConstants.SOURCE)
|
||||
.getConstraintValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
|
|
@ -36,6 +36,7 @@ import com.raytheon.uf.common.time.DataTime;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 9, 2014 3333 bclement moved from LightningResource
|
||||
* Mar 05, 2015 4233 bsteffen include source in cache key.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -44,6 +45,8 @@ import com.raytheon.uf.common.time.DataTime;
|
|||
*/
|
||||
public class LightningFrameMetadata {
|
||||
|
||||
private final String source;
|
||||
|
||||
private final BinOffset offset;
|
||||
|
||||
private final DataTime frameTime;
|
||||
|
@ -52,7 +55,9 @@ public class LightningFrameMetadata {
|
|||
|
||||
private final List<BinLightningRecord> processed = new ArrayList<BinLightningRecord>();
|
||||
|
||||
public LightningFrameMetadata(DataTime frameTime, BinOffset offset) {
|
||||
public LightningFrameMetadata(String source, DataTime frameTime,
|
||||
BinOffset offset) {
|
||||
this.source = source;
|
||||
this.frameTime = frameTime;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
@ -92,6 +97,7 @@ public class LightningFrameMetadata {
|
|||
result = prime * result
|
||||
+ ((frameTime == null) ? 0 : frameTime.hashCode());
|
||||
result = prime * result + ((offset == null) ? 0 : offset.hashCode());
|
||||
result = prime * result + ((source == null) ? 0 : source.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -114,6 +120,11 @@ public class LightningFrameMetadata {
|
|||
return false;
|
||||
} else if (!offset.equals(other.offset))
|
||||
return false;
|
||||
if (source == null) {
|
||||
if (other.source != null)
|
||||
return false;
|
||||
} else if (!source.equals(other.source))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import com.raytheon.viz.mpe.util.ReadTemperatureStationList;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 31, 2009 snaples Initial creation
|
||||
* Feb 5, 2015 17101 snaples Updated max_stations to use size of dqc.precip_stations.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -72,13 +73,9 @@ public class GroupEditCalls {
|
|||
|
||||
int pcpn_time = dqc.pcpn_time;
|
||||
|
||||
ReadPrecipStationList rp = new ReadPrecipStationList();
|
||||
int max_stations = dqc.precip_stations.size();
|
||||
|
||||
ReadTemperatureStationList rt = new ReadTemperatureStationList();
|
||||
|
||||
int max_stations = rp.getNumPstations();
|
||||
|
||||
int max_tstations = rt.getNumTstations();
|
||||
int max_tstations = dqc.temperature_stations.size();
|
||||
|
||||
public void apply_group()
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jan 7, 2015 16954 cgobs Fix for cv_use issue - using getFieldName() in certain parts.
|
||||
* Feb 4, 2015 17094 cgobs Fix for fieldType being too long for mapx_field_type column in RWResult table.
|
||||
* </pre>
|
||||
**/
|
||||
package com.raytheon.viz.mpe.ui.actions;
|
||||
|
@ -33,8 +34,10 @@ import java.io.IOException;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriter;
|
||||
|
@ -343,7 +346,10 @@ public class SaveBestEstimate {
|
|||
Rwresult pRWResultNode = pRWResultHead.get(0);
|
||||
|
||||
/* Update the elements in the RWResult node. */
|
||||
pRWResultNode.setMapxFieldType(fldtype);
|
||||
|
||||
fldtype = checkAndModifyMapxFieldType(fldtype);
|
||||
|
||||
pRWResultNode.setMapxFieldType(fldtype.toLowerCase());
|
||||
pRWResultNode.setAutoSave(asave);
|
||||
pRWResultNode.setDrawPrecip(drpr);
|
||||
pRWResultNode.setLastSaveTime(SimulatedTime.getSystemTime()
|
||||
|
@ -365,4 +371,32 @@ public class SaveBestEstimate {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private static String checkAndModifyMapxFieldType(String fieldType) {
|
||||
|
||||
// This method changes fieldType to lowercase.
|
||||
// It also shortens fieldTypes as needed to fit into the mapx_field_type column in the RWResult table.
|
||||
// Note: the mapx_field_type column is informational only. It is not used by the code
|
||||
// other than reading and writing from and to the database.
|
||||
|
||||
String newFieldType = null;
|
||||
String lowerCaseFieldType = fieldType.toLowerCase();
|
||||
|
||||
final Map<String,String> conversionTable = new HashMap<String , String>();
|
||||
|
||||
conversionTable.put("localfield1", "localfld1");
|
||||
conversionTable.put("localfield2", "localfld2");
|
||||
conversionTable.put("localfield3", "localfld3");
|
||||
|
||||
conversionTable.put("avgrdmosaic", "avgrdmos");
|
||||
conversionTable.put("maxrdmosaic", "maxrdmos");
|
||||
|
||||
|
||||
newFieldType = conversionTable.get(lowerCaseFieldType);
|
||||
if (newFieldType == null)
|
||||
{
|
||||
newFieldType = lowerCaseFieldType;
|
||||
}
|
||||
return newFieldType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
|||
* Feb 2, 2014 16201 snaples Added saved data flag support
|
||||
* Apr 28, 2014 16707 snaples Added code to save and set location of dialog box when moved.
|
||||
* Jan 12, 2015 16993 snaples Restored code for Substitute Field Combo box.
|
||||
*
|
||||
* Feb 26, 2015 17209 cgobs Ensured that there is an initial selection of Substitution field, prevents empty selection.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -387,16 +387,22 @@ public class DrawPolygonDlg extends CaveSWTDialog {
|
|||
// spaceLabel.setText("***** ");
|
||||
|
||||
int selectedFieldIndex = 0;
|
||||
|
||||
boolean found = false;
|
||||
//find the index of the selected field
|
||||
for (selectedFieldIndex = 0; selectedFieldIndex < displayFieldDataArray.length; selectedFieldIndex++)
|
||||
{
|
||||
if (displayFieldDataArray[selectedFieldIndex] == subType)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
selectedFieldIndex = 0;
|
||||
}
|
||||
|
||||
//create and initialize the display field type name array
|
||||
displayTypeNameArray = new String[displayFieldDataArray.length];
|
||||
|
||||
|
@ -411,27 +417,42 @@ public class DrawPolygonDlg extends CaveSWTDialog {
|
|||
fieldTypeCombo.setTextLimit(35);
|
||||
fieldTypeCombo.setLayoutData(gd);
|
||||
fieldTypeCombo.setItems(displayTypeNameArray);
|
||||
fieldTypeCombo.select(selectedFieldIndex);
|
||||
// fieldTypeCombo.select(selectedFieldIndex);
|
||||
|
||||
fieldTypeCombo.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
String selectedFieldString = fieldTypeCombo.getText();
|
||||
|
||||
setSubstitutionField();
|
||||
|
||||
// String selectedFieldString = fieldTypeCombo.getText();
|
||||
|
||||
// System.out.println("DrawPolygon.createFieldCombo(): selectedFieldString = " +
|
||||
// selectedFieldString);
|
||||
|
||||
subType = DisplayFieldData.fromDisplayNameString(selectedFieldString);
|
||||
// subType = DisplayFieldData.fromDisplayNameString(selectedFieldString);
|
||||
|
||||
// if (subType != null)
|
||||
// {
|
||||
// System.out.println("DrawPolygon.createFieldCombo(): subType = " +
|
||||
// subType.toString());
|
||||
// }
|
||||
// {
|
||||
// System.out.println("DrawPolygon.createFieldCombo(): subType = " +
|
||||
// subType.toString());
|
||||
// }
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//select the substitution field
|
||||
|
||||
fieldTypeCombo.select(selectedFieldIndex);
|
||||
setSubstitutionField();
|
||||
|
||||
}
|
||||
|
||||
private void setSubstitutionField()
|
||||
{
|
||||
String selectedFieldString = fieldTypeCombo.getText();
|
||||
subType = DisplayFieldData.fromDisplayNameString(selectedFieldString);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -160,7 +160,7 @@ public class BestEstimate1HrQpeDlg extends BasePostAnalysisDlg {
|
|||
applyGridAdjustments(adjustedGrid, biasRatioGrid, disaggGrid);
|
||||
|
||||
float[] dataArray = paMgr.convertToSingleArray(adjustedGrid, false, true);
|
||||
short[] shortArray= paMgr.convertToShortArray(dataArray, 100.0f);
|
||||
short[] shortArray= paMgr.convertToShortArray(dataArray, 1.0f);
|
||||
|
||||
XmrgFile file = new XmrgFile();
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* December 2013 DCS 167 C. Gobs Initial version
|
||||
*
|
||||
* February 2015 C. Gobs Fixed issue with parsing unexpected file name formats in xmrg directory
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
|
@ -156,6 +156,7 @@ public class PostAnalysisManager
|
|||
try
|
||||
{
|
||||
shiftedDate = utcSdf2.parse(timeString);
|
||||
longTime = shiftedDate.getTime();
|
||||
}
|
||||
catch(ParseException e)
|
||||
{
|
||||
|
@ -164,7 +165,7 @@ public class PostAnalysisManager
|
|||
|
||||
}
|
||||
|
||||
longTime = shiftedDate.getTime();
|
||||
|
||||
|
||||
return longTime;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 9, 2009 snaples Initial creation
|
||||
* Feb 5, 2015 17101 snaples Fixed issue with writing zero length bad values file.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -51,8 +52,7 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
|||
public class BadValues {
|
||||
BufferedReader in = null;
|
||||
DailyQcUtils dqc = DailyQcUtils.getInstance();
|
||||
ReadPrecipStationList rp = new ReadPrecipStationList();
|
||||
private int max_stations = rp.getNumPstations();
|
||||
private int max_stations = dqc.precip_stations.size();
|
||||
|
||||
|
||||
public void read_bad_values(String precd, int m) {
|
||||
|
@ -194,7 +194,7 @@ public class BadValues {
|
|||
// ier=sprintf(ibuf,"%s %s %d %f\n",bad_values[i].hb5,bad_values[i].parm,
|
||||
// bad_values[i].quart,bad_values[i].fvalue);
|
||||
|
||||
ibuf = String.format("%s %s %d %f", bad_values[i].hb5,
|
||||
ibuf = String.format("%s %s %d %4.2f", bad_values[i].hb5,
|
||||
bad_values[i].parm, bad_values[i].quart,
|
||||
bad_values[i].fvalue);
|
||||
out.write(ibuf);
|
||||
|
|
|
@ -41,6 +41,7 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 11, 2009 snaples Initial creation
|
||||
* Feb 5, 2015 17101 snaples Updated max_stations to use size of dqc.precip_stations.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -68,8 +69,7 @@ public class GetBadSnotel {
|
|||
/* Retrieve the number of days to QC data for. */
|
||||
num_qc_days = dqc.qcDays;
|
||||
|
||||
ReadPrecipStationList pl = new ReadPrecipStationList();
|
||||
int max_stations = pl.getNumPstations();
|
||||
int max_stations = dqc.precip_stations.size();
|
||||
// Pdata[] pdata = DailyQcUtils.pdata;
|
||||
|
||||
for (j = 0; j < num_qc_days; j++) {
|
||||
|
|
|
@ -36,6 +36,7 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 23, 2009 snaples Initial creation
|
||||
* Feb 3, 2015 16993 snaples Fixed if condition on cparm.
|
||||
* Mar 2, 2015 15660 snaples Fixed issue with if statement testing CPARM and checking for both values to be true, broken logic.
|
||||
*
|
||||
* </pre>
|
||||
|
|
|
@ -43,8 +43,9 @@ import com.raytheon.viz.mpe.core.MPEDataManager;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 24, 2009 snaples Initial creation
|
||||
* April , 2012 8672 lbousaidi fixed the reading of the PRISM data.
|
||||
* Mar 2, 2015 15660 snaples Fixed problem with color scale using wrong values. Causing grids to be all zeros.
|
||||
* April , 2012 8672 lbousaidi fixed the reading of the PRISM data.
|
||||
* Feb 3, 2015 16993 snaples fixed color scale data conversion issue.
|
||||
* Mar 2, 2015 15660 snaples Fixed problem with color scale using wrong values. Causing grids to be all zeros.
|
||||
* </pre>
|
||||
*
|
||||
* @author snaples
|
||||
|
|
|
@ -86,6 +86,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
|||
* Jul 22, 2014 3419 jsanchez Cleaned up converFeAreaToPartList.
|
||||
* Sep 14, 2014 ASM #641 dhuffman Filtered out cases where Areas do not match Zones by using
|
||||
* refactored WarngenLayer::filterArea.
|
||||
* Mar 9, 2014 ASM #17190 D. Friedman Use fipsField and areaField for unique area ID.
|
||||
* </pre>
|
||||
*
|
||||
* @author chammack
|
||||
|
@ -191,8 +192,7 @@ public class Area {
|
|||
}
|
||||
}
|
||||
|
||||
List<String> uniqueFips = new ArrayList<String>();
|
||||
List<String> uniqueCountyname = new ArrayList<String>();
|
||||
List<String> uniqueAreaIDs = new ArrayList<String>();
|
||||
List<AffectedAreas> areas = new ArrayList<AffectedAreas>();
|
||||
for (GeospatialData regionFeature : countyMap.values()) {
|
||||
Geometry regionGeom = regionFeature.geometry;
|
||||
|
@ -272,14 +272,15 @@ 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)) {
|
||||
uniqueFips.add(area.fips);
|
||||
if (countyName != null) {
|
||||
uniqueCountyname.add(countyName);
|
||||
}
|
||||
/*
|
||||
* Usually, the fipsField value is a unique identifier, but in some
|
||||
* cases there are multiple areas that have the same value. These
|
||||
* areas have different names, so we make that part of the unique
|
||||
* ID.
|
||||
*/
|
||||
String areaID = area.fips + ':' + area.name;
|
||||
if (uniqueAreaIDs.contains(areaID) == false) {
|
||||
uniqueAreaIDs.add(areaID);
|
||||
areas.add(area);
|
||||
}
|
||||
}
|
||||
|
|
22
deltaScripts/14.4.1/DR4209/updateSatSpatialDiffTypes.sh
Normal file
22
deltaScripts/14.4.1/DR4209/updateSatSpatialDiffTypes.sh
Normal file
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
# DR #4209 - this update script will convert the satellite_spatial dx and dy columns to double precision
|
||||
# This is only necessary on sites installed before 14.2 but there is no harm running it everywhere.
|
||||
|
||||
PSQL="/awips2/psql/bin/psql"
|
||||
|
||||
echo "INFO: Updating satellite spatial table"
|
||||
|
||||
${PSQL} -U awips -d metadata -c "ALTER TABLE satellite_spatial ALTER COLUMN dx SET DATA TYPE double precision;"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Failed to update column type for dx column of satellite_spatial table"
|
||||
echo "FATAL: The update has failed."
|
||||
exit 1
|
||||
fi
|
||||
${PSQL} -U awips -d metadata -c "ALTER TABLE satellite_spatial ALTER COLUMN dy SET DATA TYPE double precision;"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Failed to update column type for dy column of satellite_spatial table"
|
||||
echo "FATAL: The update has failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "INFO: Satellite spatial table successfully updated."
|
71
edexOsgi/build.edex/esb/bin/ndmMenuIngester.sh
Normal file
71
edexOsgi/build.edex/esb/bin/ndmMenuIngester.sh
Normal file
|
@ -0,0 +1,71 @@
|
|||
#!/bin/bash
|
||||
##
|
||||
# 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.
|
||||
##
|
||||
# NDM Menu File Ingester
|
||||
|
||||
if [ "$1" == "-help" ];
|
||||
then
|
||||
echo ""
|
||||
echo "ndmMenuIngester.sh <ndmFileDirectory> <ndmMenuFileName>"
|
||||
echo " ndmFileDirectory is the directory holding the ndm files"
|
||||
echo " ndmMenuFileName is the name of the ndm menu file to convert"
|
||||
echo ""
|
||||
echo " Required files: redbookDataKeys.txt, redbookDepictKeys.txt,"
|
||||
echo " redbookProductButtons.txt, and the menu file to convert"
|
||||
exit;
|
||||
fi
|
||||
if [ ! -d "$1" ];
|
||||
then
|
||||
echo "Directory [$1] does not exist!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -f "$1/$2" ];
|
||||
then
|
||||
echo "File [$2] does not exist!"
|
||||
exit
|
||||
fi
|
||||
SRC_DIR=$1
|
||||
MENU_FILE=$2
|
||||
path_to_script=`readlink -f $0`
|
||||
dir=$(dirname $path_to_script)
|
||||
dir=$(dirname $dir)
|
||||
AWIPS_HOME=$(dirname $dir)
|
||||
|
||||
# Search for jars
|
||||
EDEX_PLUGINS="$AWIPS_HOME/edex/lib/"
|
||||
JARS=$(find $EDEX_PLUGINS -name "*.jar")
|
||||
|
||||
# Add jars to classpath
|
||||
addSep=false
|
||||
for i in $JARS
|
||||
do
|
||||
if [[ "$addSep" == true ]];
|
||||
then
|
||||
LOCAL_CLASSPATH=$LOCAL_CLASSPATH":"$i
|
||||
else
|
||||
LOCAL_CLASSPATH=$i
|
||||
addSep=true
|
||||
fi
|
||||
done
|
||||
|
||||
JAVA_INSTALL=/awips2/java/
|
||||
${JAVA_INSTALL}/bin/java -classpath $LOCAL_CLASSPATH com.raytheon.uf.edex.plugin.redbook.menu.NdmMenuConverter $SRC_DIR $MENU_FILE
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<bean id="gfeSiteActivation" class="com.raytheon.edex.plugin.gfe.config.GFESiteActivation"
|
||||
depends-on="commonTimeRegistered, gfeDbRegistered, levelFactoryInitialized">
|
||||
<constructor-arg ref="fetchATSrv" />
|
||||
<constructor-arg ref="iscProvider" />
|
||||
</bean>
|
||||
|
||||
<bean id="gfeSitesActiveRequest" factory-bean="siteAwareRegistry" factory-method="register">
|
||||
|
@ -588,22 +588,32 @@
|
|||
<constructor-arg ref="clusteredGfeIscRoutes"/>
|
||||
</bean>
|
||||
|
||||
<!-- Active Table Sharing Definitions -->
|
||||
<bean id="fetchATSrv" class="com.raytheon.edex.plugin.gfe.isc.FetchActiveTableSrv" />
|
||||
<!-- ISC Services Beans -->
|
||||
<bean id="iscProvider" class="com.raytheon.edex.plugin.gfe.isc.IscServiceProvider" />
|
||||
|
||||
<bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
|
||||
<constructor-arg ref="activeTableSharingRoutes"/>
|
||||
<bean id="fetchATSrv" class="com.raytheon.edex.plugin.gfe.isc.FetchActiveTableSrv" />
|
||||
<bean factory-bean="iscProvider" factory-method="addISCService">
|
||||
<constructor-arg ref="fetchATSrv"/>
|
||||
</bean>
|
||||
|
||||
<camelContext id="activeTableSharingRoutes" xmlns="http://camel.apache.org/schema/spring"
|
||||
<bean id="requestTCVSrv" class="com.raytheon.edex.plugin.gfe.isc.RequestTCVSrv" />
|
||||
<bean factory-bean="iscProvider" factory-method="addISCService">
|
||||
<constructor-arg ref="requestTCVSrv"/>
|
||||
</bean>
|
||||
|
||||
<bean factory-bean="contextManager" factory-method="registerContextStateProcessor">
|
||||
<constructor-arg ref="clusteredIscBeans" />
|
||||
<constructor-arg ref="iscProvider" />
|
||||
</bean>
|
||||
|
||||
<camelContext id="clusteredIscBeans" xmlns="http://camel.apache.org/schema/spring"
|
||||
errorHandlerRef="errorHandler">
|
||||
<route id="activateFetchATSrv">
|
||||
<from uri="timer://activateActiveTableSharing?repeatCount=1"/>
|
||||
<bean ref="fetchATSrv" method="activateService"/>
|
||||
<route id="activateISC">
|
||||
<from uri="timer://activateISCServices?repeatCount=1"/>
|
||||
<bean ref="iscProvider" method="activateInstance"/>
|
||||
</route>
|
||||
</camelContext>
|
||||
<bean factory-bean="contextManager" factory-method="registerClusteredContext">
|
||||
<constructor-arg ref="activeTableSharingRoutes"/>
|
||||
<constructor-arg ref="clusteredIscBeans"/>
|
||||
</bean>
|
||||
</beans>
|
||||
|
|
|
@ -21,41 +21,22 @@ package com.raytheon.edex.plugin.gfe.config;
|
|||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
|
||||
import com.raytheon.edex.plugin.gfe.exception.GfeMissingConfigurationException;
|
||||
import com.raytheon.edex.plugin.gfe.isc.FetchActiveTableSrv;
|
||||
import com.raytheon.edex.plugin.gfe.isc.IRTManager;
|
||||
import com.raytheon.edex.plugin.gfe.isc.IscServiceProvider;
|
||||
import com.raytheon.edex.plugin.gfe.server.IFPServer;
|
||||
import com.raytheon.edex.site.SiteUtil;
|
||||
import com.raytheon.uf.common.dataplugin.PluginException;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException;
|
||||
import com.raytheon.uf.common.localization.IPathManager;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||
import com.raytheon.uf.common.python.PyUtil;
|
||||
import com.raytheon.uf.common.python.PythonScript;
|
||||
import com.raytheon.uf.common.site.notify.SiteActivationNotification;
|
||||
import com.raytheon.uf.common.site.notify.SiteActivationNotification.ACTIVATIONSTATUS;
|
||||
import com.raytheon.uf.common.site.notify.SiteActivationNotification.ACTIVATIONTYPE;
|
||||
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.util.FileUtil;
|
||||
import com.raytheon.uf.edex.activetable.ActiveTablePyIncludeUtil;
|
||||
import com.raytheon.uf.edex.core.EDEXUtil;
|
||||
import com.raytheon.uf.edex.core.EdexException;
|
||||
import com.raytheon.uf.edex.database.DataAccessLayerException;
|
||||
|
@ -94,6 +75,7 @@ import com.raytheon.uf.edex.site.notify.SendSiteActivationNotifications;
|
|||
* Oct 07, 2014 #3684 randerso Restructured IFPServer start up
|
||||
* Dec 10, 2014 #4953 randerso Added requestTCVFiles call at site activation
|
||||
* Feb 25, 2015 #4128 dgilling Simplify activation of active table sharing.
|
||||
* Mar 11, 2015 #4128 dgilling Refactor activation and management of ISC services.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -113,9 +95,7 @@ public class GFESiteActivation implements ISiteActivationListener {
|
|||
|
||||
private boolean intialized;
|
||||
|
||||
private final ExecutorService postActivationTaskExecutor;
|
||||
|
||||
private final FetchActiveTableSrv fetchAtSrv;
|
||||
private final IscServiceProvider iscServices;
|
||||
|
||||
/**
|
||||
* Default constructor. Builds a GFESiteActivation instance with no
|
||||
|
@ -127,17 +107,14 @@ public class GFESiteActivation implements ISiteActivationListener {
|
|||
|
||||
/**
|
||||
* Builds a GFESiteActivation instance with an associated
|
||||
* {@code FetchActiveTableSrv} instance. Should only be used on request JVM.
|
||||
* {@code IscServiceProvider} instance. Should only be used on request JVM.
|
||||
*
|
||||
* @param fetchAtSrv
|
||||
* {@code FetchActiveTableSrv} instance
|
||||
* @param iscServices
|
||||
* {@code IscServiceProvider} instance
|
||||
*/
|
||||
public GFESiteActivation(final FetchActiveTableSrv fetchAtSrv) {
|
||||
public GFESiteActivation(final IscServiceProvider iscServices) {
|
||||
this.intialized = false;
|
||||
this.postActivationTaskExecutor = MoreExecutors
|
||||
.getExitingExecutorService((ThreadPoolExecutor) Executors
|
||||
.newCachedThreadPool());
|
||||
this.fetchAtSrv = fetchAtSrv;
|
||||
this.iscServices = iscServices;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -330,63 +307,8 @@ public class GFESiteActivation implements ISiteActivationListener {
|
|||
ClusterLockUtils.unlock(ct, false);
|
||||
}
|
||||
|
||||
// Doesn't need to be cluster locked
|
||||
statusHandler.info("Checking ISC configuration...");
|
||||
if (config.requestISC()) {
|
||||
String host = InetAddress.getLocalHost().getCanonicalHostName();
|
||||
String gfeHost = config.getServerHost();
|
||||
String hostNameToCompare = gfeHost;
|
||||
if (gfeHost.endsWith("f")) {
|
||||
hostNameToCompare = gfeHost.substring(0, gfeHost.length() - 1);
|
||||
}
|
||||
// TODO: specific to a host and jvm type, register it independently,
|
||||
// but don't hard code request
|
||||
if (host.contains(hostNameToCompare)
|
||||
&& System.getProperty("edex.run.mode").equals("request")) {
|
||||
statusHandler.info("Enabling ISC...");
|
||||
try {
|
||||
IRTManager.getInstance().enableISC(siteID, config);
|
||||
|
||||
final IFPServerConfig configRef = config;
|
||||
|
||||
if (configRef.tableFetchTime() > 0) {
|
||||
Runnable activateTableSharing = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
EDEXUtil.waitForRunning();
|
||||
fetchAtSrv.activateSite(siteID, configRef);
|
||||
}
|
||||
};
|
||||
postActivationTaskExecutor.submit(activateTableSharing);
|
||||
}
|
||||
|
||||
Runnable requestTCV = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// wait until EDEX is up and running to request TCV
|
||||
// files
|
||||
EDEXUtil.waitForRunning();
|
||||
|
||||
requestTCVFiles(siteID, configRef);
|
||||
}
|
||||
};
|
||||
|
||||
postActivationTaskExecutor.submit(requestTCV);
|
||||
|
||||
} catch (Exception e) {
|
||||
statusHandler
|
||||
.error("Error starting GFE ISC. ISC functionality will be unavailable!!",
|
||||
e);
|
||||
}
|
||||
} else {
|
||||
statusHandler
|
||||
.info("ISC Enabled but will use another EDEX instance");
|
||||
}
|
||||
|
||||
} else {
|
||||
statusHandler.info("ISC is not enabled.");
|
||||
if (iscServices != null) {
|
||||
iscServices.activateSite(siteID, config);
|
||||
}
|
||||
|
||||
statusHandler.info("Adding " + siteID + " to active sites list.");
|
||||
|
@ -423,6 +345,10 @@ public class GFESiteActivation implements ISiteActivationListener {
|
|||
|
||||
}
|
||||
|
||||
if (iscServices != null) {
|
||||
iscServices.deactivateSite(siteID);
|
||||
}
|
||||
|
||||
IFPServer.deactivateServer(siteID);
|
||||
statusHandler.info(siteID + " successfully deactivated");
|
||||
|
||||
|
@ -488,46 +414,4 @@ public class GFESiteActivation implements ISiteActivationListener {
|
|||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void requestTCVFiles(String siteId, IFPServerConfig config) {
|
||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||
LocalizationContext commonBaseCx = pathMgr.getContext(
|
||||
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
|
||||
String scriptPath = pathMgr.getFile(commonBaseCx,
|
||||
FileUtil.join(ActiveTablePyIncludeUtil.VTEC, "requestTCV.py"))
|
||||
.getPath();
|
||||
|
||||
String pythonIncludePath = PyUtil.buildJepIncludePath(
|
||||
ActiveTablePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
ActiveTablePyIncludeUtil.getCommonGfeIncludePath(),
|
||||
ActiveTablePyIncludeUtil.getVtecIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getIscScriptsIncludePath());
|
||||
|
||||
PythonScript script = null;
|
||||
try {
|
||||
script = new PythonScript(scriptPath, pythonIncludePath, this
|
||||
.getClass().getClassLoader());
|
||||
|
||||
try {
|
||||
Map<String, Object> argMap = new HashMap<String, Object>();
|
||||
argMap.put("siteID", siteId);
|
||||
argMap.put("config", config);
|
||||
script.execute("runFromJava", argMap);
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error executing requestTCV.", e);
|
||||
}
|
||||
} catch (JepException e) {
|
||||
statusHandler
|
||||
.handle(Priority.PROBLEM,
|
||||
"Unable to instantiate requestTCV python script object.",
|
||||
e);
|
||||
} finally {
|
||||
if (script != null) {
|
||||
script.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,12 +30,11 @@ import java.util.concurrent.ScheduledFuture;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
|
||||
import com.raytheon.edex.plugin.gfe.server.IFPServer;
|
||||
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.util.RunProcess;
|
||||
import com.raytheon.uf.edex.core.IContextStateProcessor;
|
||||
import com.raytheon.uf.edex.core.EDEXUtil;
|
||||
|
||||
/**
|
||||
* Service that fetches neighboring sites' active table entries that are
|
||||
|
@ -53,6 +52,8 @@ import com.raytheon.uf.edex.core.IContextStateProcessor;
|
|||
* fetching when site is deactivated.
|
||||
* Feb 26, 2015 #4128 dgilling Moved to edex.gfe plugin, rewritten as
|
||||
* IContextStateProcessor.
|
||||
* Mar 11, 2015 #4128 dgilling Ensure this service runs on same cluster
|
||||
* node as was registered with IRT.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -60,7 +61,7 @@ import com.raytheon.uf.edex.core.IContextStateProcessor;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class FetchActiveTableSrv implements IContextStateProcessor {
|
||||
public final class FetchActiveTableSrv implements IISCServiceBean {
|
||||
|
||||
private static final class FetchATJobConfig {
|
||||
|
||||
|
@ -165,31 +166,21 @@ public final class FetchActiveTableSrv implements IContextStateProcessor {
|
|||
|
||||
private ScheduledExecutorService jobExecutor;
|
||||
|
||||
private volatile boolean activeServiceInstance;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public FetchActiveTableSrv() {
|
||||
this.activeServiceInstance = false;
|
||||
this.siteJobInstanceMap = new ConcurrentHashMap<String, ScheduledFuture<?>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy trigger method for the timer in the camel context this bean
|
||||
* monitors. Ensures this bean properly fails over between cluster members
|
||||
* as needed.
|
||||
*/
|
||||
public void activateService() {
|
||||
activeServiceInstance = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a site's active table sharing job from the job pool.
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @param siteID
|
||||
* Site identifier for the site's job to stop.
|
||||
* @see
|
||||
* com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#deactivateSite(java.
|
||||
* lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void deactivateSite(final String siteID) {
|
||||
ScheduledFuture<?> siteJob = siteJobInstanceMap.remove(siteID);
|
||||
if (siteJob != null) {
|
||||
|
@ -198,17 +189,19 @@ public final class FetchActiveTableSrv implements IContextStateProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a site's active table sharing job to the job pool.
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @param siteID
|
||||
* Site identifier for the site's job to add to job pool.
|
||||
* @param gfeConfig
|
||||
* {@code IFPServerConfig} for the site.
|
||||
* @see
|
||||
* com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#activateSite(java.lang
|
||||
* .String, com.raytheon.edex.plugin.gfe.config.IFPServerConfig)
|
||||
*/
|
||||
@Override
|
||||
public void activateSite(final String siteID,
|
||||
final IFPServerConfig gfeConfig) {
|
||||
if (activeServiceInstance && (!siteJobInstanceMap.containsKey(siteID))) {
|
||||
EDEXUtil.waitForRunning();
|
||||
if ((gfeConfig.tableFetchTime() > 0)
|
||||
&& (!siteJobInstanceMap.containsKey(siteID))) {
|
||||
FetchATJobConfig jobConfig = new FetchATJobConfig(siteID, gfeConfig);
|
||||
|
||||
statusHandler.info("Activating FetchAT for " + siteID);
|
||||
|
@ -226,6 +219,10 @@ public final class FetchActiveTableSrv implements IContextStateProcessor {
|
|||
"Unable to submit fetchAT job for execution:", e);
|
||||
siteJobInstanceMap.remove(siteID);
|
||||
}
|
||||
} else {
|
||||
statusHandler
|
||||
.info("Skipping activation of active table sharing for site "
|
||||
+ siteID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,53 +279,35 @@ public final class FetchActiveTableSrv implements IContextStateProcessor {
|
|||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#preStart()
|
||||
* @see com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#startup()
|
||||
*/
|
||||
@Override
|
||||
public void preStart() {
|
||||
public void startup() {
|
||||
statusHandler.info("Initializing FetchATSrv...");
|
||||
|
||||
activeServiceInstance = true;
|
||||
jobExecutor = Executors.newScheduledThreadPool(1);
|
||||
}
|
||||
|
||||
for (IFPServer ifpServer : IFPServer.getActiveServers()) {
|
||||
IFPServerConfig config = ifpServer.getConfig();
|
||||
if ((config.requestISC()) && (config.tableFetchTime() > 0)) {
|
||||
activateSite(ifpServer.getSiteId(), config);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#preShutdown()
|
||||
*/
|
||||
@Override
|
||||
public void preShutdown() {
|
||||
statusHandler.info("Shutting down FetchATSrv...");
|
||||
if (jobExecutor != null) {
|
||||
jobExecutor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#postStart()
|
||||
* @see com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#postShutdown()
|
||||
*/
|
||||
@Override
|
||||
public void postStart() {
|
||||
// no op
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#preStop()
|
||||
*/
|
||||
@Override
|
||||
public void preStop() {
|
||||
statusHandler.info("Shutting down FetchATSrv...");
|
||||
|
||||
activeServiceInstance = false;
|
||||
jobExecutor.shutdown();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#postStop()
|
||||
*/
|
||||
@Override
|
||||
public void postStop() {
|
||||
public void postShutdown() {
|
||||
jobExecutor = null;
|
||||
siteJobInstanceMap.clear();
|
||||
}
|
||||
|
|
|
@ -26,15 +26,12 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.edex.plugin.gfe.config.GridDbConfig;
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager;
|
||||
import com.raytheon.edex.plugin.gfe.server.IFPServer;
|
||||
import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
|
||||
|
@ -57,23 +54,25 @@ import com.raytheon.uf.common.util.FileUtil;
|
|||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 07/14/09 1995 bphillip Initial creation
|
||||
* Mar 14, 2013 1794 djohnson FileUtil.listFiles now returns List.
|
||||
* 06/13/13 2044 randerso Refactored to use IFPServer
|
||||
* Sep 05, 2013 2307 dgilling Use better PythonScript constructor.
|
||||
* Oct 16, 2013 2475 dgilling Move logic previously in IrtServer.py
|
||||
* into this class to avoid Jep memory leak.
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 14, 2009 1995 bphillip Initial creation
|
||||
* Mar 14, 2013 1794 djohnson FileUtil.listFiles now returns List.
|
||||
* Jun 13, 2013 2044 randerso Refactored to use IFPServer
|
||||
* Sep 05, 2013 2307 dgilling Use better PythonScript constructor.
|
||||
* Oct 16, 2013 2475 dgilling Move logic previously in IrtServer.py
|
||||
* into this class to avoid Jep memory leak.
|
||||
* Mar 11, 2015 4128 dgilling Refactored to match refactored IRTManager.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bphillip
|
||||
* @version 1
|
||||
* @version 1.0
|
||||
*/
|
||||
public class GfeIRT extends Thread {
|
||||
public final class GfeIRT implements Runnable {
|
||||
|
||||
/** The logger */
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
private static final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(GfeIRT.class);
|
||||
|
||||
private static final String PYTHON_INSTANCE = "irt";
|
||||
|
@ -103,30 +102,33 @@ public class GfeIRT extends Thread {
|
|||
/** The Python script object */
|
||||
private PythonScript script;
|
||||
|
||||
/**
|
||||
* Map of threads used to unregister sites from the IRT server upon shutdown
|
||||
*/
|
||||
private static Map<String, Thread> shutdownHooks = new ConcurrentHashMap<String, Thread>();
|
||||
private final IRTManager irtMgr;
|
||||
|
||||
private final String ancfUrl;
|
||||
|
||||
private final String bncfUrl;
|
||||
|
||||
/**
|
||||
* Creates a new GfeIRT object for the provided site ID
|
||||
*
|
||||
* @param siteID
|
||||
* @param siteid
|
||||
* The site ID to create the GfeIRT object for
|
||||
* @throws GfeConfigurationException
|
||||
* If the GFE configuration for the specified site could not be
|
||||
* loaded.
|
||||
* @param config
|
||||
* @param irtMgr
|
||||
*/
|
||||
public GfeIRT(String siteid, IFPServerConfig config)
|
||||
throws GfeConfigurationException {
|
||||
this.setDaemon(true);
|
||||
public GfeIRT(String siteid, IFPServerConfig config, IRTManager irtMgr) {
|
||||
this.siteID = siteid;
|
||||
this.mhsID = config.getMhsid();
|
||||
|
||||
this.irtMgr = irtMgr;
|
||||
|
||||
this.serverHost = config.getServerHost();
|
||||
this.serverPort = config.getRpcPort();
|
||||
this.serverProtocol = config.getProtocolVersion();
|
||||
|
||||
this.ancfUrl = config.iscRoutingTableAddress().get("ANCF");
|
||||
this.bncfUrl = config.iscRoutingTableAddress().get("BNCF");
|
||||
|
||||
GridLocation domain = config.dbDomain();
|
||||
|
||||
this.gridProj = domain.getProjection().getProjectionID().toString();
|
||||
|
@ -188,23 +190,10 @@ public class GfeIRT extends Thread {
|
|||
}
|
||||
config.setRequestedISCsites(this.iscWfosWanted);
|
||||
}
|
||||
|
||||
Thread hook = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
statusHandler.info("Unregistering site [" + siteID
|
||||
+ "] from IRT server...");
|
||||
IRTManager.getInstance().disableISC(mhsID, siteID);
|
||||
statusHandler.info("Site [" + siteID + "] unregistered!");
|
||||
}
|
||||
};
|
||||
java.lang.Runtime.getRuntime().addShutdownHook(hook);
|
||||
shutdownHooks.put(mhsID + siteID, hook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||
LocalizationContext cx = pathMgr.getContext(
|
||||
|
@ -215,30 +204,29 @@ public class GfeIRT extends Thread {
|
|||
String includePath = PyUtil.buildJepIncludePath(
|
||||
GfePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
GfePyIncludeUtil.getIscScriptsIncludePath(),
|
||||
GfePyIncludeUtil.getGfeConfigIncludePath(this.siteID));
|
||||
this.script = new PythonScript(scriptPath, includePath, getClass()
|
||||
GfePyIncludeUtil.getGfeConfigIncludePath(siteID));
|
||||
script = new PythonScript(scriptPath, includePath, getClass()
|
||||
.getClassLoader());
|
||||
|
||||
IFPServerConfig config = IFPServerConfigManager
|
||||
.getServerConfig(siteID);
|
||||
Map<String, Object> initArgs = new HashMap<String, Object>(2, 1f);
|
||||
initArgs.put("ancfURL", config.iscRoutingTableAddress().get("ANCF"));
|
||||
initArgs.put("bncfURL", config.iscRoutingTableAddress().get("BNCF"));
|
||||
this.script.instantiatePythonClass(PYTHON_INSTANCE, "IrtAccess",
|
||||
initArgs.put("ancfURL", ancfUrl);
|
||||
initArgs.put("bncfURL", bncfUrl);
|
||||
script.instantiatePythonClass(PYTHON_INSTANCE, "IrtAccess",
|
||||
initArgs);
|
||||
} catch (GfeConfigurationException e) {
|
||||
throw new RuntimeException("Could not load GFE configuration", e);
|
||||
} catch (JepException e) {
|
||||
throw new RuntimeException(
|
||||
"Could not instantiate IRT python script instance", e);
|
||||
statusHandler.error(
|
||||
"Could not instantiate IRT python script instance for site "
|
||||
+ siteID, e);
|
||||
statusHandler.error("ISC is disabled for site " + siteID);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// upon any overall failure, start thread over
|
||||
while (IRTManager.getInstance().isRegistered(mhsID, siteID)) {
|
||||
while (irtMgr.shouldRegister(siteID)) {
|
||||
try {
|
||||
// do initial registration, keep trying until successful
|
||||
while (IRTManager.getInstance().isRegistered(mhsID, siteID)) {
|
||||
while (irtMgr.shouldRegister(siteID)) {
|
||||
statusHandler
|
||||
.info("performing initial IRT registration.");
|
||||
|
||||
|
@ -259,11 +247,10 @@ public class GfeIRT extends Thread {
|
|||
|
||||
if (okay) {
|
||||
break;
|
||||
} else if (!IRTManager.getInstance().isRegistered(
|
||||
mhsID, siteID)) {
|
||||
} else if (!irtMgr.shouldRegister(siteID)) {
|
||||
break; // exit processing loop
|
||||
} else {
|
||||
sleep(3 * TimeUtil.MILLIS_PER_SECOND);
|
||||
Thread.sleep(3 * TimeUtil.MILLIS_PER_SECOND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,8 +258,9 @@ public class GfeIRT extends Thread {
|
|||
// for re-register every few seconds, check the StopIRT flag
|
||||
// every few seconds
|
||||
statusHandler.info("initial IRT registration complete.");
|
||||
while (IRTManager.getInstance().isRegistered(mhsID, siteID)) {
|
||||
sleep(3 * TimeUtil.MILLIS_PER_SECOND); // wait 3 seconds
|
||||
while (irtMgr.shouldRegister(siteID)) {
|
||||
Thread.sleep(3 * TimeUtil.MILLIS_PER_SECOND); // wait 3
|
||||
// seconds
|
||||
|
||||
Boolean status1 = (Boolean) script.execute(
|
||||
"checkForReregister", PYTHON_INSTANCE, null);
|
||||
|
@ -302,23 +290,4 @@ public class GfeIRT extends Thread {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the site's entry from the shutdown hook map
|
||||
*
|
||||
* @param mhsid
|
||||
* The MHS ID of the site
|
||||
* @param siteid
|
||||
* The Site ID of the site
|
||||
*/
|
||||
public void removeShutdownHook(String mhsid, String siteid) {
|
||||
if (shutdownHooks.containsKey(mhsid + siteid)) {
|
||||
Thread hook = shutdownHooks.get(mhsid + siteid);
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(hook);
|
||||
} catch (IllegalStateException e) {
|
||||
// Ignore. Shutdown in progress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* 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.edex.plugin.gfe.isc;
|
||||
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
|
||||
|
||||
/**
|
||||
* An interface for beans that provide ISC services for
|
||||
* {@code IscServiceProvider}. This bean, once registered with
|
||||
* {@code IscServiceProvider} will run on only one of the available EDEX cluster
|
||||
* nodes. The {@code IscServiceProvider} ensures that dependent services all run
|
||||
* together on the same node.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 11, 2015 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public interface IISCServiceBean {
|
||||
|
||||
/**
|
||||
* Called upon activation of a new GFE site. Will only trigger on the
|
||||
* cluster node currently hosting ISC services and if
|
||||
* {@code gfeConfig.requestISC()} returns {@code true}.
|
||||
*
|
||||
* @param siteID
|
||||
* Site identifier to activate ISC services for.
|
||||
* @param gfeConfig
|
||||
* Configuration data for this site.
|
||||
*/
|
||||
void activateSite(final String siteID, final IFPServerConfig gfeConfig);
|
||||
|
||||
/**
|
||||
* Called upon deactivation of a GFE site. Will only trigger on the cluster
|
||||
* node currently hosting ISC services.
|
||||
*
|
||||
* @param siteID
|
||||
* Site identifier to deactivate ISC services for.
|
||||
*/
|
||||
void deactivateSite(final String siteID);
|
||||
|
||||
/**
|
||||
* The startup method for this bean. Should be used to initialize heavy
|
||||
* objects that shouldn't be allowed to run on both cluster nodes to
|
||||
* conserve system resources.
|
||||
*/
|
||||
void startup();
|
||||
|
||||
/**
|
||||
* Called to begin the shutdown process for this bean. Recommend using this
|
||||
* method to cancel any asynchronous tasks this bean may be running.
|
||||
* <p>
|
||||
* Note that this method does not require that the startup method has
|
||||
* previously been called so ensure this code does not rely on any behaviors
|
||||
* of that method.
|
||||
*/
|
||||
void preShutdown();
|
||||
|
||||
/**
|
||||
* Called after {@code IscServiceProvider} has completed its shutdown. One
|
||||
* last chance to cleanup any resources in use by this bean.
|
||||
* <p>
|
||||
* Note that this method does not require that the startup method has
|
||||
* previously been called so ensure this code does not rely on any behaviors
|
||||
* of that method.
|
||||
*/
|
||||
void postShutdown();
|
||||
}
|
|
@ -20,15 +20,21 @@
|
|||
|
||||
package com.raytheon.edex.plugin.gfe.isc;
|
||||
|
||||
import java.lang.Thread.State;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
||||
/**
|
||||
* Manages interactions for the IRT server used with the GFE ISC capability
|
||||
|
@ -41,89 +47,138 @@ import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* 08/10/09 1995 bphillip Initial creation
|
||||
* 06/13/13 2044 randerso Refactored to use IFPServer
|
||||
* 03/11/15 4128 dgilling Refactored to use ISCServiceProvider.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bphillip
|
||||
* @version 1
|
||||
*/
|
||||
public class IRTManager {
|
||||
public final class IRTManager {
|
||||
|
||||
/** The logger */
|
||||
protected transient Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/** The singleton instance */
|
||||
private static IRTManager instance;
|
||||
private final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(IRTManager.class);
|
||||
|
||||
/** Map of active IRT connections keyed by site */
|
||||
private Map<String, GfeIRT> irtMap;
|
||||
private final ConcurrentMap<String, Future<?>> irtMap;
|
||||
|
||||
/**
|
||||
* Gets the singleton instance of the IRTManager
|
||||
*
|
||||
* @return The singleton instance of the IRTManager
|
||||
*/
|
||||
public static synchronized IRTManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new IRTManager();
|
||||
}
|
||||
/** List of valid ISC sites. */
|
||||
private final Set<String> registeredSiteIDs;
|
||||
|
||||
return instance;
|
||||
}
|
||||
private ExecutorService jobExecutor;
|
||||
|
||||
/**
|
||||
* Constructs the singleton instance of the IRT Manager
|
||||
*/
|
||||
private IRTManager() {
|
||||
irtMap = new ConcurrentHashMap<String, GfeIRT>();
|
||||
public IRTManager() {
|
||||
this.irtMap = new ConcurrentHashMap<>();
|
||||
this.registeredSiteIDs = new CopyOnWriteArraySet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables ISC functionality for a site
|
||||
* Determines whether the specified site should continue to (re-) register
|
||||
* with IRT.
|
||||
*
|
||||
* @param siteID
|
||||
* The site to activate ISC functionality for
|
||||
* @param config
|
||||
* server configuration
|
||||
* @throws GfeException
|
||||
* If the ISC functionality cannot be activated
|
||||
* Site identifier to check for.
|
||||
* @return {@code true} if the site should continue registration with IRT.
|
||||
* {@code false} if not.
|
||||
*/
|
||||
public void enableISC(String siteID, IFPServerConfig config)
|
||||
throws GfeException {
|
||||
|
||||
String mhsID = config.getMhsid();
|
||||
if (!irtMap.containsKey(mhsID + "--" + siteID)) {
|
||||
irtMap.put(mhsID + "--" + siteID, new GfeIRT(siteID, config));
|
||||
}
|
||||
|
||||
logger.info("Starting IRT registration thread for site [" + siteID
|
||||
+ "]");
|
||||
irtMap.get(mhsID + "--" + siteID).start();
|
||||
public boolean shouldRegister(final String siteID) {
|
||||
/*
|
||||
* We use this separate Set to hold site IDs to avoid a race condition.
|
||||
* While it would be more convenient to use the keys of the irtMap to
|
||||
* maintain the list of sites that should be attempting to register with
|
||||
* IRT, this will cause a race condition when the Runnable's attempt to
|
||||
* call this method. It's likely the job will hit the shouldRegister()
|
||||
* check before the Future has been added to the Map and thus fail to
|
||||
* ever attempt registration with IRT.
|
||||
*/
|
||||
return registeredSiteIDs.contains(siteID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables ISC functionality for a site
|
||||
* Register the given site with the IRT server.
|
||||
*
|
||||
* @param siteID
|
||||
* The site to disable ISC functionality for
|
||||
* Site identifier for the site to register with the IRT server.
|
||||
* @param gfeConfig
|
||||
* The {@code IFPServerConfig} configuration data for the site.
|
||||
*/
|
||||
public void disableISC(String mhsID, String siteID) {
|
||||
GfeIRT gfeIrt = null;
|
||||
String irtKey = mhsID + "--" + siteID;
|
||||
gfeIrt = irtMap.remove(irtKey);
|
||||
if (gfeIrt != null) {
|
||||
if (gfeIrt.getState() != null) {
|
||||
while (!gfeIrt.getState().equals(State.TERMINATED)) {
|
||||
}
|
||||
public void activateSite(String siteID, IFPServerConfig gfeConfig) {
|
||||
if (!irtMap.containsKey(siteID)) {
|
||||
statusHandler.info("Starting IRT registration thread for site ["
|
||||
+ siteID + "]");
|
||||
|
||||
registeredSiteIDs.add(siteID);
|
||||
Runnable job = constructJob(siteID, gfeConfig);
|
||||
|
||||
try {
|
||||
Future<?> future = jobExecutor.submit(job);
|
||||
irtMap.put(siteID, future);
|
||||
} catch (RejectedExecutionException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Unable to submit fetchAT job for execution:", e);
|
||||
irtMap.remove(siteID);
|
||||
}
|
||||
// Remove the shutdown hook so an unregister is not attempted upon
|
||||
// shutdown
|
||||
gfeIrt.removeShutdownHook(mhsID, siteID);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRegistered(String mhsID, String siteID) {
|
||||
boolean registered = irtMap.containsKey(mhsID + "--" + siteID);
|
||||
return registered;
|
||||
private GfeIRT constructJob(final String siteID,
|
||||
final IFPServerConfig config) {
|
||||
return new GfeIRT(siteID, config, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the given site with the IRT server.
|
||||
*
|
||||
* @param siteID
|
||||
* Site identifier of the site to unregister.
|
||||
*/
|
||||
public void deactivateSite(String siteID) {
|
||||
registeredSiteIDs.remove(siteID);
|
||||
Future<?> job = irtMap.remove(siteID);
|
||||
if (job != null) {
|
||||
statusHandler.info("Deactivating IRT registration thread for "
|
||||
+ siteID);
|
||||
job.cancel(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Startup hook for this bean. Initializes job pool.
|
||||
*/
|
||||
public void preStart() {
|
||||
statusHandler.info("Initializing IRTManager...");
|
||||
|
||||
jobExecutor = Executors.newCachedThreadPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* Preliminary shutdown hook for this bean. Stops all running IRT
|
||||
* registration jobs and initiates shutdown of the job pool.
|
||||
*/
|
||||
public void preStop() {
|
||||
statusHandler.info("Shutting down IRTManager...");
|
||||
|
||||
Collection<String> siteIds = new ArrayList<>(registeredSiteIDs);
|
||||
for (String siteId : siteIds) {
|
||||
deactivateSite(siteId);
|
||||
}
|
||||
|
||||
if (jobExecutor != null) {
|
||||
jobExecutor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown completion hook for this bean. Clears all saved state for this
|
||||
* bean.
|
||||
*/
|
||||
public void postStop() {
|
||||
jobExecutor = null;
|
||||
irtMap.clear();
|
||||
registeredSiteIDs.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
/**
|
||||
* 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.edex.plugin.gfe.isc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
|
||||
import com.raytheon.edex.plugin.gfe.server.IFPServer;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.edex.core.IContextStateProcessor;
|
||||
|
||||
/**
|
||||
* An {@code IContextStateProcessor} implementation for ISC beans. Ensures that
|
||||
* all ISC services are running on the same cluster node together.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 11, 2015 #4128 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class IscServiceProvider implements IContextStateProcessor {
|
||||
|
||||
private final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(IscServiceProvider.class);
|
||||
|
||||
private volatile boolean activeInstance;
|
||||
|
||||
private final Collection<IISCServiceBean> iscBeans;
|
||||
|
||||
private final ExecutorService jobThreads;
|
||||
|
||||
private final IRTManager irtManager;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public IscServiceProvider() {
|
||||
this.iscBeans = new ArrayList<>();
|
||||
this.activeInstance = false;
|
||||
this.jobThreads = Executors.newCachedThreadPool();
|
||||
this.irtManager = new IRTManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new {@code IISCServiceBean} instance with this class. Beans
|
||||
* can only be added and never removed.
|
||||
*
|
||||
* @param iscServiceBean
|
||||
* The bean to register.
|
||||
* @return The bean that was registered.
|
||||
*/
|
||||
public IISCServiceBean addISCService(final IISCServiceBean iscServiceBean) {
|
||||
iscBeans.add(iscServiceBean);
|
||||
return iscServiceBean;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#preStart()
|
||||
*/
|
||||
@Override
|
||||
public void preStart() {
|
||||
activeInstance = true;
|
||||
|
||||
irtManager.preStart();
|
||||
for (IISCServiceBean iscBean : iscBeans) {
|
||||
iscBean.startup();
|
||||
}
|
||||
|
||||
for (IFPServer ifpServer : IFPServer.getActiveServers()) {
|
||||
activateSite(ifpServer.getSiteId(), ifpServer.getConfig());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#postStart()
|
||||
*/
|
||||
@Override
|
||||
public void postStart() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#preStop()
|
||||
*/
|
||||
@Override
|
||||
public void preStop() {
|
||||
irtManager.preStop();
|
||||
for (IISCServiceBean iscBean : iscBeans) {
|
||||
iscBean.preShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.edex.core.IContextStateProcessor#postStop()
|
||||
*/
|
||||
@Override
|
||||
public void postStop() {
|
||||
irtManager.postStop();
|
||||
for (IISCServiceBean iscBean : iscBeans) {
|
||||
iscBean.postShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy trigger method for the timer in the camel context this bean
|
||||
* monitors. Ensures this bean properly fails over between cluster members
|
||||
* as needed.
|
||||
*/
|
||||
public void activateInstance() {
|
||||
activeInstance = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the ISC services for the given site. All registered beans will
|
||||
* have their {@code activateSite} method called if this instance is running
|
||||
* on the designated ISC cluster node.
|
||||
*
|
||||
* @param siteID
|
||||
* Site identifier to activate ISC services for.
|
||||
* @param config
|
||||
* Configuration data for this site.
|
||||
*/
|
||||
public void activateSite(final String siteID, final IFPServerConfig config) {
|
||||
statusHandler.info("Checking ISC configuration for site " + siteID);
|
||||
|
||||
if (config.requestISC()) {
|
||||
if (activeInstance) {
|
||||
statusHandler.info("Enabling ISC for site " + siteID);
|
||||
|
||||
irtManager.activateSite(siteID, config);
|
||||
|
||||
for (final IISCServiceBean bean : iscBeans) {
|
||||
Runnable activationJob = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
bean.activateSite(siteID, config);
|
||||
} catch (Throwable t) {
|
||||
statusHandler.error(
|
||||
"Unhandled RuntimeException thrown while activating service "
|
||||
+ bean.getClass()
|
||||
+ " for site " + siteID, t);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jobThreads.submit(activationJob);
|
||||
}
|
||||
|
||||
} else {
|
||||
statusHandler
|
||||
.info("ISC Enabled but will use another EDEX instance");
|
||||
}
|
||||
} else {
|
||||
statusHandler.info("ISC is not enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the ISC services for the given site. All registered beans
|
||||
* will have their {@code deactivateSite} method called if this instance is
|
||||
* running on the designated ISC cluster node.
|
||||
*
|
||||
* @param siteID
|
||||
* Site identifier to deactivate ISC services for.
|
||||
*/
|
||||
public void deactivateSite(final String siteID) {
|
||||
if (activeInstance) {
|
||||
irtManager.deactivateSite(siteID);
|
||||
|
||||
for (final IISCServiceBean bean : iscBeans) {
|
||||
Runnable deactivationJob = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
bean.deactivateSite(siteID);
|
||||
} catch (Throwable t) {
|
||||
statusHandler.error(
|
||||
"Unhandled RuntimeException thrown while deactivating service "
|
||||
+ bean.getClass() + " for site "
|
||||
+ siteID, t);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jobThreads.submit(deactivationJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* 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.edex.plugin.gfe.isc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
|
||||
import com.raytheon.uf.common.localization.IPathManager;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||
import com.raytheon.uf.common.python.PyUtil;
|
||||
import com.raytheon.uf.common.python.PythonScript;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.util.FileUtil;
|
||||
import com.raytheon.uf.edex.activetable.ActiveTablePyIncludeUtil;
|
||||
import com.raytheon.uf.edex.core.EDEXUtil;
|
||||
|
||||
/**
|
||||
* Bean to run requestTCV at GFE site activation time.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 11, 2015 #4128 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class RequestTCVSrv implements IISCServiceBean {
|
||||
|
||||
private final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(RequestTCVSrv.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#activateSite(java.lang
|
||||
* .String, com.raytheon.edex.plugin.gfe.config.IFPServerConfig)
|
||||
*/
|
||||
@Override
|
||||
public void activateSite(String siteID, IFPServerConfig gfeConfig) {
|
||||
EDEXUtil.waitForRunning();
|
||||
requestTCVFiles(siteID, gfeConfig);
|
||||
}
|
||||
|
||||
private void requestTCVFiles(String siteId, IFPServerConfig config) {
|
||||
statusHandler.info("Running requestTCV for site " + siteId);
|
||||
|
||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||
LocalizationContext commonBaseCx = pathMgr.getContext(
|
||||
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
|
||||
String scriptPath = pathMgr.getFile(commonBaseCx,
|
||||
FileUtil.join(ActiveTablePyIncludeUtil.VTEC, "requestTCV.py"))
|
||||
.getPath();
|
||||
|
||||
String pythonIncludePath = PyUtil.buildJepIncludePath(
|
||||
ActiveTablePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
ActiveTablePyIncludeUtil.getCommonGfeIncludePath(),
|
||||
ActiveTablePyIncludeUtil.getVtecIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getIscScriptsIncludePath());
|
||||
|
||||
PythonScript script = null;
|
||||
try {
|
||||
script = new PythonScript(scriptPath, pythonIncludePath, this
|
||||
.getClass().getClassLoader());
|
||||
|
||||
try {
|
||||
Map<String, Object> argMap = new HashMap<String, Object>();
|
||||
argMap.put("siteID", siteId);
|
||||
argMap.put("config", config);
|
||||
script.execute("runFromJava", argMap);
|
||||
} catch (JepException e) {
|
||||
statusHandler.error("Error executing requestTCV.", e);
|
||||
}
|
||||
} catch (JepException e) {
|
||||
statusHandler
|
||||
.error("Unable to instantiate requestTCV python script object.",
|
||||
e);
|
||||
} finally {
|
||||
if (script != null) {
|
||||
script.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#deactivateSite(java.
|
||||
* lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void deactivateSite(String siteID) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#startup()
|
||||
*/
|
||||
@Override
|
||||
public void startup() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#preShutdown()
|
||||
*/
|
||||
@Override
|
||||
public void preShutdown() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.edex.plugin.gfe.isc.IISCServiceBean#postShutdown()
|
||||
*/
|
||||
@Override
|
||||
public void postShutdown() {
|
||||
// no-op
|
||||
}
|
||||
}
|
|
@ -30,7 +30,6 @@ import java.util.Set;
|
|||
import com.raytheon.edex.plugin.gfe.cache.gridlocations.GridLocationCache;
|
||||
import com.raytheon.edex.plugin.gfe.config.IFPServerConfig;
|
||||
import com.raytheon.edex.plugin.gfe.db.dao.IscSendRecordDao;
|
||||
import com.raytheon.edex.plugin.gfe.isc.IRTManager;
|
||||
import com.raytheon.edex.plugin.gfe.reference.MapManager;
|
||||
import com.raytheon.edex.plugin.gfe.server.database.NetCDFDatabaseManager;
|
||||
import com.raytheon.edex.plugin.gfe.server.database.TopoDatabaseManager;
|
||||
|
@ -46,7 +45,6 @@ import com.raytheon.uf.common.dataplugin.message.DataURINotificationMessage;
|
|||
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
|
||||
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.edex.database.DataAccessLayerException;
|
||||
|
||||
/**
|
||||
|
@ -63,6 +61,7 @@ import com.raytheon.uf.edex.database.DataAccessLayerException;
|
|||
* May 30, 2013 #2044 randerso Initial creation
|
||||
* Nov 20, 2013 #2331 randerso Added getTopoData method
|
||||
* Oct 07, 2014 #3684 randerso Restructured IFPServer start up
|
||||
* Mar 11, 2015 #4128 dgilling Remove unregister from IRT to IRTManager.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -210,16 +209,11 @@ public class IFPServer {
|
|||
}
|
||||
|
||||
private void dispose() {
|
||||
if (config.requestISC()) {
|
||||
IRTManager.getInstance().disableISC(config.getMhsid(), siteId);
|
||||
}
|
||||
|
||||
try {
|
||||
new IscSendRecordDao().deleteForSite(siteId);
|
||||
} catch (DataAccessLayerException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Could not clear IscSendRecords for site " + siteId
|
||||
+ " from queue.", e);
|
||||
statusHandler.error("Could not clear IscSendRecords for site "
|
||||
+ siteId + " from queue.", e);
|
||||
}
|
||||
|
||||
// TODO necessary?
|
||||
|
|
|
@ -144,10 +144,10 @@ public class ClearGfeOrphanedLocks {
|
|||
lockList = (List<Lock>) lockMgr.getAllLocks(siteId);
|
||||
// find orphaned locks and break them
|
||||
breakLocks(clients, lockList, lockMgr, siteId);
|
||||
return;
|
||||
} catch (GfeException e) {
|
||||
statusHandler.error("Error retrieving all locks", e);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# 12/05/14 4953 randerso Changed to use LocalizationSupport
|
||||
# 03/10/2015 #4129 randerso Fixed error logging
|
||||
#
|
||||
##
|
||||
|
||||
|
@ -225,7 +226,7 @@ def createAreaDictionary(outputDir, mapDict):
|
|||
|
||||
|
||||
if areadict.has_key(ean) and d != areadict[ean]:
|
||||
LogStream.logDiag("Mismatch of definitions in " +\
|
||||
LogStream.logProblem("Mismatch of definitions in " +\
|
||||
"AreaDictionary creation. EditAreaName=", ean,
|
||||
"AreaDict=\n", areadict[ean], "\nIgnored=\n", d)
|
||||
else:
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
# ------------ ---------- ----------- --------------------------
|
||||
# 12/10/14 #4953 randerso Cleaned up imports,
|
||||
# improved spawning of shell cmd
|
||||
# 03/10/2015 #4129 randerso Refactored server selection code into a reusable method
|
||||
#
|
||||
##
|
||||
|
||||
|
@ -49,12 +50,15 @@ import iscUtil
|
|||
class IrtAccess():
|
||||
|
||||
#Constructor taking the web URL for the ISC Routing Table
|
||||
def __init__(self, ancfURL=None, bncfURL=None):
|
||||
def __init__(self, ancfURL=None, bncfURL=None, logger=None):
|
||||
self.__addrs = {}
|
||||
self.__addrs['ANCF'] = ancfURL
|
||||
self.__addrs['BNCF'] = bncfURL
|
||||
self.__registered = None #flag to indicate whether we registered
|
||||
self.__logger=iscUtil.getLogger("irtAccess","irtServer.log")
|
||||
if logger is not None:
|
||||
self.__logger=logger
|
||||
else:
|
||||
self.__logger=iscUtil.getLogger("irtAccess","irtServer.log")
|
||||
|
||||
def logEvent(self,*msg):
|
||||
self.__logger.info(iscUtil.tupleToString(*msg))
|
||||
|
@ -527,3 +531,118 @@ class IrtAccess():
|
|||
s = "mhs=" + mhsid + ",host=" + host + ",port=" + port +\
|
||||
",proto=" + protocol + ",site=" + site
|
||||
return s
|
||||
|
||||
def createDestinationXML(self, destSites, requestingServer):
|
||||
#--------------------------------------------------------------------
|
||||
# Assemble XML source/destination document
|
||||
#--------------------------------------------------------------------
|
||||
iscE = ElementTree.Element('isc')
|
||||
self.addSourceXML(iscE, requestingServer)
|
||||
self.logEvent("Requesting Server:", self.printServerInfo(requestingServer))
|
||||
|
||||
# who is running the domains requested?
|
||||
status, xml = self.getServers(destSites)
|
||||
if not status:
|
||||
raise Exception('Failure to getServers from IRT')
|
||||
|
||||
# decode the XML
|
||||
try:
|
||||
serverTree = ElementTree.ElementTree(ElementTree.XML(xml))
|
||||
serversE = serverTree.getroot()
|
||||
except:
|
||||
self.logException("Malformed XML from getServers()")
|
||||
raise
|
||||
|
||||
if serversE.tag != "servers":
|
||||
raise Exception("Servers packet missing from web server")
|
||||
|
||||
# process each requested domain returned to us
|
||||
msgSendDest = []
|
||||
chosenServers = []
|
||||
matchingServers = []
|
||||
for domainE in serversE:
|
||||
if domainE.tag != "domain":
|
||||
continue
|
||||
|
||||
domain = domainE.get('site')
|
||||
servers = [] #list of servers for this domain
|
||||
|
||||
# decode each server in the domain
|
||||
for addressE in domainE.getchildren():
|
||||
info = self.decodeXMLAddress(addressE)
|
||||
if info is None:
|
||||
continue #not address tag
|
||||
servers.append(info)
|
||||
matchingServers.append(info)
|
||||
|
||||
# server search list in priority. The px3 entries are used for
|
||||
# dual domain for AFC.
|
||||
hp = [('dx4','98000000'),('px3', '98000000'), ('dx4','98000001'),
|
||||
('px3', '98000001')]
|
||||
|
||||
# choose one server from this domain, find first dx4, 98000000
|
||||
# try to use one with the same mhsidDest as the site, which
|
||||
# would be the primary operational GFE. Note that the px3 entries
|
||||
# are for AFC.
|
||||
found = False
|
||||
for matchServer, matchPort in hp:
|
||||
if found:
|
||||
break
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort and server['mhsid'] == domain:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# find first dx4, 98000000, but perhaps a different mhsid
|
||||
# this is probably not the primary operational GFE
|
||||
for matchServer, matchPort in hp:
|
||||
if found:
|
||||
break
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# if didn't find standard one, then take the first one, but don't
|
||||
# take ourselves unless we are the only one.
|
||||
if not found and servers:
|
||||
for server in servers:
|
||||
if server['mhsid'] != requestingServer['mhsid'] \
|
||||
and server['host'] != requestingServer['host'] \
|
||||
and server['port'] != requestingServer['port'] \
|
||||
and server['site'] != requestingServer['site']:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break;
|
||||
|
||||
if not found:
|
||||
chosenServers.append(servers[0])
|
||||
if servers[0]['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(servers[0]['mhsid'])
|
||||
|
||||
|
||||
# Display the set of matching servers
|
||||
s = "Matching Servers:"
|
||||
for x in matchingServers:
|
||||
s += "\n" + self.printServerInfo(x)
|
||||
self.logEvent(s)
|
||||
|
||||
# Display the chosen set of servers
|
||||
s = "Chosen Servers:"
|
||||
for x in chosenServers:
|
||||
s += "\n" + self.printServerInfo(x)
|
||||
self.logEvent(s)
|
||||
|
||||
self.addDestinationXML(iscE, chosenServers)
|
||||
|
||||
return msgSendDest, iscE
|
||||
|
|
|
@ -24,6 +24,7 @@ import LogStream, tempfile, os, sys, JUtil, subprocess, traceback, errno
|
|||
import time, copy, string, iscUtil
|
||||
|
||||
from com.raytheon.edex.plugin.gfe.isc import IRTManager
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
|
||||
#
|
||||
|
@ -47,6 +48,8 @@ from com.raytheon.edex.plugin.gfe.isc import IRTManager
|
|||
# registration with IRT.
|
||||
# 12/08/2014 4953 randerso Added support for sending/receiving TCV files
|
||||
# Additional code clean up
|
||||
# 03/05/2015 4129 randerso Fix exception handling on subprocess calls
|
||||
# Fixed error when no TCV files were found
|
||||
#
|
||||
##
|
||||
PURGE_AGE = 30 * 24 * 60 * 60 # 30 days in seconds
|
||||
|
@ -157,9 +160,11 @@ def getVTECActiveTable(dataFile, xmlPacket):
|
|||
args.append(fnameXML)
|
||||
try:
|
||||
output = subprocess.check_output(args, stderr=subprocess.STDOUT)
|
||||
logEvent("sendAT command output: ", output)
|
||||
except subprocess.CalledProcessError as e:
|
||||
logProblem("sendAT returned error code: ", e.returncode, e.output)
|
||||
except:
|
||||
logProblem("Error executing sendAT: ", traceback.format_exc())
|
||||
logEvent("sendAT command output: ", output)
|
||||
|
||||
#when we receive a requested active table from another site, this function
|
||||
#is called from iscDataRec
|
||||
|
@ -191,9 +196,11 @@ def putVTECActiveTable(dataFile, xmlPacket):
|
|||
args.append(fnameXML)
|
||||
try:
|
||||
output = subprocess.check_output(args, stderr=subprocess.STDOUT)
|
||||
logEvent("ingestAT command output: ", output)
|
||||
except subprocess.CalledProcessError as e:
|
||||
logProblem("ingestAT returned error code: ", e.returncode, e.output)
|
||||
except:
|
||||
logProblem("Error executing ingestAT: ", traceback.format_exc())
|
||||
logEvent("ingesAT command output: ", output)
|
||||
|
||||
def putTCVFiles(siteID, tarFile):
|
||||
import LocalizationSupport
|
||||
|
@ -313,21 +320,24 @@ def getTCVFiles(ourMhsID, srcServer, destE):
|
|||
fname = fp.name
|
||||
|
||||
try:
|
||||
TCVUtil.packageTCVFiles(localSites, fname, getLogger())
|
||||
if TCVUtil.packageTCVFiles(localSites, fname, getLogger()):
|
||||
|
||||
from xml.etree import ElementTree
|
||||
from xml.etree.ElementTree import Element, SubElement
|
||||
iscE = ElementTree.Element('isc')
|
||||
irt.addSourceXML(iscE, destServer)
|
||||
irt.addDestinationXML(iscE, [srcServer])
|
||||
|
||||
# create the XML file
|
||||
with tempfile.NamedTemporaryFile(suffix='.xml', dir=tcvProductsDir, delete=False) as fd:
|
||||
fnameXML = fd.name
|
||||
fd.write(ElementTree.tostring(iscE))
|
||||
|
||||
# send the files to srcServer
|
||||
sendMHSMessage("PUT_TCV_FILES", srcServer['mhsid'], [fname, fnameXML])
|
||||
from xml.etree import ElementTree
|
||||
from xml.etree.ElementTree import Element, SubElement
|
||||
iscE = ElementTree.Element('isc')
|
||||
irt.addSourceXML(iscE, destServer)
|
||||
irt.addDestinationXML(iscE, [srcServer])
|
||||
|
||||
# create the XML file
|
||||
with tempfile.NamedTemporaryFile(suffix='.xml', dir=tcvProductsDir, delete=False) as fd:
|
||||
fnameXML = fd.name
|
||||
fd.write(ElementTree.tostring(iscE))
|
||||
|
||||
# send the files to srcServer
|
||||
sendMHSMessage("PUT_TCV_FILES", srcServer['mhsid'], [fname, fnameXML])
|
||||
else:
|
||||
logEvent('No TCV files to send')
|
||||
|
||||
except:
|
||||
logException('Error sending TCV files for ' + str(localSites))
|
||||
|
||||
|
@ -502,14 +512,6 @@ def serviceISCRequest(dataFile):
|
|||
ServiceISCRequest.serviceRequest(JUtil.pyValToJavaObj(info['parms']),xmlDestinations,siteConfig.GFESUITE_SITEID)
|
||||
# ifpServer.serviceISCRequest(info['parms'], xmlDestinations)
|
||||
|
||||
# get servers direct call for IRT
|
||||
def irtGetServers(ancfURL, bncfURL, iscWfosWanted):
|
||||
import IrtAccess
|
||||
irt = IrtAccess.IrtAccess(ancfURL, bncfURL)
|
||||
xml = None
|
||||
status, xml = irt.getServers(iscWfosWanted)
|
||||
return xml
|
||||
|
||||
def sendMHSMessage(subject, adressees, attachments, xmtScript=None):
|
||||
# Transmit the request -- do string substitution
|
||||
import siteConfig
|
||||
|
|
|
@ -196,7 +196,7 @@ def execIscDataRec(MSGID,SUBJECT,FILES):
|
|||
elif SUBJECT == 'GET_ACTIVE_TABLE':
|
||||
IrtServer.getVTECActiveTable(dataFile, None)
|
||||
elif SUBJECT == 'GET_ACTIVE_TABLE2':
|
||||
IrtServer.getVTECActiveTable(dateFile, xmlFileBuf)
|
||||
IrtServer.getVTECActiveTable(dataFile, xmlFileBuf)
|
||||
elif SUBJECT in ['ISCGRIDS', 'ISCGRIDS2']:
|
||||
args = {"siteID": siteConfig.GFESUITE_SITEID,
|
||||
"userID": 'SITE',
|
||||
|
|
|
@ -1,275 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
##
|
||||
# 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.
|
||||
##
|
||||
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
import getopt, sys, os, time, socket, threading, SocketServer, LogStream, select
|
||||
import cPickle, stat, tempfile
|
||||
import iscDataRec
|
||||
from com.raytheon.edex.plugin.gfe.isc import IRTManager
|
||||
|
||||
#
|
||||
# Port of msg_send script
|
||||
#
|
||||
# SOFTWARE HISTORY
|
||||
#
|
||||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# 07/06/09 1995 bphillip Initial Creation.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
ISC_DATA_REC = "iscDataRec" # Assume it is on the PATH
|
||||
|
||||
class Server(object):
|
||||
|
||||
class Handler(SocketServer.StreamRequestHandler):
|
||||
def handle(self):
|
||||
func = cPickle.load(self.rfile)
|
||||
print "func: ", func
|
||||
if func == 'gettable':
|
||||
with self.server.tlock:
|
||||
msg = cPickle.dumps(self.server.table)
|
||||
self.wfile.write(msg)
|
||||
self.wfile.flush()
|
||||
elif func == 'msg_send':
|
||||
meta = cPickle.load(self.rfile)
|
||||
print "meta: ", meta
|
||||
nfiles = cPickle.load(self.rfile)
|
||||
print "nfiles: ", nfiles
|
||||
fnames = []
|
||||
while nfiles > 0:
|
||||
size = cPickle.load(self.rfile)
|
||||
print "reading: ", size
|
||||
fname = tempfile.mktemp()
|
||||
fnames.append(fname)
|
||||
fpout = open(fname, 'wb')
|
||||
while size > 0:
|
||||
buf = self.rfile.read(min(4096, size))
|
||||
fpout.write(buf)
|
||||
size = size - len(buf)
|
||||
sys.stdout.write('.')
|
||||
print "done size: ", size
|
||||
fpout.close()
|
||||
nfiles = nfiles - 1
|
||||
|
||||
iscDataRec.execIscDataRec(os.path.basename(fname), meta['subject'], fnames)
|
||||
|
||||
fnames.append(fname)
|
||||
|
||||
|
||||
def __init__(self, wanid):
|
||||
self.__shutdown = False
|
||||
self.wanid = wanid
|
||||
self.table = {}
|
||||
self.tlock = threading.Lock()
|
||||
self.tscan = time.time()
|
||||
|
||||
def discover(self):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.bind(("0.0.0.0", 10000))
|
||||
poll_interval = 1.0
|
||||
while not self.__shutdown:
|
||||
r, w, e = select.select([s], [], [], poll_interval)
|
||||
if r:
|
||||
data, addr = s.recvfrom(1024, socket.MSG_WAITALL)
|
||||
if not data:
|
||||
break
|
||||
data = cPickle.loads(data)
|
||||
if data[0] == "tcpaddr":
|
||||
with self.tlock:
|
||||
self.table[data[1]] = (addr[0], data[2], data[3])
|
||||
now = time.time()
|
||||
if now - self.tscan > 15:
|
||||
dlist = []
|
||||
for k, v in self.table.iteritems():
|
||||
if now - v[2] > 15:
|
||||
dlist.append(k)
|
||||
for k in dlist:
|
||||
del self.table[k]
|
||||
self.tscan = now
|
||||
#print "received packet: ", self.table
|
||||
|
||||
|
||||
def broadcast(self):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
s.bind(("<broadcast>", 10000))
|
||||
while not self.__shutdown:
|
||||
# msg type, wanid, host, port, time of update.
|
||||
msg = cPickle.dumps(("tcpaddr", self.wanid, self.addr[1],
|
||||
time.time()))
|
||||
s.sendto(msg, socket.MSG_WAITALL,
|
||||
("<broadcast>", 10000))
|
||||
time.sleep(5)
|
||||
|
||||
def startThreads(self):
|
||||
LogStream.logEvent("Starting Threads")
|
||||
self.t1 = threading.Thread(target=self.broadcast)
|
||||
self.t1.setDaemon(True)
|
||||
self.t1.start()
|
||||
self.t2 = threading.Thread(target=self.discover)
|
||||
self.t2.setDaemon(True)
|
||||
self.t2.start()
|
||||
|
||||
def run(self):
|
||||
LogStream.logEvent("Running with ShutDown Value:", self.__shutdown)
|
||||
tcps = SocketServer.TCPServer(('', 0), self.Handler)
|
||||
tcps.table = self.table
|
||||
tcps.tlock = self.tlock
|
||||
self.addr = tcps.server_address
|
||||
self.startThreads()
|
||||
|
||||
poll_interval = 2.0
|
||||
|
||||
while not self.__shutdown:
|
||||
r, w, e = select.select([tcps], [], [], poll_interval)
|
||||
if r:
|
||||
tcps.handle_request()
|
||||
|
||||
if IRTManager.getInstance().isRegistered(self.wanid) == False:
|
||||
LogStream.logEvent("Shutting Down GFE Socket Server for site [", self.wanid, "]...")
|
||||
self.__shutdown = True
|
||||
LogStream.logEvent("Stopping Broadcast thread for site [", self.wanid, "]...")
|
||||
self.t1.join()
|
||||
LogStream.logEvent("Stopping Discovery thread for site [", self.wanid, "]...")
|
||||
self.t2.join()
|
||||
LogStream.logEvent("GFE Socket Server for site [", self.wanid, "] shut down")
|
||||
|
||||
def serve(wanid):
|
||||
s = Server(wanid)
|
||||
s.run()
|
||||
|
||||
def gettable():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.bind(("<broadcast>", 10000))
|
||||
data, addr = s.recvfrom(1024, socket.MSG_WAITALL)
|
||||
if not data:
|
||||
pass # something bad happened.
|
||||
data = cPickle.loads(data)
|
||||
s.close()
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((addr[0], data[2]))
|
||||
s.sendall(cPickle.dumps("gettable"), socket.MSG_WAITALL)
|
||||
data = s.recv(1024, socket.MSG_WAITALL)
|
||||
data = cPickle.loads(data)
|
||||
return data
|
||||
|
||||
def msg_send(addrs, files, meta):
|
||||
|
||||
table = gettable()
|
||||
|
||||
for addr in addrs:
|
||||
if table.has_key(addr):
|
||||
host, port, time = table[addr]
|
||||
print "send to: ", host, port
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((host, port))
|
||||
s.sendall(cPickle.dumps("msg_send"), socket.MSG_WAITALL)
|
||||
s.sendall(cPickle.dumps(meta), socket.MSG_WAITALL)
|
||||
s.sendall(cPickle.dumps(len(files)), socket.MSG_WAITALL)
|
||||
fp = s.makefile('rw')
|
||||
for f in files:
|
||||
size = os.stat(f)[stat.ST_SIZE]
|
||||
print "sending: ", f, size, "(bytes)"
|
||||
s.sendall(cPickle.dumps(size), socket.MSG_WAITALL)
|
||||
fpin = open(f, 'rb')
|
||||
buf = fpin.read(4096)
|
||||
while buf != "":
|
||||
fp.write(buf)
|
||||
buf = fpin.read(4096)
|
||||
fpin.close()
|
||||
fp.flush()
|
||||
else:
|
||||
print "No table entry for", addr,"in table"
|
||||
print table
|
||||
|
||||
# typical args /awips/ops/bin/msg_send -s %SUBJECT -a %ADDRESSES -i %WMOID -c 11 -p 0 -e %ATTACHMENTS
|
||||
def msg_send_main(args):
|
||||
optlist, args = getopt.getopt(args, 'a:e:s:i:c:p:')
|
||||
addrs = []
|
||||
files = []
|
||||
meta = {}
|
||||
for opt in optlist:
|
||||
k, v = opt
|
||||
if k == '-a':
|
||||
addrs = v.split(',')
|
||||
elif k == '-e':
|
||||
files = v.split(',')
|
||||
elif k == '-s':
|
||||
meta['subject'] = v
|
||||
elif k == '-i':
|
||||
meta['wmoid'] = v
|
||||
msg_send(addrs, files, meta)
|
||||
|
||||
|
||||
def usage(status=0):
|
||||
print """Usage:
|
||||
mmhs --help (This message)
|
||||
|
||||
mmhs --server=WANID --iscdr=/path/to/iscDataRec
|
||||
(Start server mode where WANID is awips wan id)
|
||||
|
||||
msg_send [args] (run in msg_send mode [args are just like msg_send])
|
||||
"""
|
||||
sys.exit(status)
|
||||
|
||||
def main():
|
||||
global ISC_DATA_REC
|
||||
|
||||
mode = os.path.basename(sys.argv[0])
|
||||
|
||||
if mode == 'msg_send':
|
||||
msg_send_main(sys.argv[1:])
|
||||
sys.exit(0)
|
||||
|
||||
# server mode
|
||||
try:
|
||||
optlist, args = getopt.getopt(sys.argv[1:], '',
|
||||
['server=', 'iscdr='])
|
||||
|
||||
except (getopt.GetoptError, getopt.error):
|
||||
usage(1)
|
||||
|
||||
mhid = ""
|
||||
msg_args = []
|
||||
|
||||
for opt in optlist:
|
||||
k, v = opt
|
||||
if k == '--server':
|
||||
mhid = v
|
||||
elif k == '--iscdr':
|
||||
ISC_DATA_REC = v
|
||||
elif k == '--help':
|
||||
usage()
|
||||
else:
|
||||
usage(1)
|
||||
|
||||
serve(mhid)
|
||||
|
||||
#if __name__ == "__main__":
|
||||
# main()
|
|
@ -1,4 +1,4 @@
|
|||
# Version 2015.1.6-0
|
||||
# Version 2015.2.12-1
|
||||
|
||||
import GenericHazards
|
||||
import string, time, os, re, types, copy, LogStream, collections
|
||||
|
@ -9,7 +9,6 @@ import numpy
|
|||
import LocalizationSupport
|
||||
|
||||
from AbsTime import *
|
||||
from StartupDialog import IFPDialog as Dialog
|
||||
from com.raytheon.uf.common.dataplugin.gfe.reference import ReferenceData, ReferenceID
|
||||
from com.raytheon.uf.common.dataplugin.gfe.grid import Grid2DBit as JavaGrid2DBit
|
||||
AWIPS_ENVIRON = "AWIPS2"
|
||||
|
@ -100,7 +99,6 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
"_getLowestThreat": 0,
|
||||
"_setHazardImpactCategories": 0,
|
||||
"_createWholeDomainEditArea": 0,
|
||||
"_groupSegments": 0,
|
||||
"_determineHazards": 0,
|
||||
"_formatLocalTime": 0,
|
||||
"_getTimeZoneList": 0,
|
||||
|
@ -129,13 +127,13 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
"_productHeader": 0,
|
||||
"_ugcHeader": 0,
|
||||
"_processProductParts": 0,
|
||||
"_formatUGC_entries": 0,
|
||||
"_getUgcInfo": 0,
|
||||
"_createProductDictionary": 0,
|
||||
"_initializeProductDictionary": 0,
|
||||
"_formatProductDictionary": 0,
|
||||
"_getStatValue": 0,
|
||||
"_allAreas": 0,
|
||||
"_groupSegments": 0,
|
||||
"_getSegmentVTECRecordsTuples": 0,
|
||||
"_computeIntersectAreas": 0,
|
||||
"_initializeHazardsTable": 0,
|
||||
"_getHazardsTable": 0,
|
||||
|
@ -223,7 +221,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
}
|
||||
|
||||
# Definition["debug"] = 1 # turn on ALL debug messages
|
||||
# Definition["debug"] = 0 # turn off ALL debug messages
|
||||
Definition["debug"] = 0 # turn off ALL debug messages
|
||||
|
||||
def __init__(self):
|
||||
HLSTCV_Common.TextProduct.__init__(self)
|
||||
|
@ -429,13 +427,16 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
if error is not None:
|
||||
return error
|
||||
|
||||
if self._stormName is None or self._stormName.strip() == "":
|
||||
if self._stormName is None or self._stormName == "":
|
||||
return "Could not determine the storm name"
|
||||
|
||||
self._loadLastTwoAdvisories()
|
||||
if self._previousAdvisory is None and self._ImpactsAnticipated:
|
||||
return "A TCV must be transmitted before an HLS can be run"
|
||||
|
||||
if len(self._IncludedImpacts) == 0:
|
||||
return "At least one potential impact section needs to be included."
|
||||
|
||||
# Determine time ranges
|
||||
self._determineTimeRanges(argDict)
|
||||
|
||||
|
@ -452,7 +453,9 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
self._setHazardImpactCategories(threatName)
|
||||
|
||||
# Create the product dictionary and format it to create the output
|
||||
productDict = self._createProductDictionary(self._allAreas())
|
||||
productDict = self._createProductDictionary(self._productParts_HLS,
|
||||
self._allAreas(),
|
||||
areProductPartsSegmented=False)
|
||||
productOutput = self._formatProductDictionary(LegacyFormatter, productDict)
|
||||
|
||||
return productOutput
|
||||
|
@ -493,6 +496,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
statsDict['impactMin'] = None
|
||||
statsDict['impactMax'] = None
|
||||
statsDict['impactRange'] = None
|
||||
statsDict['impactRangeMax'] = None
|
||||
|
||||
self._samplingDict['WindThreat'] = copy.copy(statsDict)
|
||||
self._samplingDict['StormSurgeThreat'] = copy.copy(statsDict)
|
||||
|
@ -553,35 +557,63 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
sectionDict['impactRange'] = ""
|
||||
sectionDict['impactLib'] = []
|
||||
sectionDict['additionalImpactRange'] = []
|
||||
sectionDict['variedImpacts'] = False
|
||||
|
||||
impactMin = self._samplingDict['WindThreat']['impactMin']
|
||||
impactMax = self._samplingDict['WindThreat']['impactMax']
|
||||
impactRange = self._samplingDict['WindThreat']['impactRange']
|
||||
impactRangeMax = self._samplingDict['WindThreat']['impactRangeMax']
|
||||
inputThreatDominant = self._samplingDict['WindThreat']['inputThreatDominant']
|
||||
|
||||
# Test the simplest case first
|
||||
if impactMin == "none" and impactMax == "none":
|
||||
sectionDict['impactRange'] = impactRange
|
||||
sectionDict['variedImpacts'] = None
|
||||
productDict['windSection'] = sectionDict
|
||||
return
|
||||
|
||||
qualifier = self._getImpactsQualifier(impactMax)
|
||||
|
||||
# If there is only one impact across the entire CWA, and it is the max
|
||||
if impactMax != "none" and impactMin == impactMax and inputThreatDominant != "None":
|
||||
sectionDict['impactRange'] = "Prepare for " + impactMax + " damage across " + self._cwa_descriptor() + "."
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
sectionDict['impactRange'] = "Prepare for " + qualifier + "wind having possible " + impactMax + " impacts across " + self._cwa_descriptor() + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
sectionDict['impactRange'] = "Protect against " + qualifier + "wind having possible " + impactMax + " impacts across " + self._cwa_descriptor() + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
sectionDict['impactRange'] = "Potential impacts from the main wind event are now unfolding across " + self._cwa_descriptor() + ". Remain well sheltered from " + qualifier + "wind having " + self._frame("possible | additional") + " " + impactMax + " impacts. If realized, these impacts include:"
|
||||
else:
|
||||
sectionDict['impactRange'] = "Little to no additional wind impacts expected."
|
||||
# Handle the case where the impacts are not the same across the entire CWA
|
||||
else:
|
||||
sectionDict['variedImpacts'] = True
|
||||
sectionDict['impactRange'] = "Prepare for " + impactMax + " damage " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
sectionDict['impactRange'] = "Prepare for " + qualifier + "wind having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts in this area include:"
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
sectionDict['impactRange'] = "Protect against " + qualifier + "wind having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts in this area include:"
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
sectionDict['impactRange'] = "Potential impacts from the main wind event are now unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well sheltered from " + qualifier + "wind having " + self._frame("possible | additional") + " " + impactMax + " impacts. If realized, these impacts include:"
|
||||
else:
|
||||
sectionDict['impactRange'] = "Little to no additional wind impacts expected."
|
||||
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Wind", self._impactCategoryToThreatLevel(impactMax))
|
||||
if self._GeneralOnsetTime != "recovery":
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Wind", self._impactCategoryToThreatLevel(impactMax))
|
||||
else:
|
||||
sectionDict['impactLib'] = ["Community officials are now assessing the extent of actual wind impacts accordingly.",
|
||||
"Emergency response teams are attending to casualty situations as needed.",
|
||||
"Emergency work crews are restoring essential community infrastructure as necessary.",
|
||||
"If you have an emergency dial 9 1 1.",
|
||||
]
|
||||
|
||||
# If there are additional areas
|
||||
if impactRange != impactMax:
|
||||
qualifier = self._getImpactsQualifier(impactRangeMax)
|
||||
|
||||
curPhrase = "Prepare for %s damage across %s." % \
|
||||
(impactRange, self._frame("ENTER AREA DESCRIPTION"))
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
curPhrase = "Also, prepare for " + qualifier + "wind having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
curPhrase = "Also, protect against " + qualifier + "wind having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
curPhrase = "Potential impacts from the main wind event are also now unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well sheltered from " + qualifier + "wind having " + self._frame("possible | additional") + " " + impactRange + " impacts."
|
||||
else:
|
||||
curPhrase = "Little to no additional wind impacts expected."
|
||||
|
||||
# If this phrase is not already part of the additional impacts
|
||||
if curPhrase not in sectionDict['additionalImpactRange']:
|
||||
|
@ -614,12 +646,12 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
impactMin = self._samplingDict['StormSurgeThreat']['impactMin']
|
||||
impactMax = self._samplingDict['StormSurgeThreat']['impactMax']
|
||||
impactRange = self._samplingDict['StormSurgeThreat']['impactRange']
|
||||
impactRangeMax = self._samplingDict['StormSurgeThreat']['impactRangeMax']
|
||||
inputThreatDominant = self._samplingDict['StormSurgeThreat']['inputThreatDominant']
|
||||
|
||||
# Test the simplest case first
|
||||
if impactMin == "none" and impactMax == "none":
|
||||
sectionDict['impactRange'] = impactRange
|
||||
sectionDict['variedImpacts'] = None
|
||||
productDict['surgeSection'] = sectionDict
|
||||
return
|
||||
|
||||
|
@ -628,14 +660,27 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
lifeThreatening = ""
|
||||
|
||||
if impactMax in ["significant", "extensive", "devastating", "catastrophic"]:
|
||||
lifeThreatening = "life-threatening storm surge and "
|
||||
lifeThreatening = "life-threatening "
|
||||
elif impactMax == "limited":
|
||||
lifeThreatening = "locally hazardous "
|
||||
|
||||
sectionDict['impactRange'] = "Prepare for " + \
|
||||
lifeThreatening + impactMax + \
|
||||
" damage in surge prone areas of " + self._cwa_descriptor() + ", with the greatest impacts " + \
|
||||
self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
sectionDict['impactRange'] = "Prepare for " + lifeThreatening + "surge having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts in this area include:"
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
sectionDict['impactRange'] = "Protect against " + lifeThreatening + "surge having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts in this area include:"
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
sectionDict['impactRange'] = "Potential impacts from the main surge event are now unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well away from " + lifeThreatening + "surge having " + self._frame("possible | additional") + " " + impactMax + " impacts. If realized, these impacts include:"
|
||||
else:
|
||||
sectionDict['impactRange'] = "Little to no additional surge impacts expected."
|
||||
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Storm Surge", self._impactCategoryToThreatLevel(impactMax))
|
||||
if self._GeneralOnsetTime != "recovery":
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Storm Surge", self._impactCategoryToThreatLevel(impactMax))
|
||||
else:
|
||||
sectionDict['impactLib'] = ["Community officials are now assessing the extent of actual surge impacts accordingly.",
|
||||
"Emergency response teams are attending to casualty situations as needed.",
|
||||
"Emergency work crews are restoring essential community infrastructure as necessary.",
|
||||
"If you have an emergency dial 9 1 1.",
|
||||
]
|
||||
|
||||
# Reexamine the impact range - we need to separate out "life-threatening" surge categories into a separate statement
|
||||
impactParts = impactRange.split(" ")
|
||||
|
@ -649,9 +694,11 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
if impactParts[0] in ["limited", "none"]:
|
||||
# Make a new range to report
|
||||
impactRange = "significant"
|
||||
impactRangeMax = impactRange
|
||||
|
||||
if impactParts[2] != "significant":
|
||||
impactRange += " to " + impactParts[2]
|
||||
impactRangeMax = impactParts[2]
|
||||
|
||||
impactRangeRest = impactParts[0]
|
||||
|
||||
|
@ -665,8 +712,21 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
# If there are additional life-threatening surge areas
|
||||
if impactRange != impactMax and impactRange != impactMin:
|
||||
|
||||
curPhrase = "Brace for %s%s damage across %s." % \
|
||||
(lifeThreatening, impactRange, self._frame("ENTER AREA DESCRIPTION"))
|
||||
lifeThreatening = ""
|
||||
|
||||
if impactRangeMax in ["significant", "extensive", "devastating", "catastrophic"]:
|
||||
lifeThreatening = "life-threatening "
|
||||
elif impactRangeMax == "limited":
|
||||
lifeThreatening = "locally hazardous "
|
||||
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
curPhrase = "Also, prepare for " + lifeThreatening + "surge having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
curPhrase = "Also, protect against " + lifeThreatening + "surge having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
curPhrase = "Potential impacts from the main surge event are also now unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well away from " + lifeThreatening + "surge having " + self._frame("possible | additional") + " " + impactRange + " impacts."
|
||||
else:
|
||||
curPhrase = "Little to no additional surge impacts expected."
|
||||
|
||||
self.debug_print("DEBUG: curPhrase = '%s'" % (curPhrase), 1)
|
||||
self.debug_print("DEBUG: sectionDict['additionalImpactRange'] = \n'%s'" %
|
||||
|
@ -680,8 +740,16 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
# If there are additional areas
|
||||
if impactRangeRest != impactMax:
|
||||
|
||||
curPhrase = "Prepare for %s damage from storm surge across %s." % \
|
||||
(impactRangeRest, self._frame("ENTER AREA DESCRIPTION"))
|
||||
lifeThreatening = "locally hazardous "
|
||||
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
curPhrase = "Also, prepare for " + lifeThreatening + "surge having possible " + impactRangeRest + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
curPhrase = "Also, protect against " + lifeThreatening + "surge having possible " + impactRangeRest + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
curPhrase = "Potential impacts from the main surge event are also now unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well away from " + lifeThreatening + "surge having " + self._frame("possible | additional") + " " + impactRangeRest + " impacts."
|
||||
else:
|
||||
curPhrase = "Little to no additional surge impacts expected."
|
||||
|
||||
# If this phrase is not already part of the additional impacts
|
||||
if curPhrase not in sectionDict['additionalImpactRange']:
|
||||
|
@ -716,6 +784,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
impactMin = self._samplingDict['FloodingRainThreat']['impactMin']
|
||||
impactMax = self._samplingDict['FloodingRainThreat']['impactMax']
|
||||
impactRange = self._samplingDict['FloodingRainThreat']['impactRange']
|
||||
impactRangeMax = self._samplingDict['FloodingRainThreat']['impactRangeMax']
|
||||
inputThreatDominant = self._samplingDict['FloodingRainThreat']['inputThreatDominant']
|
||||
|
||||
self.debug_print("In _floodingRainSection", 1)
|
||||
|
@ -724,25 +793,68 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
# Test the simplest case first
|
||||
if impactMin == "none" and impactMax == "none":
|
||||
sectionDict['impactRange'] = impactRange
|
||||
sectionDict['variedImpacts'] = None
|
||||
productDict['floodingRainSection'] = sectionDict
|
||||
return
|
||||
|
||||
qualifier = ""
|
||||
if impactMax in ["extensive", "devastating", "catastrophic"]:
|
||||
qualifier = "life-threatening "
|
||||
elif impactMax == "significant":
|
||||
qualifier = "dangerous "
|
||||
elif impactMax == "limited":
|
||||
qualifier = "locally hazardous "
|
||||
|
||||
# If there is only one impact across the entire CWA, and it is the max
|
||||
if impactMax != "none" and impactMin == impactMax and inputThreatDominant != "None":
|
||||
sectionDict['impactRange'] = "Prepare for " + impactMax + " flooding across " + self._cwa_descriptor() + "."
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
sectionDict['impactRange'] = "Prepare for " + qualifier + "rainfall flooding having possible " + impactMax + " impacts across " + self._cwa_descriptor() + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
sectionDict['impactRange'] = "Protect against " + qualifier + "rainfall flooding having possible " + impactMax + " impacts across " + self._cwa_descriptor() + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
sectionDict['impactRange'] = "Potential impacts from the flooding rain are still unfolding across " + self._cwa_descriptor() + ". Remain well guarded against " + qualifier + "flood waters having " + self._frame("possible | additional") + " " + impactMax + " impacts. If realized, these impacts include:"
|
||||
else:
|
||||
sectionDict['impactRange'] = "Additional impacts from flooding rain are still a concern across " + self._cwa_descriptor() + ". Remain well guarded against " + qualifier + "flood waters having further impacts of " + impactMax + " potential."
|
||||
# Handle the case where the impacts are not the same across the entire CWA
|
||||
else:
|
||||
sectionDict['variedImpacts'] = True
|
||||
sectionDict['impactRange'] = "Prepare for " + impactMax + " flooding " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
sectionDict['impactRange'] = "Prepare for " + qualifier + "rainfall flooding having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
sectionDict['impactRange'] = "Protect against " + qualifier + "rainfall flooding having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
sectionDict['impactRange'] = "Potential impacts from the flooding rain are still unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well guarded against " + qualifier + "flood waters having " + self._frame("possible | additional") + " " + impactMax + " impacts. If realized, these impacts include:"
|
||||
else:
|
||||
if impactMax != "none":
|
||||
sectionDict['impactRange'] = "Additional impacts from flooding rain are still a concern across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well guarded against " + qualifier + "flood waters having further impacts of " + impactMax + " potential."
|
||||
else:
|
||||
sectionDict['impactRange'] = "Little to no additional impacts expected from flooding rain."
|
||||
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Flooding Rain", self._impactCategoryToThreatLevel(impactMax))
|
||||
if self._GeneralOnsetTime != "recovery":
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Flooding Rain", self._impactCategoryToThreatLevel(impactMax))
|
||||
else:
|
||||
sectionDict['impactLib'] = []
|
||||
|
||||
# If there are additional areas
|
||||
if impactRange != impactMax:
|
||||
|
||||
curPhrase = "Prepare for %s flooding impacts across %s." % \
|
||||
(impactRange, self._frame("ENTER AREA DESCRIPTION"))
|
||||
qualifier = ""
|
||||
if impactRangeMax in ["extensive", "devastating", "catastrophic"]:
|
||||
qualifier = "life-threatening "
|
||||
elif impactRangeMax == "significant":
|
||||
qualifier = "dangerous "
|
||||
elif impactRangeMax == "limited":
|
||||
qualifier = "locally hazardous "
|
||||
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
curPhrase = "Prepare for " + qualifier + "rainfall flooding having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
curPhrase = "Protect against " + qualifier + "rainfall flooding having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
curPhrase = "Potential impacts from the flooding rain are still unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well guarded against " + qualifier + "flood waters having " + self._frame("possible | additional") + " " + impactRange + " impacts."
|
||||
else:
|
||||
if impactMax != "none":
|
||||
curPhrase = "Additional impacts from flooding rain are still a concern across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well guarded against " + qualifier + "flood waters having further impacts of " + impactRange + " potential."
|
||||
else:
|
||||
curPhrase = "Little to no additional impacts expected from flooding rain."
|
||||
|
||||
# If this phrase is not already part of the additional impacts
|
||||
if curPhrase not in sectionDict['additionalImpactRange']:
|
||||
|
@ -775,12 +887,12 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
impactMin = self._samplingDict['TornadoThreat']['impactMin']
|
||||
impactMax = self._samplingDict['TornadoThreat']['impactMax']
|
||||
impactRange = self._samplingDict['TornadoThreat']['impactRange']
|
||||
impactRangeMax = self._samplingDict['TornadoThreat']['impactRangeMax']
|
||||
inputThreatDominant = self._samplingDict['TornadoThreat']['inputThreatDominant']
|
||||
|
||||
# Test the simplest case first
|
||||
if impactMin == "none" and impactMax == "none":
|
||||
sectionDict['impactRange'] = impactRange
|
||||
sectionDict['variedImpacts'] = None
|
||||
productDict['tornadoSection'] = sectionDict
|
||||
return
|
||||
|
||||
|
@ -791,6 +903,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
impactMin = "devastating"
|
||||
if impactRange in ["devastating", "catastrophic"]:
|
||||
impactRange = "devastating"
|
||||
impactRangeMax = impactRange
|
||||
|
||||
# If the max impact category is "catastrophic", and we lumped "devastating" in with it, ensure "devastating" is not
|
||||
# leftover as the high end of the range
|
||||
|
@ -802,25 +915,67 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
if impactParts[0] != "extensive":
|
||||
# Force the upper end to be 1 category lower
|
||||
impactRange.replace("devastating", "extensive")
|
||||
impactRangeMax = "extensive"
|
||||
# Otherwise, the impact is just "extensive"
|
||||
else:
|
||||
impactRange = "extensive"
|
||||
impactRangeMax = "extensive"
|
||||
|
||||
qualifier = ""
|
||||
if impactMax in ["extensive", "devastating"]:
|
||||
qualifier = "particularly dangerous "
|
||||
elif impactMax == "significant":
|
||||
qualifier = "dangerous "
|
||||
|
||||
# If there is only one impact across the entire CWA, and it is the max
|
||||
if impactMax != "none" and impactMin == impactMax and inputThreatDominant != "None":
|
||||
sectionDict['impactRange'] = "Prepare for " + impactMax + " damage across " + self._cwa_descriptor() + "."
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
sectionDict['impactRange'] = "Prepare for a " + qualifier + "tornado event having possible " + impactMax + " impacts across " + self._cwa_descriptor() + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
sectionDict['impactRange'] = "Protect against a " + qualifier + "tornado event having possible " + impactMax + " impacts across " + self._cwa_descriptor() + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
sectionDict['impactRange'] = "Potential impacts from tornadoes are still unfolding across " + self._cwa_descriptor() + ". Remain well braced against a " + qualifier + "tornado event having " + self._frame("possible | additional") + " " + impactMax + " impacts. If realized, these impacts include:"
|
||||
else:
|
||||
sectionDict['impactRange'] = "Additional impacts from tornadoes are still a concern across " + self._cwa_descriptor() + ". Remain well braced against " + qualifier + "tornado event having further " + impactMax + " impact potential."
|
||||
# Handle the case where the impacts are not the same across the entire CWA
|
||||
else:
|
||||
sectionDict['variedImpacts'] = True
|
||||
sectionDict['impactRange'] = "Prepare for " + impactMax + " damage " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
sectionDict['impactRange'] = "Prepare for a " + qualifier + "tornado event having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
sectionDict['impactRange'] = "Protect against a " + qualifier + "tornado event having possible " + impactMax + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + ". Potential impacts include:"
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
sectionDict['impactRange'] = "Potential impacts from tornadoes are still unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well braced against a " + qualifier + "tornado event having " + self._frame("possible | additional") + " " + impactMax + " impacts. If realized, these impacts include:"
|
||||
else:
|
||||
if impactMax != "none":
|
||||
sectionDict['impactRange'] = "Additional impacts from tornadoes are still a concern across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well braced against " + qualifier + "tornado event having further " + impactMax + " impact potential."
|
||||
else:
|
||||
sectionDict['impactRange'] = "Little to no additional impacts expected from tornadoes."
|
||||
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Tornado", self._impactCategoryToThreatLevel(impactMax))
|
||||
if self._GeneralOnsetTime != "recovery":
|
||||
sectionDict['impactLib'] = self._getPotentialImpactsStatements("Tornado", self._impactCategoryToThreatLevel(impactMax))
|
||||
else:
|
||||
sectionDict['impactLib'] = []
|
||||
|
||||
# If there are additional areas
|
||||
if impactRange != impactMax:
|
||||
|
||||
curPhrase = "Prepare for %s damage across %s." % \
|
||||
(impactRange, self._frame("ENTER AREA DESCRIPTION"))
|
||||
qualifier = ""
|
||||
if impactRangeMax in ["extensive", "devastating"]:
|
||||
qualifier = "particularly dangerous "
|
||||
elif impactRangeMax == "significant":
|
||||
qualifier = "dangerous "
|
||||
|
||||
if self._GeneralOnsetTime == "check plans":
|
||||
curPhrase = "Prepare for a " + qualifier + "tornado event having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "complete preparations":
|
||||
curPhrase = "Protect against a " + qualifier + "tornado event having possible " + impactRange + " impacts across " + self._frame("ENTER AREA DESCRIPTION") + "."
|
||||
elif self._GeneralOnsetTime == "hunker down":
|
||||
curPhrase = "Potential impacts from tornadoes are still unfolding across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well braced against a " + qualifier + "tornado event having " + self._frame("possible | additional") + " " + impactRange + " impacts."
|
||||
else:
|
||||
if impactMax != "none":
|
||||
curPhrase = "Additional impacts from tornadoes are still a concern across " + self._frame("ENTER AREA DESCRIPTION") + ". Remain well braced against " + qualifier + "tornado event having further " + impactRange + " impact potential."
|
||||
else:
|
||||
curPhrase = "Little to no additional impacts expected from tornadoes."
|
||||
|
||||
# If this phrase is not already part of the additional impacts
|
||||
if curPhrase not in sectionDict['additionalImpactRange']:
|
||||
|
@ -842,6 +997,17 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
|
||||
productDict['tornadoSection'] = sectionDict
|
||||
|
||||
def _getImpactsQualifier(self, impact):
|
||||
qualifier = ""
|
||||
if impact in ["extensive", "devastating", "catastrophic"]:
|
||||
qualifier = "life-threatening "
|
||||
elif impact == "significant":
|
||||
qualifier = "dangerous "
|
||||
elif impact == "limited":
|
||||
qualifier = "hazardous "
|
||||
|
||||
return qualifier
|
||||
|
||||
def _coastalHazardsSection(self, productDict, productSegmentGroup, productSegment):
|
||||
productDict['coastalHazardsSection'] = self._frame("ENTER HERE A STATEMENT OF ANY ADDITIONAL HAZARDS OF CONCERN ALONG THE COAST SUCH AS RIP CURRENTS, HIGH WAVES, CONCERNS FOR BEACH EROSION ETC ETC IF NOT ALREADY DONE IN THE SURGE SECTION.")
|
||||
|
||||
|
@ -1199,7 +1365,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
|
||||
# Determine dominant impact category for rest of CWA - No impact
|
||||
if impactMin == "none" and impactMax == "none":
|
||||
impactRange = "No impacts are anticipated at this time across " + self._cwa_descriptor() + "."
|
||||
impactRange = "Little to no " + self._frame("additional") + " impacts are anticipated at this time across " + self._cwa_descriptor() + "."
|
||||
# Otherwise, at least some impact will be experienced across the CWA
|
||||
else:
|
||||
# Do not permit the lowest category to be "None", if the highest category is also not "None"
|
||||
|
@ -1210,6 +1376,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
|
||||
if impactMin == impactMax:
|
||||
impactRange = impactMax
|
||||
impactRangeMax = impactMax
|
||||
elif impactMin == impactRangeMax:
|
||||
impactRange = impactRangeMax
|
||||
else:
|
||||
|
@ -1218,6 +1385,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
self._samplingDict[threatName]['impactMin'] = impactMin
|
||||
self._samplingDict[threatName]['impactMax'] = impactMax
|
||||
self._samplingDict[threatName]['impactRange'] = impactRange
|
||||
self._samplingDict[threatName]['impactRangeMax'] = impactRangeMax
|
||||
|
||||
###############################################################
|
||||
### Area, Zone and Segment related methods
|
||||
|
@ -1234,30 +1402,6 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
refData = ReferenceData(gridLoc, refID, grid2Dbit)
|
||||
editAreaUtils.saveEditAreas([refData])
|
||||
|
||||
def _groupSegments(self, segments):
|
||||
'''
|
||||
Group the segments into the products
|
||||
return a list of productSegmentGroup dictionaries
|
||||
'''
|
||||
|
||||
segment_vtecRecords_tuples = []
|
||||
for segment in segments:
|
||||
vtecRecords = self._getVtecRecords(segment)
|
||||
self.debug_print("vtecRecords =\n\n%s\n" % (self._pp.pformat(vtecRecords)))
|
||||
segment_vtecRecords_tuples.append((segment, vtecRecords))
|
||||
|
||||
productSegmentGroup = {
|
||||
'productID' : 'HLS',
|
||||
'productName': self._productName,
|
||||
'geoType': 'area',
|
||||
'vtecEngine': self._hazardsTable,
|
||||
'mapType': 'publicZones',
|
||||
'segmented': True,
|
||||
'productParts': self._productParts_HLS(segment_vtecRecords_tuples),
|
||||
}
|
||||
|
||||
return productSegmentGroup
|
||||
|
||||
###############################################################
|
||||
### Hazards related methods
|
||||
|
||||
|
@ -1393,7 +1537,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
headlineSearch[0] = re.sub("\.\.\.$", "", headlineSearch[0])
|
||||
|
||||
# # Remove the first and last '**' - if they exist
|
||||
# headlineSearch[0] = headlineSearch[0].sub("**", "").strip()
|
||||
headlineSearch[0] = headlineSearch[0].replace("**", "").strip()
|
||||
|
||||
# Return the first cleaned-up headline string we found
|
||||
return self._cleanText(headlineSearch[0])
|
||||
|
@ -2321,7 +2465,7 @@ class LegacyFormatter():
|
|||
elif name == "situationOverview":
|
||||
text += self.processSituationOverview(productDict['situationOverview'])
|
||||
elif name == "sigPotentialImpacts":
|
||||
header = "Significant Potential Impacts"
|
||||
header = "Potential Impacts"
|
||||
text += header + "\n" + "-"*len(header) + "\n\n"
|
||||
if not self._textProduct._ImpactsAnticipated:
|
||||
text += "None\n\n"
|
||||
|
@ -2517,20 +2661,20 @@ class LegacyFormatter():
|
|||
text = "* " + sectionDict['title'] + ":\n"
|
||||
|
||||
impactRangeText = sectionDict['impactRange']
|
||||
if sectionDict['variedImpacts'] is not None:
|
||||
if sectionDict['variedImpacts']:
|
||||
impactRangeText += " In these areas, potential impacts include:"
|
||||
else:
|
||||
impactRangeText += " Potential impacts include:"
|
||||
|
||||
text += self._textProduct.indentText(impactRangeText, maxWidth=self._textProduct._lineLength)
|
||||
|
||||
if self._textProduct._GeneralOnsetTime == "recovery" and len(sectionDict['impactLib']) != 0:
|
||||
text += "|*\n"
|
||||
|
||||
for impact in sectionDict['impactLib']:
|
||||
text += self._textProduct.indentText(impact,
|
||||
indentFirstString = self.TAB + "- ",
|
||||
indentNextString = self.TAB + " ",
|
||||
maxWidth=self._textProduct._lineLength)
|
||||
|
||||
if self._textProduct._GeneralOnsetTime == "recovery" and len(sectionDict['impactLib']) != 0:
|
||||
text += "*|\n"
|
||||
|
||||
if len(sectionDict['additionalImpactRange']) != 0:
|
||||
text += "\n"
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,7 @@
|
|||
|
||||
<!-- SUBCENTER 0 -->
|
||||
<model>
|
||||
<name>MRMS</name>
|
||||
<name>MRMS_1000</name>
|
||||
<center>161</center>
|
||||
<subcenter>0</subcenter>
|
||||
<grid>10000</grid>
|
||||
|
@ -22,7 +22,7 @@
|
|||
</model>
|
||||
|
||||
<model>
|
||||
<name>MRMS</name>
|
||||
<name>MRMS_0500</name>
|
||||
<center>161</center>
|
||||
<subcenter>0</subcenter>
|
||||
<grid>10001</grid>
|
||||
|
@ -58,4 +58,4 @@
|
|||
|
||||
<!-- END SUBCENTER 1 -->
|
||||
|
||||
</gribModelSet>
|
||||
</gribModelSet>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
</model>
|
||||
|
||||
<model>
|
||||
<name>MPE-Local</name>
|
||||
<name>MPE-Mosaic</name>
|
||||
<center>9</center>
|
||||
<subcenter>0</subcenter>
|
||||
<grid>304</grid>
|
||||
|
@ -50,7 +50,6 @@
|
|||
</process>
|
||||
</model>
|
||||
|
||||
|
||||
<!-- END SUBCENTER 0 -->
|
||||
|
||||
<!-- SUBCENTER 105: San Juan PR WFO -->
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<subGridDef>
|
||||
<modelNames>MRMS</modelNames>
|
||||
<modelNames>MRMS_1000</modelNames>
|
||||
<referenceGrid>10000</referenceGrid>
|
||||
<nx>800</nx>
|
||||
<ny>600</ny>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<subGridDef>
|
||||
<modelNames>MRMS</modelNames>
|
||||
<modelNames>MRMS_0500</modelNames>
|
||||
<referenceGrid>10001</referenceGrid>
|
||||
<nx>1600</nx>
|
||||
<ny>1200</ny>
|
||||
|
|
|
@ -1201,7 +1201,7 @@ C | 1 | 0 | 4 | | |..|8000F0FF| | 0 | 2
|
|||
<parameter>PLI</parameter>
|
||||
</paramLevelMatches>
|
||||
<contourStyle>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
<contourLabeling labelSpacing="4">
|
||||
<increment>2</increment>
|
||||
</contourLabeling>
|
||||
|
@ -1212,7 +1212,7 @@ C | 1 | 0 | 4 | | |..|8000F0FF| | 0 | 2
|
|||
<parameter>SLI</parameter>
|
||||
</paramLevelMatches>
|
||||
<contourStyle>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
<displayFlags>NoPlane</displayFlags>
|
||||
<contourLabeling labelSpacing="4">
|
||||
<increment>2</increment>
|
||||
|
@ -1229,7 +1229,7 @@ C | 1 | 0 | 4 | | |..|8000F0FF|,900| 0 | 2
|
|||
<creatingEntity>Laps</creatingEntity>
|
||||
</paramLevelMatches>
|
||||
<contourStyle>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
<displayFlags>NoPlane</displayFlags>
|
||||
<contourLabeling labelSpacing="4">
|
||||
<increment>2</increment>
|
||||
|
@ -1244,7 +1244,7 @@ C | 1 | 0 | 4 | | |..|8000F0FF| | 0 | 2
|
|||
<parameter>BLI</parameter>
|
||||
</paramLevelMatches>
|
||||
<contourStyle>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
<contourLabeling labelSpacing="4">
|
||||
<increment>2</increment>
|
||||
</contourLabeling>
|
||||
|
@ -2771,7 +2771,7 @@ C | 1 | 0 | 4 | | |..|8000F0FF|,,,80 | 0 | 2
|
|||
</paramLevelMatches>
|
||||
<contourStyle>
|
||||
<smoothingDistance>80</smoothingDistance>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
<displayFlags>NoPlane</displayFlags>
|
||||
<contourLabeling labelSpacing="4">
|
||||
<increment>2</increment>
|
||||
|
|
|
@ -347,7 +347,7 @@
|
|||
<parameter>shWlt</parameter>
|
||||
</paramLevelMatches>
|
||||
<graphStyle>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
</graphStyle>
|
||||
</styleRule>
|
||||
|
||||
|
|
|
@ -1780,7 +1780,7 @@
|
|||
<parameter>PLI</parameter>
|
||||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
<range scale="LINEAR">
|
||||
<minValue>-15</minValue>
|
||||
<maxValue>15</maxValue>
|
||||
|
@ -1800,7 +1800,7 @@
|
|||
<parameter>BLI</parameter>
|
||||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
<displayUnits label="C">K</displayUnits>
|
||||
<displayUnits>C</displayUnits>
|
||||
<range scale="LINEAR">
|
||||
<minValue>-15</minValue>
|
||||
<maxValue>15</maxValue>
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
## EVAN BOOKBINDER -- SEP 18 2013 Implemented config.vm
|
||||
## PHIL KURIMSKI -- JUN 26 2014 OB14.2.2-9 ##
|
||||
## ADDED DSS EVENTS ##
|
||||
## UPDATED PHIL KURIMSKI -- FEB 18 2015 Implemented##
|
||||
## updated CTAs ##
|
||||
#####################################################
|
||||
#parse("config.vm")
|
||||
################################################
|
||||
|
@ -335,7 +337,7 @@ THIS IS A TEST MESSAGE. ##
|
|||
THIS IS A TEST MESSAGE. ##
|
||||
#end
|
||||
#thirdBullet(${dateUtil},${event},${timeFormat},${localtimezone},${secondtimezone})
|
||||
...${report}LOCATED ##
|
||||
...${report}WAS LOCATED ##
|
||||
#if(${stormType} == "line")
|
||||
#handleClosestPoints(${list}, ${closestPoints}, ${otherClosestPoints}, ${stormType}, ${nearPhrase} , ${maxMarineNearDistance}, ${overPhrase}, ${maxMarineOverDistance}, ${marineDistanceUnits}, ${useSecondReferenceLine})
|
||||
#else
|
||||
|
@ -406,7 +408,7 @@ THOSE ATTENDING !**event/venue name or location**! ARE IN THE PATH OF ${specialE
|
|||
|
||||
## Comment out #parse command below to pull in Dynamic DSS Event Info
|
||||
## If this feature is utilized, the "specialEvent" bullet (output above) can
|
||||
## likely be commented out from the impactSevereThunderstormWarning.xml file
|
||||
## likely be commented out from the impactSpecialMarineWarning.xml file
|
||||
#parse("dssEvents.vm")
|
||||
|
||||
#####################
|
||||
|
@ -430,46 +432,46 @@ PRECAUTIONARY/PREPAREDNESS ACTIONS...
|
|||
${ashfallCTA}
|
||||
|
||||
#if(${list.contains(${bullets}, "genericCTA")})
|
||||
#if(${stormType} == "line")
|
||||
AS THUNDERSTORMS MOVE OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES.
|
||||
|
||||
#else
|
||||
AS THIS THUNDERSTORM MOVES OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THE STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "gustyWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "hailWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THESE STORMS.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THIS STORM.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "nonThunderstormCTA")})
|
||||
MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES. BOATERS...ESPECIALLY THOSE UNDER SAIL...SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THE HIGH WINDS SUBSIDE.
|
||||
SEEK SAFE SHELTER...MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES.
|
||||
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "waterspoutCTA")})
|
||||
#if(${list.contains(${bullets}, "thunderstorm")})
|
||||
THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS. WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#else
|
||||
WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "lightningCTA")})
|
||||
#if(${stormType} == "line")
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THESE STORMS. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#else
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "reportCTA")})
|
||||
REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY WILL RELAY YOUR REPORT TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
|
||||
#end
|
||||
#if(${ctaSelected} == "YES")
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
Note: Volcano information will not show up in the GUI unless uncommented out
|
||||
Phil Kurimski 09-19-2013 added geospatialConfig.xml
|
||||
Phil Kurimski 06-26-2014 added DSS Events
|
||||
Phil Kurimski 02-18-2015 Updated CTA section
|
||||
-->
|
||||
|
||||
<!-- INCLUDE ALL GEOSPTATIAL INFORMATION FOR THIS PRODUCT
|
||||
|
@ -137,13 +138,13 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="specialEvent" bulletText="Special heads-up for large event/venue" parseString="THOSE ATTENDING"/>
|
||||
<bullet bulletText="" bulletType="title"/>
|
||||
<bullet bulletText=" ****** CALLS TO ACTION (CHOOSE 1 OR MORE) ****** " bulletType="title"/>
|
||||
<bullet bulletName="genericCTA" bulletText="As thunderstorms move over the water.." parseString="OVER THE WATER...BOATERS CAN EXPECT"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES..."/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Mariners can expect cta with hail/wind speeds" parseString="MARINERS CAN EXPECT WIND GUSTS"/>
|
||||
<bullet bulletName="genericCTA" bulletText="Generic CTA" parseString="MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Gusty Winds CTA" parseString="MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED"/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Wind/Hail cta with hail/wind speeds" parseString="DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE"/>
|
||||
<bullet bulletName="nonThunderstormCTA" bulletText="Non thunderstorm winds - mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Thunderstorms can produce waterspouts" parseString="THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning" parseString="FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Waterspout CTA" parseString="CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning CTA" parseString="FREQUENT LIGHTNING IS OCCURRING WITH"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE"/>
|
||||
</bullets>
|
||||
</bulletActionGroup>
|
||||
<bulletActionGroup action="COR" phen="MA" sig="W">
|
||||
|
@ -196,13 +197,13 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="specialEvent" bulletText="Special heads-up for large event/venue" parseString="THOSE ATTENDING"/>
|
||||
<bullet bulletText="" bulletType="title"/>
|
||||
<bullet bulletText=" ****** CALLS TO ACTION (CHOOSE 1 OR MORE) ****** " bulletType="title"/>
|
||||
<bullet bulletName="genericCTA" bulletText="As thunderstorms move over the water.." parseString="OVER THE WATER...BOATERS CAN EXPECT"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES..."/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Mariners can expect cta with hail/wind speeds" parseString="MARINERS CAN EXPECT WIND GUSTS"/>
|
||||
<bullet bulletName="genericCTA" bulletText="Generic CTA" parseString="MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Gusty Winds CTA" parseString="MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED"/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Wind/Hail cta with hail/wind speeds" parseString="DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE"/>
|
||||
<bullet bulletName="nonThunderstormCTA" bulletText="Non thunderstorm winds - mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Thunderstorms can produce waterspouts" parseString="THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning" parseString="FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Waterspout CTA" parseString="CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning CTA" parseString="FREQUENT LIGHTNING IS OCCURRING WITH"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE"/>
|
||||
</bullets>
|
||||
</bulletActionGroup>
|
||||
</bulletActionGroups>
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
## UPDATED BOOKBINDER 9-18-2013 Implemented config.vm
|
||||
## PHIL KURIMSKI -- JUN 26 2014 OB14.2.2-9 ##
|
||||
## ADDED DSS EVENTS ##
|
||||
## UPDATED PHIL KURIMSKI -- FEB 18 2015 Implemented##
|
||||
## updated CTAs ##
|
||||
## MIKE REGA - 2-26-2015 removed wind/hail/spout ##
|
||||
## tags in CAN and EXP ##
|
||||
#####################################################
|
||||
#parse("config.vm")
|
||||
############################################
|
||||
|
@ -447,7 +451,7 @@ ${area.name}...
|
|||
THIS IS A TEST MESSAGE. ##
|
||||
#end
|
||||
#thirdBullet(${dateUtil},${event},${timeFormat},${localtimezone},${secondtimezone})
|
||||
...${report}LOCATED ##
|
||||
...${report}WAS LOCATED ##
|
||||
#if(${stormType} == "line")
|
||||
#handleClosestPoints(${list}, ${closestPoints}, ${otherClosestPoints}, ${stormType}, ${nearPhrase} , ${maxMarineNearDistance}, ${overPhrase}, ${maxMarineOverDistance}, ${marineDistanceUnits}, ${useSecondReferenceLine})
|
||||
#else
|
||||
|
@ -507,7 +511,7 @@ THOSE ATTENDING !**event/venue name or location**! ARE IN THE PATH OF ${specialE
|
|||
|
||||
## Comment out #parse command below to pull in Dynamic DSS Event Info
|
||||
## If this feature is utilized, the "specialEvent" bullet (output above) can
|
||||
## likely be commented out from the impactSevereThunderstormWarning.xml file
|
||||
## likely be commented out from the impactSpecialMarineWarningFollowup.xml file
|
||||
#parse("dssEvents.vm")
|
||||
|
||||
#####################
|
||||
|
@ -532,46 +536,46 @@ PRECAUTIONARY/PREPAREDNESS ACTIONS...
|
|||
${ashfallCTA}
|
||||
|
||||
#if(${list.contains(${bullets}, "genericCTA")})
|
||||
#if(${stormType} == "line")
|
||||
AS THUNDERSTORMS MOVE OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES.
|
||||
|
||||
#else
|
||||
AS THIS THUNDERSTORM MOVES OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THE STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "gustyWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "hailWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THESE STORMS.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THIS STORM.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "nonThunderstormCTA")})
|
||||
MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES. BOATERS...ESPECIALLY THOSE UNDER SAIL...SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THE HIGH WINDS SUBSIDE.
|
||||
SEEK SAFE SHELTER...MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES.
|
||||
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "waterspoutCTA")})
|
||||
THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS. WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
#if(${list.contains(${bullets}, "thunderstorm")})
|
||||
THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS. WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#else
|
||||
WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "lightningCTA")})
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
#if(${stormType} == "line")
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THESE STORMS. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#else
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "reportCTA")})
|
||||
REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY WILL RELAY YOUR REPORT TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
|
||||
#end
|
||||
#if(${ctaSelected} == "YES")
|
||||
|
@ -756,7 +760,7 @@ ${area.name}...
|
|||
#if(${productClass}=="T")
|
||||
THIS IS A TEST MESSAGE. ##
|
||||
#end
|
||||
AT ${dateUtil.format(${event}, ${timeFormat.clock}, ${localtimezone})}...${report}LOCATED ##
|
||||
AT ${dateUtil.format(${event}, ${timeFormat.clock}, ${localtimezone})}...${report}WAS LOCATED ##
|
||||
#if(${stormType} == "line")
|
||||
#handleClosestPoints(${list}, ${closestPoints}, ${otherClosestPoints}, ${stormType}, ${nearPhrase} , ${maxMarineNearDistance}, ${overPhrase}, ${maxMarineOverDistance}, ${marineDistanceUnits}, ${useSecondReferenceLine})
|
||||
#else
|
||||
|
@ -822,7 +826,7 @@ THOSE ATTENDING THE !**event/venue name or location**! ARE IN THE PATH OF THIS S
|
|||
|
||||
## Comment out #parse command below to pull in Dynamic DSS Event Info
|
||||
## If this feature is utilized, the "specialEvent" bullet (output above) can
|
||||
## likely be commented out from the impactSevereThunderstormWarning.xml file
|
||||
## likely be commented out from the impactSpecialMarineWarningFollowup.xml file
|
||||
#parse("dssEvents.vm")
|
||||
|
||||
#####################
|
||||
|
@ -847,46 +851,46 @@ PRECAUTIONARY/PREPAREDNESS ACTIONS...
|
|||
${ashfallCTA}
|
||||
|
||||
#if(${list.contains(${bullets}, "genericCTA")})
|
||||
#if(${stormType} == "line")
|
||||
AS THUNDERSTORMS MOVE OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES.
|
||||
|
||||
#else
|
||||
AS THIS THUNDERSTORM MOVES OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THE STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "gustyWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "hailWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THESE STORMS.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THIS STORM.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "nonThunderstormCTA")})
|
||||
MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES. BOATERS...ESPECIALLY THOSE UNDER SAIL...SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THE HIGH WINDS SUBSIDE.
|
||||
SEEK SAFE SHELTER...MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES.
|
||||
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "waterspoutCTA")})
|
||||
THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS. WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
#if(${list.contains(${bullets}, "thunderstorm")})
|
||||
THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS. WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#else
|
||||
WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "lightningCTA")})
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
#if(${stormType} == "line")
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THESE STORMS. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#else
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "reportCTA")})
|
||||
REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY WILL RELAY YOUR REPORT TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
|
||||
#end
|
||||
#if(${ctaSelected} == "YES")
|
||||
|
@ -1023,7 +1027,7 @@ ${area.name}...
|
|||
#if(${productClass}=="T")
|
||||
THIS IS A TEST MESSAGE. ##
|
||||
#end
|
||||
AT ${dateUtil.format(${event}, ${timeFormat.clock}, ${localtimezone})}...${report}LOCATED ##
|
||||
AT ${dateUtil.format(${event}, ${timeFormat.clock}, ${localtimezone})}...${report}WAS LOCATED ##
|
||||
##Many of the variables passed below are controlled by config.vm
|
||||
#if(${stormType} == "line")
|
||||
#handleClosestPoints(${list}, ${closestPoints}, ${otherClosestPoints}, ${stormType}, ${nearPhrase} , ${maxMarineNearDistance}, ${overPhrase}, ${maxMarineOverDistance}, ${marineDistanceUnits}, ${useSecondReferenceLine})
|
||||
|
@ -1090,7 +1094,7 @@ THOSE ATTENDING THE !**event/venue name or location**! ARE IN THE PATH OF THIS S
|
|||
|
||||
## Comment out #parse command below to pull in Dynamic DSS Event Info
|
||||
## If this feature is utilized, the "specialEvent" bullet (output above) can
|
||||
## likely be commented out from the impactSevereThunderstormWarning.xml file
|
||||
## likely be commented out from the impactSpecialMarineWarningFollowup.xml file
|
||||
#parse("dssEvents.vm")
|
||||
|
||||
#####################
|
||||
|
@ -1115,46 +1119,46 @@ PRECAUTIONARY/PREPAREDNESS ACTIONS...
|
|||
${ashfallCTA}
|
||||
|
||||
#if(${list.contains(${bullets}, "genericCTA")})
|
||||
#if(${stormType} == "line")
|
||||
AS THUNDERSTORMS MOVE OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES.
|
||||
|
||||
#else
|
||||
AS THIS THUNDERSTORM MOVES OVER THE WATER...BOATERS CAN EXPECT GUSTY WINDS AND HIGH WAVES. MOVE TO SAFE HARBOR OR STAY CLOSE TO SHORE UNTIL THE STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "gustyWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "hailWindsCTA")})
|
||||
#if(${stormType} == "line")
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THESE STORMS PASS. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THESE STORMS.
|
||||
|
||||
#else
|
||||
MARINERS CAN EXPECT ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAINS. BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES.
|
||||
BOATERS SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THIS STORM PASSES. ${windCTA}${hailCTA}...HIGH WAVES...DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE WITH THIS STORM.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "nonThunderstormCTA")})
|
||||
MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES. BOATERS...ESPECIALLY THOSE UNDER SAIL...SHOULD SEEK SAFE HARBOR IMMEDIATELY...UNTIL THE HIGH WINDS SUBSIDE.
|
||||
SEEK SAFE SHELTER...MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES.
|
||||
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "waterspoutCTA")})
|
||||
THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS. WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
#if(${list.contains(${bullets}, "thunderstorm")})
|
||||
THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS. WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#else
|
||||
WATERSPOUTS CAN EASILY OVERTURN BOATS AND CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "lightningCTA")})
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
#if(${stormType} == "line")
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THESE STORMS. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#else
|
||||
FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM. IF CAUGHT ON THE OPEN WATER STAY BELOW DECK IF POSSIBLE...KEEP AWAY FROM UNGROUNDED METAL OBJECTS.
|
||||
|
||||
#end
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "reportCTA")})
|
||||
REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY WILL RELAY YOUR REPORT TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE OFFICE.
|
||||
|
||||
#end
|
||||
#if(${ctaSelected} == "YES")
|
||||
|
@ -1266,11 +1270,21 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE.
|
|||
## Waterspout/Hail/Wind Tags used by CR for IBW
|
||||
##################################################################
|
||||
|
||||
#if(${action}=="CAN" || ${action}=="EXP")
|
||||
#set($windTag = "")
|
||||
#set($hailTag = "")
|
||||
#set($spoutTag = "")
|
||||
#end
|
||||
|
||||
#if($spoutTag.length() > 0)
|
||||
<L>${spoutTag}</L>
|
||||
#end
|
||||
#if($hailTag.length() > 0)
|
||||
<L>HAIL...${hailTag}IN</L>
|
||||
#end
|
||||
#if($windTag.length() > 0)
|
||||
<L>WIND...${windTag}KTS</L>
|
||||
#end
|
||||
|
||||
$$
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
Note: Volcano information will not show up in the GUI unless uncommented out
|
||||
Phil Kurimski 09-19-2013 added geospatialConfig.xml
|
||||
Phil Kurimski 06-26-2014 added DSS Events
|
||||
Phil Kurimski 02-18-2015 Updated CTA section
|
||||
-->
|
||||
|
||||
<!-- INCLUDE ALL GEOSPTATIAL INFORMATION FOR THIS PRODUCT
|
||||
|
@ -184,13 +185,13 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="specialEvent" bulletText="Special heads-up for large event/venue" parseString="THOSE ATTENDING"/>
|
||||
<bullet bulletText="" bulletType="title"/>
|
||||
<bullet bulletText=" ****** CALLS TO ACTION (CHOOSE 1 OR MORE) ****** " bulletType="title"/>
|
||||
<bullet bulletName="genericCTA" bulletText="As thunderstorms move over the water.." parseString="OVER THE WATER...BOATERS CAN EXPECT"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES..."/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Mariners can expect cta with hail/wind speeds" parseString="MARINERS CAN EXPECT WIND GUSTS"/>
|
||||
<bullet bulletName="genericCTA" bulletText="Generic CTA" parseString="MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Gusty Winds CTA" parseString="MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED"/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Wind/Hail cta with hail/wind speeds" parseString="DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE"/>
|
||||
<bullet bulletName="nonThunderstormCTA" bulletText="Non thunderstorm winds - mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Thunderstorms can produce waterspouts" parseString="THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning" parseString="FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Waterspout CTA" parseString="CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning CTA" parseString="FREQUENT LIGHTNING IS OCCURRING WITH"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE"/>
|
||||
</bullets>
|
||||
</bulletActionGroup>
|
||||
<bulletActionGroup action="COR" phen="MA" sig="W">
|
||||
|
@ -243,13 +244,13 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="specialEvent" bulletText="Special heads-up for large event/venue" parseString="THOSE ATTENDING"/>
|
||||
<bullet bulletText="" bulletType="title"/>
|
||||
<bullet bulletText=" ****** CALLS TO ACTION (CHOOSE 1 OR MORE) ****** " bulletType="title"/>
|
||||
<bullet bulletName="genericCTA" bulletText="As thunderstorms move over the water.." parseString="OVER THE WATER...BOATERS CAN EXPECT"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...HIGH WAVES..."/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Mariners can expect cta with hail/wind speeds" parseString="MARINERS CAN EXPECT WIND GUSTS"/>
|
||||
<bullet bulletName="genericCTA" bulletText="Generic CTA" parseString="MOVE TO SAFE HARBOR UNTIL HAZARDOUS WEATHER PASSES"/>
|
||||
<bullet bulletName="gustyWindsCTA" bulletText="Gusty Winds CTA" parseString="MOVE TO SAFE HARBOR IMMEDIATELY AS GUSTY WINDS AND HIGH WAVES ARE EXPECTED"/>
|
||||
<bullet bulletName="hailWindsCTA" bulletText="Wind/Hail cta with hail/wind speeds" parseString="DANGEROUS LIGHTNING...AND HEAVY RAIN ARE POSSIBLE"/>
|
||||
<bullet bulletName="nonThunderstormCTA" bulletText="Non thunderstorm winds - mariners can expect gusty winds.." parseString="MARINERS CAN EXPECT GUSTY WINDS...AND INCREASING WAVES"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Thunderstorms can produce waterspouts" parseString="THUNDERSTORMS CAN PRODUCE SUDDEN WATERSPOUTS"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning" parseString="FREQUENT LIGHTNING IS OCCURRING WITH THIS STORM"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY"/>
|
||||
<bullet bulletName="waterspoutCTA" bulletText="Waterspout CTA" parseString="CREATE LOCALLY HAZARDOUS SEAS. SEEK SAFE HARBOR IMMEDIATELY"/>
|
||||
<bullet bulletName="lightningCTA" bulletText="Frequent lightning CTA" parseString="FREQUENT LIGHTNING IS OCCURRING WITH"/>
|
||||
<bullet bulletName="reportCTA" bulletText="Report severe wx" parseString="REPORT SEVERE WEATHER TO THE NATIONAL WEATHER SERVICE"/>
|
||||
</bullets>
|
||||
</bulletActionGroup>
|
||||
</bulletActionGroups>
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
## EDITED EVAN BOOKBINDER 2-25-13 FOR IBW 2013 ##
|
||||
## EDITED PHIL KURIMSKI 5-20-13 FOR UPDATED IMPACT STATEMENTS ##
|
||||
## EDITED PHIL KURIMSKI 9-17-13 FOR SMW IMPACT STATEMENTS ##
|
||||
## EDITED EvAN BOOKBINDER 2-18-14 FOR 2014 IMPACT STATEMENTS ##
|
||||
## EDITED EVAN BOOKBINDER 2-18-14 FOR 2014 IMPACT STATEMENTS ##
|
||||
## EDITED PHIL KURIMSKI 6-26-15 FIXED CONSID IMPCT VARIABLE ##
|
||||
## EDITED PHIL KURIMSKI 2-19-15 UPDATED SMW IMPACT STATEMENTS ##
|
||||
################################################################
|
||||
##
|
||||
################################################################
|
||||
|
@ -114,7 +115,63 @@
|
|||
################################################################
|
||||
## Finally create the Impact Statements for the SMW template
|
||||
################################################################
|
||||
#set($smwimpact = "OVERTURNED AND CAPSIZED BOATS.")
|
||||
###################################################
|
||||
## HANDLE HAIL POSSIBILITIES ######################
|
||||
###################################################
|
||||
#set($smwHailImpact = "")
|
||||
#set($hailAppend = "")
|
||||
#if($hailTag == ">.75")
|
||||
#set($smwHailImpact = "LARGE HAIL COULD RESULT IN STRUCTURAL DAMAGE.")
|
||||
#set($hailAppend = " AND HAIL")
|
||||
#end
|
||||
#if($hailTag == ">2.0")
|
||||
#set($smwHailImpact = "LARGE HAIL COULD RESULT IN PERSONAL INJURY AND SIGNIFICANT STRUCTURAL DAMAGE.")
|
||||
#set($hailAppend = " AND HAIL")
|
||||
#end
|
||||
###################################################
|
||||
## HANDLE WIND POSSIBILITIES ######################
|
||||
###################################################
|
||||
#set($smwWindImpact = "")
|
||||
#if(${windTag} == ">34" || ${windTag} == "40" || ${windTag} == "49")
|
||||
#set($smwWindImpact = "SMALL CRAFT COULD BE DAMAGED IN BRIEFLY HIGHER WINDS AND SUDDENLY HIGHER WAVES.")
|
||||
#end
|
||||
## If winds are 50 knots or greater do not include hail impact statement
|
||||
#if(${windTag} == "50" || ${windTag} == "65")
|
||||
#set($smwWindImpact = "BOATS COULD SUFFER SIGNIFICANT STRUCTURAL DAMAGE IN HIGH WINDS${hailAppend}. SMALL CRAFT COULD CAPSIZE IN SUDDENLY HIGHER WAVES.")
|
||||
#set($smwHailImpact = "")
|
||||
#end
|
||||
###################################################
|
||||
## HANDLE WATERSPOUTS #############################
|
||||
###################################################
|
||||
#set($smwWaterspoutImpact = "")
|
||||
#if(${list.contains(${bullets}, "thunderstorm")})
|
||||
#set($extraImpact = "EASILY OVERTURN BOATS AND ")
|
||||
#else
|
||||
#set($extraImpact = "")
|
||||
#end
|
||||
#if(${list.contains(${bullets}, "sightedSpout")} || ${list.contains(${bullets}, "possibleSpout")})
|
||||
#set($smwWaterspoutImpact = "WATERSPOUTS CAN ${extraImpact}CREATE LOCALLY HAZARDOUS SEAS.")
|
||||
#end
|
||||
##########################################################
|
||||
## Merge the Hail...Wind and Waterspout Impact Statements
|
||||
##########################################################
|
||||
#if($smwWindImpact.length() > 0 && $smwHailImpact.length() > 0 && $smwWaterspoutImpact.length() > 0)
|
||||
#set($smwimpact = "${smwWaterspoutImpact} ${smwWindImpact} ${smwHailImpact}")
|
||||
#elseif($smwWindImpact.length() > 0 && $smwHailImpact.length() > 0)
|
||||
#set($smwimpact = "${smwWindImpact} ${smwHailImpact}")
|
||||
#elseif($smwWindImpact.length() > 0 && $smwWaterspoutImpact.length() > 0)
|
||||
#set($smwimpact = "${smwWaterspoutImpact} ${smwWindImpact}")
|
||||
#elseif($smwHailImpact.length() > 0 && $smwWaterspoutImpact.length() > 0)
|
||||
#set($smwimpact = "${smwWaterspoutImpact} ${smwHailImpact}")
|
||||
#elseif($smwWaterspoutImpact.length() > 0)
|
||||
#set($smwimpact = "${smwWaterspoutImpact}")
|
||||
#elseif($smwWindImpact.length() > 0)
|
||||
#set($smwimpact = "${smwWindImpact}")
|
||||
#elseif($smwHailImpact.length() > 0)
|
||||
#set($smwimpact = "${smwHailImpact}")
|
||||
#else
|
||||
#set($smwimpact = "!**YOU DID NOT SELECT ANY THREATS WORTHY OF SMW CRITERIA. PLEASE CLOSE THIS WINDOW AND RE-GENERATE THIS WARNING!**!")
|
||||
#end
|
||||
############################################################################
|
||||
## End of File
|
||||
############################################################################
|
||||
|
|
|
@ -61,6 +61,10 @@ import com.raytheon.uf.common.util.CollectionUtil;
|
|||
import com.raytheon.uf.common.util.FileUtil;
|
||||
import com.raytheon.uf.edex.core.EDEXUtil;
|
||||
import com.raytheon.uf.edex.database.DataAccessLayerException;
|
||||
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
|
||||
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState;
|
||||
import com.raytheon.uf.edex.database.cluster.ClusterTask;
|
||||
import com.raytheon.uf.edex.database.cluster.handler.CurrentTimeClusterLockHandler;
|
||||
import com.raytheon.uf.edex.database.dao.CoreDao;
|
||||
import com.raytheon.uf.edex.database.dao.DaoConfig;
|
||||
import com.raytheon.uf.edex.database.query.DatabaseQuery;
|
||||
|
@ -95,11 +99,15 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery;
|
|||
* Added performance logging
|
||||
* Nov 14, 2014 4953 randerso Moved dumpProductToTempFile into PracticeVtecDecoder
|
||||
* since it had no reason to be in this class
|
||||
* Dec 30, 2014 16942 ryu Fix update of records for sites other than
|
||||
* Feb 05, 2015 16942 ryu Fix update of records for sites other than
|
||||
* the home site and its neighbors.
|
||||
* Pass issuance site id to getActiveTable()
|
||||
* in updateActiveTable() so records will
|
||||
* be updated correctly.
|
||||
* Feb 05, 2015 4099 randerso Fixed latest ETN query for year-end
|
||||
* Feb 23, 2015 4127 dgilling Use cluster locking to only allow 1 active
|
||||
* table write at a time.
|
||||
* Mar 04, 2015 4129 randerso Pass active table change logger to ingestAt and/or MergeVTEC
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -114,6 +122,10 @@ public class ActiveTable {
|
|||
private static final Logger changeLog = Logger
|
||||
.getLogger("ActiveTableChange");
|
||||
|
||||
private static final String ACTIVE_TABLE_LOCK_NAME = "ActiveTableWriteLock";
|
||||
|
||||
private static final long DEFAULT_LOCK_TIMEOUT = 5 * TimeUtil.MILLIS_PER_MINUTE;
|
||||
|
||||
private static ThreadLocal<PythonScript> threadLocalPythonScript = new ThreadLocal<PythonScript>() {
|
||||
|
||||
/*
|
||||
|
@ -288,7 +300,7 @@ public class ActiveTable {
|
|||
*/
|
||||
private void updateActiveTable(String siteId,
|
||||
List<ActiveTableRecord> newRecords, float offsetSecs) {
|
||||
if (newRecords.size() > 0) {
|
||||
if (!newRecords.isEmpty()) {
|
||||
ActiveTableMode mode = ActiveTableMode.PRACTICE;
|
||||
if (newRecords.get(0) instanceof OperationalActiveTableRecord) {
|
||||
mode = ActiveTableMode.OPERATIONAL;
|
||||
|
@ -299,36 +311,67 @@ public class ActiveTable {
|
|||
IPerformanceStatusHandler perfStat = PerformanceStatus
|
||||
.getHandler("ActiveTable");
|
||||
ITimer timer = TimeUtil.getTimer();
|
||||
timer.start();
|
||||
List<ActiveTableRecord> activeTable = getActiveTable(issueSiteId, mode);
|
||||
timer.stop();
|
||||
perfStat.logDuration("getActiveTable", timer.getElapsedTime());
|
||||
MergeResult result = null;
|
||||
ClusterTask writeLock = null;
|
||||
try {
|
||||
boolean logFirst = true;
|
||||
timer.start();
|
||||
do {
|
||||
if (logFirst) {
|
||||
statusHandler
|
||||
.info("updateActiveTable() waiting on lock ["
|
||||
+ ACTIVE_TABLE_LOCK_NAME + ":"
|
||||
+ mode.toString() + "].");
|
||||
logFirst = false;
|
||||
}
|
||||
writeLock = ClusterLockUtils.lock(ACTIVE_TABLE_LOCK_NAME,
|
||||
mode.toString(), new CurrentTimeClusterLockHandler(
|
||||
DEFAULT_LOCK_TIMEOUT, false), true);
|
||||
} while (!writeLock.getLockState().equals(LockState.SUCCESSFUL));
|
||||
statusHandler
|
||||
.info("updateActiveTable() obtained lock ["
|
||||
+ ACTIVE_TABLE_LOCK_NAME + ":"
|
||||
+ mode.toString() + "].");
|
||||
timer.stop();
|
||||
perfStat.logDuration("getLock", timer.getElapsedTime());
|
||||
|
||||
// get decoder sites to see if we need to backup active table
|
||||
Set<String> decoderSites = getDecoderSites(siteId);
|
||||
|
||||
// if any new record is from one of the decoder sites
|
||||
// we need to queue a backup
|
||||
for (ActiveTableRecord rec : newRecords) {
|
||||
if (decoderSites.contains(rec.getOfficeid())) {
|
||||
ActiveTableBackup.queue(mode, activeTable);
|
||||
break;
|
||||
timer.reset();
|
||||
timer.start();
|
||||
List<ActiveTableRecord> activeTable = getActiveTable(
|
||||
issueSiteId, mode);
|
||||
timer.stop();
|
||||
perfStat.logDuration("getActiveTable", timer.getElapsedTime());
|
||||
// get decoder sites to see if we need to backup active table
|
||||
Set<String> decoderSites = getDecoderSites(siteId);
|
||||
// if any new record is from one of the decoder sites
|
||||
// we need to queue a backup
|
||||
for (ActiveTableRecord rec : newRecords) {
|
||||
if (decoderSites.contains(rec.getOfficeid())) {
|
||||
ActiveTableBackup.queue(mode, activeTable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer.reset();
|
||||
timer.start();
|
||||
result = filterTable(siteId, activeTable, newRecords, mode,
|
||||
offsetSecs);
|
||||
timer.stop();
|
||||
perfStat.logDuration("filterTable", timer.getElapsedTime());
|
||||
timer.reset();
|
||||
timer.start();
|
||||
updateTable(siteId, result, mode);
|
||||
timer.stop();
|
||||
perfStat.logDuration("updateTable", timer.getElapsedTime());
|
||||
} finally {
|
||||
if (writeLock != null) {
|
||||
statusHandler.info("updateActiveTable() released lock ["
|
||||
+ ACTIVE_TABLE_LOCK_NAME + ":" + mode.toString()
|
||||
+ "].");
|
||||
ClusterLockUtils.unlock(writeLock, true);
|
||||
}
|
||||
}
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
MergeResult result = filterTable(siteId, activeTable, newRecords,
|
||||
mode, offsetSecs);
|
||||
timer.stop();
|
||||
perfStat.logDuration("filterTable", timer.getElapsedTime());
|
||||
|
||||
timer.reset();
|
||||
timer.start();
|
||||
updateTable(siteId, result, mode);
|
||||
timer.stop();
|
||||
perfStat.logDuration("updateTable", timer.getElapsedTime());
|
||||
if (result.changeList.size() > 0) {
|
||||
if (!result.changeList.isEmpty()) {
|
||||
sendNotification(mode, result.changeList, "VTECDecoder");
|
||||
}
|
||||
}
|
||||
|
@ -406,29 +449,28 @@ public class ActiveTable {
|
|||
ActiveTableMode mode, String phensigList, String action,
|
||||
String etn, Calendar currentTime, boolean requestValidTimes,
|
||||
boolean latestEtn) {
|
||||
synchronized (ActiveTable.class) {
|
||||
DatabaseQuery query = null;
|
||||
CoreDao dao = null;
|
||||
DatabaseQuery query = null;
|
||||
CoreDao dao = null;
|
||||
|
||||
if (mode.equals(ActiveTableMode.OPERATIONAL)) {
|
||||
query = new DatabaseQuery(OperationalActiveTableRecord.class);
|
||||
dao = operationalDao;
|
||||
} else {
|
||||
query = new DatabaseQuery(PracticeActiveTableRecord.class);
|
||||
dao = practiceDao;
|
||||
}
|
||||
if (mode.equals(ActiveTableMode.OPERATIONAL)) {
|
||||
query = new DatabaseQuery(OperationalActiveTableRecord.class);
|
||||
dao = operationalDao;
|
||||
} else {
|
||||
query = new DatabaseQuery(PracticeActiveTableRecord.class);
|
||||
dao = practiceDao;
|
||||
}
|
||||
|
||||
if (phensigList != null) {
|
||||
query.addQueryParam("phensig", phensigList, "in");
|
||||
}
|
||||
if (phensigList != null) {
|
||||
query.addQueryParam("phensig", phensigList, "in");
|
||||
}
|
||||
|
||||
if (action != null) {
|
||||
query.addQueryParam("act", action, "in");
|
||||
}
|
||||
if (action != null) {
|
||||
query.addQueryParam("act", action, "in");
|
||||
}
|
||||
|
||||
if (etn != null) {
|
||||
query.addQueryParam("etn", etn, "in");
|
||||
}
|
||||
if (etn != null) {
|
||||
query.addQueryParam("etn", etn, "in");
|
||||
}
|
||||
|
||||
if (requestValidTimes && (currentTime != null)) {
|
||||
// Current Time
|
||||
|
@ -442,18 +484,29 @@ public class ActiveTable {
|
|||
query.addOrder("etn", false);
|
||||
query.setMaxResults(1);
|
||||
}
|
||||
|
||||
query.addQueryParam("officeid", siteId, "in");
|
||||
|
||||
List<ActiveTableRecord> result = null;
|
||||
try {
|
||||
result = (List<ActiveTableRecord>) dao.queryByCriteria(query);
|
||||
} catch (DataAccessLayerException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error querying active table for site " + siteId, e);
|
||||
}
|
||||
return result;
|
||||
if (requestValidTimes && currentTime != null) {
|
||||
// Current Time
|
||||
query.addQueryParam("endTime", currentTime, "greater_than");
|
||||
}
|
||||
if (latestEtn && currentTime != null) {
|
||||
Calendar yearStart = Calendar.getInstance();
|
||||
yearStart.set(currentTime.get(Calendar.YEAR), Calendar.JANUARY, 1,
|
||||
0, 0);
|
||||
query.addQueryParam("issueTime", yearStart, "greater_than");
|
||||
query.addOrder("etn", false);
|
||||
query.setMaxResults(1);
|
||||
}
|
||||
|
||||
query.addQueryParam("officeid", siteId, "in");
|
||||
|
||||
List<ActiveTableRecord> result = null;
|
||||
try {
|
||||
result = (List<ActiveTableRecord>) dao.queryByCriteria(query);
|
||||
} catch (DataAccessLayerException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error querying active table for site " + siteId, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -466,23 +519,12 @@ public class ActiveTable {
|
|||
*/
|
||||
private static void updateTable(String siteId, MergeResult changes,
|
||||
ActiveTableMode mode) {
|
||||
synchronized (ActiveTable.class) {
|
||||
List<ActiveTableRecord> updated = changes.updatedList;
|
||||
List<ActiveTableRecord> purged = changes.purgedList;
|
||||
List<ActiveTableRecord> updated = changes.updatedList;
|
||||
List<ActiveTableRecord> purged = changes.purgedList;
|
||||
|
||||
CoreDao dao = null;
|
||||
if (mode.equals(ActiveTableMode.OPERATIONAL)) {
|
||||
dao = operationalDao;
|
||||
} else {
|
||||
dao = practiceDao;
|
||||
}
|
||||
for (ActiveTableRecord update : updated) {
|
||||
dao.saveOrUpdate(update);
|
||||
}
|
||||
for (ActiveTableRecord delete : purged) {
|
||||
dao.delete(delete);
|
||||
}
|
||||
}
|
||||
CoreDao dao = (ActiveTableMode.OPERATIONAL.equals(mode)) ? operationalDao
|
||||
: practiceDao;
|
||||
dao.bulkSaveOrUpdateAndDelete(updated, purged);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -553,22 +595,23 @@ public class ActiveTable {
|
|||
ActiveTableMode tableName, List<ActiveTableRecord> newRecords,
|
||||
float timeOffset, boolean makeBackup, boolean runIngestAT,
|
||||
String xmlSource) throws JepException {
|
||||
String scriptName = runIngestAT ? "ingestAT.py" : "MergeVTEC.py";
|
||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||
LocalizationContext commonCx = pathMgr.getContext(
|
||||
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
|
||||
String scriptPath = pathMgr.getFile(commonCx,
|
||||
FileUtil.join(ActiveTablePyIncludeUtil.VTEC, scriptName))
|
||||
.getPath();
|
||||
String pythonIncludePath = PyUtil.buildJepIncludePath(
|
||||
ActiveTablePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
ActiveTablePyIncludeUtil.getVtecIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getIscScriptsIncludePath());
|
||||
|
||||
MergeResult result = null;
|
||||
PythonScript script = null;
|
||||
ClusterTask writeLock = null;
|
||||
try {
|
||||
String scriptName = runIngestAT ? "ingestAT.py" : "MergeVTEC.py";
|
||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||
LocalizationContext commonCx = pathMgr.getContext(
|
||||
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
|
||||
String scriptPath = pathMgr.getFile(commonCx,
|
||||
FileUtil.join(ActiveTablePyIncludeUtil.VTEC, scriptName))
|
||||
.getPath();
|
||||
String pythonIncludePath = PyUtil.buildJepIncludePath(
|
||||
ActiveTablePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
ActiveTablePyIncludeUtil.getVtecIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId),
|
||||
ActiveTablePyIncludeUtil.getIscScriptsIncludePath());
|
||||
|
||||
try {
|
||||
script = new PythonScript(scriptPath, pythonIncludePath,
|
||||
ActiveTable.class.getClassLoader());
|
||||
|
@ -578,6 +621,23 @@ public class ActiveTable {
|
|||
throw e;
|
||||
}
|
||||
|
||||
boolean logFirst = true;
|
||||
do {
|
||||
if (logFirst) {
|
||||
statusHandler.info("mergeRemoteTable() waiting on lock ["
|
||||
+ ACTIVE_TABLE_LOCK_NAME + ":"
|
||||
+ tableName.toString() + "].");
|
||||
logFirst = false;
|
||||
}
|
||||
writeLock = ClusterLockUtils.lock(ACTIVE_TABLE_LOCK_NAME,
|
||||
tableName.toString(),
|
||||
new CurrentTimeClusterLockHandler(DEFAULT_LOCK_TIMEOUT,
|
||||
false), true);
|
||||
} while (!writeLock.getLockState().equals(LockState.SUCCESSFUL));
|
||||
statusHandler.info("mergeRemoteTable() obtained lock ["
|
||||
+ ACTIVE_TABLE_LOCK_NAME + ":" + tableName.toString()
|
||||
+ "].");
|
||||
|
||||
try {
|
||||
String site4Char = SiteMap.getInstance().getSite4LetterId(
|
||||
siteId);
|
||||
|
@ -589,6 +649,7 @@ public class ActiveTable {
|
|||
args.put("newRecords", newRecords);
|
||||
args.put("drt", timeOffset);
|
||||
args.put("makeBackups", makeBackup);
|
||||
args.put("atChangeLog", changeLog);
|
||||
if (runIngestAT) {
|
||||
args.put("xmlIncoming", xmlSource);
|
||||
}
|
||||
|
@ -600,18 +661,26 @@ public class ActiveTable {
|
|||
"Error merging active table", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
updateTable(siteId, result, tableName);
|
||||
}
|
||||
} finally {
|
||||
if (writeLock != null) {
|
||||
statusHandler.info("mergeRemoteTable() released lock ["
|
||||
+ ACTIVE_TABLE_LOCK_NAME + ":" + tableName.toString()
|
||||
+ "].");
|
||||
ClusterLockUtils.unlock(writeLock, true);
|
||||
}
|
||||
|
||||
if (script != null) {
|
||||
script.dispose();
|
||||
script = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
updateTable(siteId, result, tableName);
|
||||
if (!result.changeList.isEmpty()) {
|
||||
sendNotification(tableName, result.changeList, "MergeVTEC");
|
||||
}
|
||||
if ((result != null) && (!result.changeList.isEmpty())) {
|
||||
sendNotification(tableName, result.changeList, "MergeVTEC");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
# 06/17/13 #3296 randerso Moved active table backup and purging
|
||||
# to a separate thread in java.
|
||||
# Added performance logging
|
||||
# 02/05/15 #4099 randerso Changed log level of year-end issuance tweak
|
||||
#
|
||||
|
||||
import time
|
||||
|
@ -122,7 +123,7 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
|
|||
if oldYear < newYear:
|
||||
if (newR['act'] == "EXP" and newR['endTime'] == oldR['endTime']) or \
|
||||
self.__overlaps((oldR['startTime'],oldR['endTime']), (newR['startTime'],newR['endTime'])):
|
||||
LogStream.logVerbose("Reset issuance time to last year:",
|
||||
LogStream.logEvent("Reset issuance time to last year:",
|
||||
"\nNewRec: ", self.printEntry(newR),
|
||||
"OldRec: ", self.printEntry(oldR))
|
||||
newR['issueTime'] = lastYearIssueTime
|
||||
|
|
|
@ -35,8 +35,10 @@
|
|||
# 01/24/14 #2504 randerso change to use iscUtil.getLogger for consistency
|
||||
# 03/25/14 #2884 randerso Added xxxid to VTECChange
|
||||
# 05/15/14 #3157 dgilling Support multiple TPC and SPC sites.
|
||||
# 03/04/2015 #4129 randerso Log the active table changes at info level
|
||||
# in the active table change log
|
||||
#
|
||||
|
||||
##
|
||||
|
||||
import copy
|
||||
import cPickle
|
||||
|
@ -64,7 +66,7 @@ from com.raytheon.uf.common.activetable import VTECPartners as JavaVTECPartners
|
|||
class MergeVTEC(VTECTableUtil.VTECTableUtil):
|
||||
|
||||
def __init__(self, activeTable, activeTableMode, newRecords, offsetSecs=0.0,
|
||||
makeBackups=True, logger=None):
|
||||
makeBackups=True, logger=None, atChangeLog=None):
|
||||
# activeTable - current activeTable records
|
||||
# activeTableMode - which table is being modified--OPERATIONAL or PRACTICE
|
||||
# newRecords - records to merge in to activeTable
|
||||
|
@ -125,7 +127,7 @@ class MergeVTEC(VTECTableUtil.VTECTableUtil):
|
|||
self._log.info("Other Table squeezed size: %d", len(otherTable))
|
||||
|
||||
#merge the tables
|
||||
updatedTable, toDelete, changes = self._mergeTable(activeTable, otherTable)
|
||||
updatedTable, toDelete, changes = self._mergeTable(activeTable, otherTable, atChangeLog)
|
||||
self._log.info("Updated Active Table size: %d", len(updatedTable))
|
||||
updatedTable, tossRecordsMerged = vts.squeeze(updatedTable)
|
||||
self._log.info("Updated Active Table squeeze size: %d",
|
||||
|
@ -161,7 +163,7 @@ class MergeVTEC(VTECTableUtil.VTECTableUtil):
|
|||
|
||||
# merges the active and other table together and returns the merged
|
||||
# table along with the list of changes that occurred.
|
||||
def _mergeTable(self, activeTable, otherTable):
|
||||
def _mergeTable(self, activeTable, otherTable, atChangeLog):
|
||||
changes = []
|
||||
purges = []
|
||||
compare = ['id', 'phen', 'sig', 'officeid', 'etn', 'pil']
|
||||
|
@ -342,30 +344,31 @@ class MergeVTEC(VTECTableUtil.VTECTableUtil):
|
|||
changes.append(chgRec)
|
||||
|
||||
# log the changes
|
||||
if len(missingEntriesAct):
|
||||
self._log.debug("Active Missing entries added: %s",
|
||||
self.printActiveTable(missingEntriesAct, 1))
|
||||
if len(newReplaceEntriesAct):
|
||||
self._log.debug("Active Replacement entries (new): %s",
|
||||
self.printActiveTable(newReplaceEntriesAct, 1))
|
||||
if len(oldReplaceEntriesAct):
|
||||
self._log.debug("Active Entries Replaced (old): %s",
|
||||
self.printActiveTable(oldReplaceEntriesAct, 1))
|
||||
if len(missingEntriesPast):
|
||||
self._log.debug("Past Missing entries added %s",
|
||||
self.printActiveTable(missingEntriesPast, 1))
|
||||
if len(newReplaceEntriesPast):
|
||||
self._log.debug("Past Replacement entries (new): %s",
|
||||
self.printActiveTable(newReplaceEntriesPast, 1))
|
||||
if len(oldReplaceEntriesPast):
|
||||
self._log.debug("Past Entries Replaced (old): %s",
|
||||
self.printActiveTable(oldReplaceEntriesPast, 1))
|
||||
if len(ignoredNewReplaceAct):
|
||||
self._log.debug("Ignored Different Year Issuance (new): %s",
|
||||
self.printActiveTable(ignoredNewReplaceAct, 1))
|
||||
self._log.debug("Ignored Different Year Issuance (old): %s",
|
||||
self.printActiveTable(ignoredOldReplaceAct, 1))
|
||||
self._log.debug("Table Changes: %s", changes)
|
||||
if atChangeLog is not None:
|
||||
if len(missingEntriesAct):
|
||||
atChangeLog.info("Active Missing entries added: " +
|
||||
self.printActiveTable(missingEntriesAct, 1))
|
||||
if len(newReplaceEntriesAct):
|
||||
atChangeLog.info("Active Replacement entries (new): " +
|
||||
self.printActiveTable(newReplaceEntriesAct, 1))
|
||||
if len(oldReplaceEntriesAct):
|
||||
atChangeLog.info("Active Entries Replaced (old): " +
|
||||
self.printActiveTable(oldReplaceEntriesAct, 1))
|
||||
if len(missingEntriesPast):
|
||||
atChangeLog.info("Past Missing entries added " +
|
||||
self.printActiveTable(missingEntriesPast, 1))
|
||||
if len(newReplaceEntriesPast):
|
||||
atChangeLog.info("Past Replacement entries (new): " +
|
||||
self.printActiveTable(newReplaceEntriesPast, 1))
|
||||
if len(oldReplaceEntriesPast):
|
||||
atChangeLog.info("Past Entries Replaced (old): " +
|
||||
self.printActiveTable(oldReplaceEntriesPast, 1))
|
||||
if len(ignoredNewReplaceAct):
|
||||
atChangeLog.info("Ignored Different Year Issuance (new): " +
|
||||
self.printActiveTable(ignoredNewReplaceAct, 1))
|
||||
atChangeLog.info("Ignored Different Year Issuance (old): " +
|
||||
self.printActiveTable(ignoredOldReplaceAct, 1))
|
||||
atChangeLog.info("Table Changes: " + str(changes))
|
||||
|
||||
purges.extend(oldReplaceEntriesAct)
|
||||
purges.extend(oldReplaceEntriesPast)
|
||||
|
@ -411,7 +414,7 @@ class MergeVTEC(VTECTableUtil.VTECTableUtil):
|
|||
return iscUtil.getLogger("MergeVTEC", logLevel=logging.INFO)
|
||||
|
||||
def merge(activeTable, activeTableMode, newRecords, drt=0.0, makeBackups=True,
|
||||
logger=None):
|
||||
logger=None, atChangeLog=None):
|
||||
pyActive = []
|
||||
for i in range(activeTable.size()):
|
||||
pyActive.append(ActiveTableRecord.ActiveTableRecord(activeTable.get(i)))
|
||||
|
@ -420,7 +423,7 @@ def merge(activeTable, activeTableMode, newRecords, drt=0.0, makeBackups=True,
|
|||
for i in range(newRecords.size()):
|
||||
pyNew.append(ActiveTableRecord.ActiveTableRecord(newRecords.get(i)))
|
||||
|
||||
decoder = MergeVTEC(pyActive, activeTableMode, pyNew, drt, makeBackups, logger)
|
||||
decoder = MergeVTEC(pyActive, activeTableMode, pyNew, drt, makeBackups, logger, atChangeLog)
|
||||
mergeResults = decoder.getMergeResults()
|
||||
decoder = None
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# 12/12/14 4953 randerso Initial Creation.
|
||||
# 03/10/2015 #4129 randerso Fixed error when no TCV files were found
|
||||
#
|
||||
##
|
||||
import glob, os, subprocess, time
|
||||
|
@ -69,11 +70,20 @@ def packageTCVFiles(siteList, fileName, logger):
|
|||
for siteID in siteList:
|
||||
tcvDir = os.path.join(siteID, "gfe", "tcvAdvisories")
|
||||
|
||||
found = False
|
||||
for fileType in ["*.json", "*.allCAN"]:
|
||||
path = os.path.join(tcvDir, fileType)
|
||||
if len(glob.glob(os.path.join(siteDir, path))) > 0:
|
||||
cmd += " " + path
|
||||
|
||||
logger.debug("cmd: '" + cmd + "'")
|
||||
subprocess.check_call([cmd], shell=True)
|
||||
|
||||
found = True
|
||||
|
||||
if found:
|
||||
logger.info("cmd: '" + cmd + "'")
|
||||
try:
|
||||
subprocess.check_call([cmd], shell=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error("cmd returned error code: ", e.returncode, e.output)
|
||||
except:
|
||||
loggger.exception("cmd threw exception")
|
||||
|
||||
return found
|
|
@ -28,7 +28,9 @@
|
|||
# ------------ ---------- ----------- --------------------------
|
||||
# 02/13/13 1447 dgilling Initial Creation.
|
||||
# 01/24/14 2504 randerso change to use iscUtil.getLogger for consistency
|
||||
# 03/04/2015 4129 randerso Pass active table change logger through to MergeVtec.merge
|
||||
#
|
||||
##
|
||||
|
||||
|
||||
import os
|
||||
|
@ -48,7 +50,7 @@ def init_logging():
|
|||
logger = iscUtil.getLogger("ingestAT", logLevel=logging.INFO)
|
||||
|
||||
|
||||
def execute_ingest_at(incomingRecords, activeTable, atName, ztime, makeBackups, xmlIncoming):
|
||||
def execute_ingest_at(incomingRecords, activeTable, atName, ztime, makeBackups, xmlIncoming, atChangeLog):
|
||||
# log the source of this data
|
||||
if xmlIncoming is not None:
|
||||
irt = IrtAccess.IrtAccess("")
|
||||
|
@ -63,20 +65,20 @@ def execute_ingest_at(incomingRecords, activeTable, atName, ztime, makeBackups,
|
|||
results = None
|
||||
try:
|
||||
results = MergeVTEC.merge(activeTable, atName, incomingRecords, ztime, makeBackups,
|
||||
logger)
|
||||
logger, atChangeLog)
|
||||
except:
|
||||
logger.exception("MergeVTEC fail:")
|
||||
return results
|
||||
|
||||
def runFromJava(activeTable, activeTableMode, newRecords, drt, makeBackups,
|
||||
xmlIncoming):
|
||||
xmlIncoming, atChangeLog=None):
|
||||
init_logging()
|
||||
|
||||
logger.info('************* ingestAT ************************')
|
||||
startT = time.time()
|
||||
|
||||
results = execute_ingest_at(newRecords, activeTable, activeTableMode, drt,
|
||||
makeBackups, xmlIncoming)
|
||||
makeBackups, xmlIncoming, atChangeLog=atChangeLog)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Finish
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
# 02/06/13 1447 dgilling Initial Creation.
|
||||
# 01/24/14 2504 randerso change to use iscUtil.getLogger for consistency
|
||||
# 05/15/14 #3157 dgilling Support multiple TPC and SPC sites.
|
||||
# 03/10/2015 #4129 randerso Refactored server selection code into a reusable method
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -37,7 +38,7 @@ import os
|
|||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import xml.etree.ElementTree as ET
|
||||
from xml.etree import ElementTree
|
||||
|
||||
import IrtAccess
|
||||
import siteConfig
|
||||
|
@ -115,125 +116,23 @@ def execute_request_at(serverHost, serverPort, serverProtocol, mhsid, siteID, an
|
|||
buf = cPickle.dumps(data)
|
||||
fp.write(buf)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Assemble XML source/destination document
|
||||
#--------------------------------------------------------------------
|
||||
msgSendDest = [] #list of mhs sites to send request
|
||||
sourceServer = {'mhsid' : mhsid,
|
||||
'host' : serverHost,
|
||||
'port' : serverPort,
|
||||
'protocol': serverProtocol,
|
||||
'site' : siteID}
|
||||
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf)
|
||||
iscE = ET.Element('isc')
|
||||
# this is the requestor of the data
|
||||
sourceServer = {'mhsid': mhsid, 'host': serverHost, 'port': serverPort,
|
||||
'protocol': serverProtocol, 'site': siteID}
|
||||
irt.addSourceXML(iscE, sourceServer)
|
||||
logger.info("Requesting Server: " + irt.printServerInfo(sourceServer))
|
||||
|
||||
# who is running the domains requested?
|
||||
sites = VTECPartners.VTEC_TABLE_REQUEST_SITES
|
||||
if not sites:
|
||||
logger.error('No sites defined for VTEC_TABLE_REQUEST_SITES')
|
||||
sys.exit(1)
|
||||
|
||||
status, xml = irt.getServers(sites)
|
||||
if not status:
|
||||
logger.error('Failure to getServers from IRT')
|
||||
sys.exit(1)
|
||||
|
||||
# decode the XML
|
||||
try:
|
||||
serverTree = ET.ElementTree(ET.XML(xml))
|
||||
serversE = serverTree.getroot()
|
||||
except:
|
||||
logger.exception("Malformed XML on getServers()")
|
||||
sys.exit(1)
|
||||
|
||||
if serversE.tag != "servers":
|
||||
logger.error("Servers packet missing from web server")
|
||||
sys.exit(1)
|
||||
|
||||
# process each requested domain returned to us
|
||||
chosenServers = []
|
||||
matchingServers = []
|
||||
for domainE in serversE:
|
||||
if domainE.tag != "domain":
|
||||
continue
|
||||
servers = [] #list of servers for this domain
|
||||
|
||||
# decode each server in the domain
|
||||
for addressE in domainE.getchildren():
|
||||
info = irt.decodeXMLAddress(addressE)
|
||||
if info is None:
|
||||
continue #not address tag
|
||||
servers.append(info)
|
||||
matchingServers.append(info)
|
||||
|
||||
# server search list in priority. The px3 entries are used for
|
||||
# dual domain for AFC.
|
||||
hp = [('dx4','98000000'),('px3', '98000000'), ('dx4','98000001'),
|
||||
('px3', '98000001')]
|
||||
|
||||
# choose one server from this domain, find first dx4, 98000000
|
||||
# try to use one with the same mhsidDest as the site, which
|
||||
# would be the primary operational GFE. Note that the px3 entries
|
||||
# are for AFC.
|
||||
found = False
|
||||
for matchServer, matchPort in hp:
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort and server['mhsid'] == siteID:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# find first dx4, 98000000, but perhaps a different mhsid
|
||||
# this is probably not the primary operational GFE
|
||||
if not found:
|
||||
for matchServer, matchPort in hp:
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# if didn't find standard one, then take the first one, but don't
|
||||
# take ourselves unless we are the only one.
|
||||
if not found and servers:
|
||||
for server in servers:
|
||||
if server['mhsid'] != mhsid and server['host'] != serverHost \
|
||||
and server['port'] != serverPort and \
|
||||
server['mhsid'] != siteID:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
if not found:
|
||||
chosenServers.append(servers[0])
|
||||
if servers[0]['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(servers[0]['mhsid'])
|
||||
|
||||
# Display the set of matching servers
|
||||
s = "Matching Servers:"
|
||||
for x in matchingServers:
|
||||
s += "\n" + irt.printServerInfo(x)
|
||||
logger.info(s)
|
||||
|
||||
# Display the chosen set of servers
|
||||
s = "Chosen Servers:"
|
||||
for x in chosenServers:
|
||||
s += "\n" + irt.printServerInfo(x)
|
||||
logger.info(s)
|
||||
|
||||
irt.addDestinationXML(iscE, chosenServers)
|
||||
destSites = VTECPartners.VTEC_TABLE_REQUEST_SITES
|
||||
if not destSites:
|
||||
raise Exception('No destSites defined for VTEC_TABLE_REQUEST_SITES')
|
||||
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf, logger=logger)
|
||||
msgSendDest, xml = irt.createDestinationXML(destSites, sourceServer)
|
||||
|
||||
# create the XML file
|
||||
with tempfile.NamedTemporaryFile(suffix='.xml', dir=tempdir, delete=False) as fd:
|
||||
fnameXML = fd.name
|
||||
fd.write(ET.tostring(iscE))
|
||||
fd.write(ElementTree.tostring(xml))
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Now send the message
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# 12/05/14 4953 randerso Initial Creation.
|
||||
# 03/10/2015 #4129 randerso Refactored server selection code into a reusable method
|
||||
#
|
||||
##
|
||||
import os, errno, tempfile
|
||||
|
@ -43,134 +44,7 @@ def init_logging():
|
|||
import iscUtil
|
||||
import logging
|
||||
global logger
|
||||
logger = iscUtil.getLogger("requestTCV", logLevel=logging.DEBUG)
|
||||
|
||||
def createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger):
|
||||
#--------------------------------------------------------------------
|
||||
# Assemble XML source/destination document
|
||||
#--------------------------------------------------------------------
|
||||
msgSendDest = [] #list of mhs sites to send request
|
||||
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf)
|
||||
iscE = ElementTree.Element('isc')
|
||||
# this is the requestor of the data
|
||||
sourceServer = {'mhsid' : mhsid,
|
||||
'host' : host,
|
||||
'port' : port,
|
||||
'protocol': protocol,
|
||||
'site' : siteID}
|
||||
irt.addSourceXML(iscE, sourceServer)
|
||||
logger.info("Requesting Server: " + irt.printServerInfo(sourceServer))
|
||||
|
||||
# who is running the domains requested?
|
||||
sites = VTECPartners.VTEC_TABLE_REQUEST_SITES
|
||||
if not sites:
|
||||
logger.error('No sites defined for VTEC_TABLE_REQUEST_SITES')
|
||||
sys.exit(1)
|
||||
|
||||
status, xml = irt.getServers(sites)
|
||||
if not status:
|
||||
logger.error('Failure to getServers from IRT')
|
||||
sys.exit(1)
|
||||
|
||||
# decode the XML
|
||||
try:
|
||||
serverTree = ElementTree.ElementTree(ElementTree.XML(xml))
|
||||
serversE = serverTree.getroot()
|
||||
except:
|
||||
logger.exception("Malformed XML on getServers()")
|
||||
sys.exit(1)
|
||||
|
||||
if serversE.tag != "servers":
|
||||
logger.error("Servers packet missing from web server")
|
||||
sys.exit(1)
|
||||
|
||||
# process each requested domain returned to us
|
||||
chosenServers = []
|
||||
matchingServers = []
|
||||
for domainE in serversE:
|
||||
if domainE.tag != "domain":
|
||||
continue
|
||||
servers = [] #list of servers for this domain
|
||||
|
||||
# decode each server in the domain
|
||||
for addressE in domainE.getchildren():
|
||||
info = irt.decodeXMLAddress(addressE)
|
||||
if info is None:
|
||||
continue #not address tag
|
||||
|
||||
# remove unneeded keys
|
||||
for key in ['parms', 'area', 'domain']:
|
||||
if info.has_key(key):
|
||||
del info[key]
|
||||
|
||||
servers.append(info)
|
||||
matchingServers.append(info)
|
||||
|
||||
# server search list in priority. The px3 entries are used for
|
||||
# dual domain for AFC.
|
||||
hp = [('dx4','98000000'),('px3', '98000000'), ('dx4','98000001'),
|
||||
('px3', '98000001')]
|
||||
|
||||
# choose one server from this domain, find first dx4, 98000000
|
||||
# try to use one with the same mhsidDest as the site, which
|
||||
# would be the primary operational GFE. Note that the px3 entries
|
||||
# are for AFC.
|
||||
found = False
|
||||
for matchServer, matchPort in hp:
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort and server['mhsid'] == siteID:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# find first dx4, 98000000, but perhaps a different mhsid
|
||||
# this is probably not the primary operational GFE
|
||||
if not found:
|
||||
for matchServer, matchPort in hp:
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# if didn't find standard one, then take the first one, but don't
|
||||
# take ourselves unless we are the only one.
|
||||
if not found and servers:
|
||||
for server in servers:
|
||||
if server['mhsid'] != mhsid and server['host'] != host \
|
||||
and server['port'] != port and \
|
||||
server['mhsid'] != siteID:
|
||||
chosenServers.append(server)
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
if not found:
|
||||
chosenServers.append(server)
|
||||
if servers[0]['mhsid'] not in msgSendDest:
|
||||
msgSendDest.append(servers[0]['mhsid'])
|
||||
|
||||
# Display the set of matching servers
|
||||
s = "Matching Servers:"
|
||||
for x in matchingServers:
|
||||
s += "\n" + irt.printServerInfo(x)
|
||||
logger.info(s)
|
||||
|
||||
# Display the chosen set of servers
|
||||
s = "Chosen Servers:"
|
||||
for x in chosenServers:
|
||||
s += "\n" + irt.printServerInfo(x)
|
||||
logger.info(s)
|
||||
|
||||
irt.addDestinationXML(iscE, chosenServers)
|
||||
|
||||
return msgSendDest, iscE
|
||||
logger = iscUtil.getLogger("requestTCV", logLevel=logging.INFO)
|
||||
|
||||
def runFromJava(siteID, config):
|
||||
import siteConfig
|
||||
|
@ -191,8 +65,19 @@ def runFromJava(siteID, config):
|
|||
if e.errno != errno.EEXIST:
|
||||
logger.warn("%s: '%s'" % (e.strerror,e.filename))
|
||||
|
||||
sourceServer = {'mhsid' : mhsid,
|
||||
'host' : host,
|
||||
'port' : port,
|
||||
'protocol': protocol,
|
||||
'site' : siteID}
|
||||
try:
|
||||
msgSendDest, xml = createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger)
|
||||
destSites = VTECPartners.VTEC_TABLE_REQUEST_SITES
|
||||
if not destSites:
|
||||
raise Exception('No destSites defined for VTEC_TABLE_REQUEST_SITES')
|
||||
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf, logger=logger)
|
||||
msgSendDest, xml = irt.createDestinationXML(destSites, sourceServer)
|
||||
|
||||
# create the XML file
|
||||
with tempfile.NamedTemporaryFile(suffix='.xml', dir=tempdir, delete=False) as fd:
|
||||
fnameXML = fd.name
|
||||
|
@ -204,7 +89,6 @@ def runFromJava(siteID, config):
|
|||
|
||||
if len(msgSendDest) > 0:
|
||||
# Now send the message
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf)
|
||||
irt.transmitFiles("GET_TCV_FILES", msgSendDest, mhsid, [fnameXML], xmtScript)
|
||||
except:
|
||||
logger.exception('Error requesting TCV files for site: ' + siteID)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
# 02/08/13 1447 dgilling Initial Creation.
|
||||
# 01/24/14 2504 randerso change to use iscUtil.getLogger for consistency
|
||||
# 05/15/14 #3157 dgilling Support multiple TPC and SPC sites.
|
||||
# 03/10/2015 #4129 randerso Removed sys.exit() call
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -36,11 +37,10 @@
|
|||
import cPickle
|
||||
import gzip
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import tempfile
|
||||
import stat
|
||||
import xml.etree.ElementTree as ET
|
||||
from xml.etree import ElementTree
|
||||
|
||||
import IrtAccess
|
||||
import JUtil
|
||||
|
@ -170,7 +170,7 @@ def execute_send_at(myServerHost, myServerPort, myServerProtocol,
|
|||
#--------------------------------------------------------------------
|
||||
# Create the destination XML file
|
||||
#--------------------------------------------------------------------
|
||||
iscOut = ET.Element('isc')
|
||||
iscOut = ElementTree.Element('isc')
|
||||
irt.addSourceXML(iscOut, myServer)
|
||||
|
||||
destServers = []
|
||||
|
@ -179,7 +179,7 @@ def execute_send_at(myServerHost, myServerPort, myServerProtocol,
|
|||
with open(xmlIncoming,'rb') as fd:
|
||||
xml = fd.read()
|
||||
os.remove(xmlIncoming)
|
||||
reqTree = ET.ElementTree(ET.XML(xml))
|
||||
reqTree = ElementTree.ElementTree(ElementTree.XML(xml))
|
||||
sourceE = reqTree.find('source')
|
||||
for addressE in sourceE.getchildren():
|
||||
destServer = irt.decodeXMLAddress(addressE)
|
||||
|
@ -214,7 +214,7 @@ def execute_send_at(myServerHost, myServerPort, myServerProtocol,
|
|||
tempdir = os.path.join(siteConfig.GFESUITE_HOME, "products", "ATBL")
|
||||
with tempfile.NamedTemporaryFile(suffix='.xml', dir=tempdir, delete=False) as fd:
|
||||
fnameXML = fd.name
|
||||
fd.write(ET.tostring(iscOut))
|
||||
fd.write(ElementTree.tostring(iscOut))
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Send it
|
||||
|
@ -285,7 +285,7 @@ def runFromJava(myServerHost, myServerPort, myServerProtocol, myServerMHSID,
|
|||
xmtScript)
|
||||
except:
|
||||
logger.exception('Error in sendAT:')
|
||||
sys.exit(1)
|
||||
raise
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Finish
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# 12/05/14 4953 randerso Initial Creation.
|
||||
# 03/10/2015 #4129 randerso Refactored server selection code into a reusable method
|
||||
#
|
||||
##
|
||||
import os, errno, tempfile
|
||||
|
@ -44,136 +45,9 @@ def init_logging():
|
|||
import iscUtil
|
||||
import logging
|
||||
global logger
|
||||
logger = iscUtil.getLogger("sendTCV", logLevel=logging.DEBUG)
|
||||
logger = iscUtil.getLogger("sendTCV", logLevel=logging.INFO)
|
||||
|
||||
|
||||
def createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger):
|
||||
#--------------------------------------------------------------------
|
||||
# Assemble XML source/destination document
|
||||
#--------------------------------------------------------------------
|
||||
msgSendDest = [] #list of mhs sites to send request
|
||||
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf)
|
||||
iscE = ElementTree.Element('isc')
|
||||
# this is the requestor of the data
|
||||
sourceServer = {'mhsid' : mhsid,
|
||||
'host' : host,
|
||||
'port' : port,
|
||||
'protocol': protocol,
|
||||
'site' : siteID}
|
||||
irt.addSourceXML(iscE, sourceServer)
|
||||
logger.info("Requesting Server: " + irt.printServerInfo(sourceServer))
|
||||
|
||||
# who is running the domains requested?
|
||||
sites = VTECPartners.VTEC_TABLE_REQUEST_SITES
|
||||
if not sites:
|
||||
logger.error('No sites defined for VTEC_TABLE_REQUEST_SITES')
|
||||
sys.exit(1)
|
||||
|
||||
status, xml = irt.getServers(sites)
|
||||
if not status:
|
||||
logger.error('Failure to getServers from IRT')
|
||||
sys.exit(1)
|
||||
|
||||
# decode the XML
|
||||
try:
|
||||
serverTree = ElementTree.ElementTree(ElementTree.XML(xml))
|
||||
serversE = serverTree.getroot()
|
||||
except:
|
||||
logger.exception("Malformed XML on getServers()")
|
||||
sys.exit(1)
|
||||
|
||||
if serversE.tag != "servers":
|
||||
logger.error("Servers packet missing from web server")
|
||||
sys.exit(1)
|
||||
|
||||
# process each requested domain returned to us
|
||||
chosenServers = []
|
||||
matchingServers = []
|
||||
for domainE in serversE:
|
||||
if domainE.tag != "domain":
|
||||
continue
|
||||
servers = [] #list of servers for this domain
|
||||
|
||||
# decode each server in the domain
|
||||
for addressE in domainE.getchildren():
|
||||
info = irt.decodeXMLAddress(addressE)
|
||||
if info is None:
|
||||
continue #not address tag
|
||||
|
||||
# remove unneeded keys
|
||||
for key in ['parms', 'area', 'domain']:
|
||||
if info.has_key(key):
|
||||
del info[key]
|
||||
|
||||
servers.append(info)
|
||||
matchingServers.append(info)
|
||||
|
||||
# server search list in priority. The px3 entries are used for
|
||||
# dual domain for AFC.
|
||||
hp = [('dx4','98000000'),('px3', '98000000'), ('dx4','98000001'),
|
||||
('px3', '98000001')]
|
||||
|
||||
# choose one server from this domain, find first dx4, 98000000
|
||||
# try to use one with the same mhsidDest as the site, which
|
||||
# would be the primary operational GFE. Note that the px3 entries
|
||||
# are for AFC.
|
||||
found = False
|
||||
for matchServer, matchPort in hp:
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort and server['mhsid'] == siteID:
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
chosenServers.append(server)
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# find first dx4, 98000000, but perhaps a different mhsid
|
||||
# this is probably not the primary operational GFE
|
||||
if not found:
|
||||
for matchServer, matchPort in hp:
|
||||
for server in servers:
|
||||
if server['host'][0:3] == matchServer and \
|
||||
server['port'] == matchPort:
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
chosenServers.append(server)
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
break
|
||||
|
||||
# if didn't find standard one, then take the first one, but don't
|
||||
# take ourselves unless we are the only one.
|
||||
if not found and servers:
|
||||
for server in servers:
|
||||
if server['mhsid'] != mhsid and server['host'] != host \
|
||||
and server['port'] != port and \
|
||||
server['mhsid'] != siteID:
|
||||
if server['mhsid'] not in msgSendDest:
|
||||
chosenServers.append(server)
|
||||
msgSendDest.append(server['mhsid'])
|
||||
found = True
|
||||
if not found:
|
||||
if servers[0]['mhsid'] not in msgSendDest:
|
||||
chosenServers.append(servers[0])
|
||||
msgSendDest.append(servers[0]['mhsid'])
|
||||
|
||||
# Display the set of matching servers
|
||||
s = "Matching Servers:"
|
||||
for x in matchingServers:
|
||||
s += "\n" + irt.printServerInfo(x)
|
||||
logger.info(s)
|
||||
|
||||
# Display the chosen set of servers
|
||||
s = "Chosen Servers:"
|
||||
for x in chosenServers:
|
||||
s += "\n" + irt.printServerInfo(x)
|
||||
logger.info(s)
|
||||
|
||||
irt.addDestinationXML(iscE, chosenServers)
|
||||
|
||||
return msgSendDest, iscE
|
||||
|
||||
def runFromJava(siteID, config):
|
||||
import siteConfig
|
||||
host = str(config.getServerHost())
|
||||
|
@ -201,25 +75,37 @@ def runFromJava(siteID, config):
|
|||
with tempfile.NamedTemporaryFile(suffix='.sendtcv', dir=tcvProductsDir, delete=False) as fp:
|
||||
fname = fp.name
|
||||
|
||||
try:
|
||||
TCVUtil.packageTCVFiles([siteID], fname, logger)
|
||||
sourceServer = {'mhsid' : mhsid,
|
||||
'host' : host,
|
||||
'port' : port,
|
||||
'protocol': protocol,
|
||||
'site' : siteID}
|
||||
|
||||
msgSendDest, xml = createDestinationXML(siteID, host, port, protocol, mhsid, ancf, bncf, logger)
|
||||
|
||||
# create the XML file
|
||||
with tempfile.NamedTemporaryFile(suffix='.xml', dir=tcvProductsDir, delete=False) as fd:
|
||||
fnameXML = fd.name
|
||||
fd.write(ElementTree.tostring(xml))
|
||||
|
||||
# don't send to ourselves
|
||||
if mhsid in msgSendDest:
|
||||
msgSendDest.remove(mhsid)
|
||||
try:
|
||||
if TCVUtil.packageTCVFiles([siteID], fname, logger):
|
||||
|
||||
destSites = VTECPartners.VTEC_TABLE_REQUEST_SITES
|
||||
if not destSites:
|
||||
raise Exception('No destSites defined for VTEC_TABLE_REQUEST_SITES')
|
||||
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf, logger=logger)
|
||||
msgSendDest, xml = irt.createDestinationXML(destSites, sourceServer)
|
||||
|
||||
if len(msgSendDest) > 0:
|
||||
# Now send the message
|
||||
irt = IrtAccess.IrtAccess(ancf, bncf)
|
||||
logger.debug("msgSendDest: "+ str(msgSendDest))
|
||||
irt.transmitFiles("PUT_TCV_FILES", msgSendDest, mhsid, [fname, fnameXML], xmtScript)
|
||||
# create the XML file
|
||||
with tempfile.NamedTemporaryFile(suffix='.xml', dir=tcvProductsDir, delete=False) as fd:
|
||||
fnameXML = fd.name
|
||||
fd.write(ElementTree.tostring(xml))
|
||||
|
||||
# don't send to ourselves
|
||||
if mhsid in msgSendDest:
|
||||
msgSendDest.remove(mhsid)
|
||||
|
||||
if len(msgSendDest) > 0:
|
||||
# Now send the message
|
||||
logger.debug("msgSendDest: "+ str(msgSendDest))
|
||||
irt.transmitFiles("PUT_TCV_FILES", msgSendDest, mhsid, [fname, fnameXML], xmtScript)
|
||||
else:
|
||||
logger.info('No TCV files to send')
|
||||
|
||||
except:
|
||||
logger.exception('Error sending TCV files for site: ' + siteID)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
* Aug 25, 2014 3537 rferrel Fixed dirPattern in Category Local.
|
||||
* Jan 22, 2015 3793 rferrel Converted tags minRetentionHours to defaultRetentionHours
|
||||
* and extRetentionHours to selectedDetentionHours.
|
||||
* Feb 02, 2015 4066 rferrel Added lightning to Observation category.
|
||||
*
|
||||
* @author rferrel
|
||||
* @version 1.0
|
||||
|
@ -210,7 +211,7 @@
|
|||
<name>Observation</name>
|
||||
<selectedRetentionHours>168</selectedRetentionHours>
|
||||
<dataSet>
|
||||
<dirPattern>(airep|binlightning|bufrascat|bufrhdw|bufrmthdw|bufrssmi|lsr|MAROB|maritime|metar|misc_sfc_obs|pirep|sfcobs|shef|svrwx|synoptic)/(\d{4})(\d{2})(\d{2})/(\d{2})</dirPattern>
|
||||
<dirPattern>(airep|binlightning|bufrascat|bufrhdw|bufrmthdw|bufrssmi|entlightning|lsr|MAROB|maritime|metar|misc_sfc_obs|pirep|sfcobs|shef|svrwx|synoptic)/(\d{4})(\d{2})(\d{2})/(\d{2})</dirPattern>
|
||||
<displayLabel>{1}</displayLabel>
|
||||
<dateGroupIndices>2,3,4,5</dateGroupIndices>
|
||||
</dataSet>
|
||||
|
|
|
@ -813,7 +813,12 @@
|
|||
</rule>
|
||||
<!-- Purge rules for MRMS -->
|
||||
<rule>
|
||||
<keyValue>MRMS</keyValue>
|
||||
<keyValue>MRMS_1000</keyValue>
|
||||
<versionsToKeep>120</versionsToKeep>
|
||||
<period>03-00:00:00</period>
|
||||
</rule>
|
||||
<rule>
|
||||
<keyValue>MRMS_0500</keyValue>
|
||||
<versionsToKeep>120</versionsToKeep>
|
||||
<period>03-00:00:00</period>
|
||||
</rule>
|
||||
|
|
|
@ -10,7 +10,8 @@ Require-Bundle: com.raytheon.edex.common,
|
|||
com.raytheon.uf.common.status;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.edex.ndm;bundle-version="1.14.0",
|
||||
com.raytheon.uf.edex.menus;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.dataplugin.redbook;bundle-version="1.14.0"
|
||||
com.raytheon.uf.common.dataplugin.redbook;bundle-version="1.14.0",
|
||||
org.apache.commons.lang;bundle-version="2.3.0"
|
||||
Export-Package: com.raytheon.uf.edex.plugin.redbook,
|
||||
com.raytheon.uf.edex.plugin.redbook.decoder
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
|
|
|
@ -47,6 +47,7 @@ import com.raytheon.uf.edex.plugin.redbook.menu.RedbookUaMenuUtil;
|
|||
* Mar 19, 2014 2857 mpduff Implement NCO.
|
||||
* Mar 19, 2014 2859 mpduff Implement MPC.
|
||||
* Mar 19, 2014 2860 mpduff Implement Upper Air.
|
||||
* Jan 28, 2015 4030 mpduff Changed constants to public.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -60,22 +61,22 @@ public class RedbookMenuSubscriber implements INationalDatasetSubscriber {
|
|||
.getHandler(RedbookMenuSubscriber.class);
|
||||
|
||||
/** Hazard menu file */
|
||||
private static final String HAZARD_MENU_FILE = "RedbookHazardMenus.xml";
|
||||
public static final String HAZARD_MENU_FILE = "RedbookHazardMenus.xml";
|
||||
|
||||
/** HPC menu file */
|
||||
private static final String HPC_MENU_FILE = "RedbookHPCMenus.xml";
|
||||
public static final String HPC_MENU_FILE = "RedbookHPCMenus.xml";
|
||||
|
||||
/** CPC menu file */
|
||||
private static final String CPC_MENU_FILE = "RedbookCPCMenus.xml";
|
||||
public static final String CPC_MENU_FILE = "RedbookCPCMenus.xml";
|
||||
|
||||
/** MPC menu file */
|
||||
private static final String MPC_MENU_FILE = "RedbookMPCMenus.xml";
|
||||
public static final String MPC_MENU_FILE = "RedbookMPCMenus.xml";
|
||||
|
||||
/** NCO menu file */
|
||||
private static final String NCO_MENU_FILE = "RedbookNCOMenus.xml";
|
||||
public static final String NCO_MENU_FILE = "RedbookNCOMenus.xml";
|
||||
|
||||
/** Upper air menu file */
|
||||
private static final String UA_MENU_FILE = "RedbookUAMenus.xml";
|
||||
public static final String UA_MENU_FILE = "RedbookUAMenus.xml";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
@ -39,6 +39,7 @@ import javax.xml.bind.annotation.XmlElements;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 12, 2014 2855 mpduff Initial creation
|
||||
* Mar 19, 2014 2860 mpduff Added DataUri.
|
||||
* Jan 28, 2015 4030 mpduff Added addMenuEntry method.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -208,7 +209,7 @@ public class MenuEntry {
|
|||
* @param menuEntryList
|
||||
* the menuEntryList to set
|
||||
*/
|
||||
public void setMenuEntryyList(List<MenuEntry> menuEntryList) {
|
||||
public void setMenuEntryList(List<MenuEntry> menuEntryList) {
|
||||
this.menuEntryList = menuEntryList;
|
||||
}
|
||||
|
||||
|
@ -227,6 +228,18 @@ public class MenuEntry {
|
|||
this.dataUri = dataUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link MenuEntry}
|
||||
*
|
||||
* @param entry
|
||||
*/
|
||||
public void addMenuEntry(MenuEntry entry) {
|
||||
if (this.menuEntryList == null) {
|
||||
menuEntryList = new ArrayList<MenuEntry>();
|
||||
}
|
||||
menuEntryList.add(entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
|
|
@ -39,6 +39,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 07, 2014 2858 mpduff Initial creation.
|
||||
* Mar 17, 2014 2855 mpduff Renamed to RedbookMenusXML.java.
|
||||
* Jan 28, 2015 4030 mpduff Added addMenuEntry method.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -78,6 +79,10 @@ public class RedbookMenusXML {
|
|||
this.menuEntryList = menuEntryList;
|
||||
}
|
||||
|
||||
public void addMenuEntry(MenuEntry entry) {
|
||||
menuEntryList.add(entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
|
|
@ -0,0 +1,360 @@
|
|||
/**
|
||||
* 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.uf.edex.plugin.redbook.menu;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.Marshaller;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.raytheon.uf.edex.plugin.redbook.ingest.RedbookMenuSubscriber;
|
||||
import com.raytheon.uf.edex.plugin.redbook.ingest.xml.MenuEntry;
|
||||
import com.raytheon.uf.edex.plugin.redbook.ingest.xml.MenuEntryType;
|
||||
import com.raytheon.uf.edex.plugin.redbook.ingest.xml.RedbookMenusXML;
|
||||
|
||||
/**
|
||||
* This class is called from /awips2/edex/bin/ndmMenuIngester.sh.
|
||||
*
|
||||
* It reads in the NDM menu files and outputs an A2 version into the NDM
|
||||
* endpoint on edex.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jan 30, 2015 4030 mpduff Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mpduff
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class NdmMenuConverter {
|
||||
private static final String WMO = "wmo";
|
||||
|
||||
private static final String OUTPUT_PATH = File.separator + "awips2"
|
||||
+ File.separator + "edex" + File.separator + "data"
|
||||
+ File.separator + "ndm" + File.separator;
|
||||
|
||||
private static final String HPC_FILE = "redbookHPCMenus.txt";
|
||||
|
||||
private static final String CPC_FILE = "redbookCPCMenus.txt";
|
||||
|
||||
private static final String NCO_FILE = "redbookNCOMenus.txt";
|
||||
|
||||
private static final String HAZARDS_FILE = "redbookHazardMenus.txt";
|
||||
|
||||
private static final String MARINE_FILE = "redbookMarineMenus.txt";
|
||||
|
||||
private static final String UPPER_AIR_FILE = "redbookUpperAirMenus.txt";
|
||||
|
||||
private String dataKeysPath;
|
||||
|
||||
private String depictKeysPath;
|
||||
|
||||
private String menuFilePath;
|
||||
|
||||
private String productButtonPath;
|
||||
|
||||
private JAXBContext jax;
|
||||
|
||||
private Marshaller marshaller;
|
||||
|
||||
private File depictFile;
|
||||
|
||||
public NdmMenuConverter() {
|
||||
createContext();
|
||||
}
|
||||
|
||||
public void convert() {
|
||||
RedbookMenusXML menuXml = new RedbookMenusXML();
|
||||
MenuEntry titleMenuEntry;
|
||||
int sepCounter = 0;
|
||||
List<MenuEntry> subMenuList = new ArrayList<MenuEntry>();
|
||||
|
||||
try {
|
||||
File dataFile = new File(this.dataKeysPath);
|
||||
File menuFile = new File(this.menuFilePath);
|
||||
depictFile = new File(this.depictKeysPath);
|
||||
File productButtonFile = new File(this.productButtonPath);
|
||||
|
||||
List<String> dataKeys = Files.readAllLines(dataFile.toPath(),
|
||||
Charset.defaultCharset());
|
||||
List<String> depictKeys = Files.readAllLines(depictFile.toPath(),
|
||||
Charset.defaultCharset());
|
||||
List<String> lines = Files.readAllLines(menuFile.toPath(),
|
||||
Charset.defaultCharset());
|
||||
List<String> productButtonKeys = Files.readAllLines(
|
||||
productButtonFile.toPath(), Charset.defaultCharset());
|
||||
Map<String, String> menuTextMap = getMenuTextMap(productButtonKeys);
|
||||
Map<String, String> dataKeyMap = getSubstitutionMap(dataKeys);
|
||||
|
||||
MenuEntry subMenuEntry = null;
|
||||
|
||||
int subMenuCount = -1;
|
||||
for (String line : lines) {
|
||||
line = line.trim();
|
||||
if (line.startsWith("submenu")) {
|
||||
subMenuCount++;
|
||||
if (line.contains("&")) {
|
||||
line = line.replace("&", "&&");
|
||||
}
|
||||
|
||||
String[] parts = line.split(":");
|
||||
String text = parts[1].replace("\"", "");
|
||||
|
||||
subMenuEntry = new MenuEntry();
|
||||
subMenuEntry.setFile(null);
|
||||
subMenuEntry.setType(MenuEntryType.Submenu);
|
||||
subMenuEntry.setText(text.trim());
|
||||
|
||||
subMenuList.add(subMenuEntry);
|
||||
} else if (line.startsWith("title")) {
|
||||
String[] parts = line.split(":");
|
||||
String text = parts[1].replace("\"", "");
|
||||
titleMenuEntry = new MenuEntry();
|
||||
titleMenuEntry.setFile(null);
|
||||
titleMenuEntry.setType(MenuEntryType.Title);
|
||||
titleMenuEntry.setText(text);
|
||||
titleMenuEntry.setId(text);
|
||||
subMenuList.get(subMenuCount).addMenuEntry(titleMenuEntry);
|
||||
} else if (line.startsWith("productButton")) {
|
||||
String[] parts = line.split(":");
|
||||
MenuEntry me = new MenuEntry();
|
||||
me.setFile(null);
|
||||
me.setType(MenuEntryType.ProductButton);
|
||||
/*
|
||||
* There are certain productButtons in the NCO menu data
|
||||
* keys in the (25000 range) that have data keys that don't
|
||||
* map to anything. This results in those menu items not
|
||||
* being created. The site will need to fix this after
|
||||
* generating the new menus.
|
||||
*/
|
||||
String dataKey = parts[1].trim().substring(0, 4);
|
||||
StringBuilder subValue = new StringBuilder();
|
||||
// Find the matching value
|
||||
for (String depictKeyLine : depictKeys) {
|
||||
if (depictKeyLine.trim().startsWith(dataKey)) {
|
||||
String[] depictKeyParts = depictKeyLine
|
||||
.split("\\|");
|
||||
me.setText(menuTextMap.get(dataKey));
|
||||
me.setId(depictKeyParts[6].trim());
|
||||
subMenuList.get(subMenuCount).addMenuEntry(me);
|
||||
|
||||
String[] subParts = depictKeyParts[2].split(",");
|
||||
MenuEntry subEntry = new MenuEntry();
|
||||
subEntry.setFile(null);
|
||||
subEntry.setType(MenuEntryType.Substitute);
|
||||
subEntry.setKey(WMO);
|
||||
|
||||
for (String subPart : subParts) {
|
||||
for (String key : dataKeyMap.keySet()) {
|
||||
if (key.startsWith(subPart)) {
|
||||
subValue.append(dataKeyMap.get(key))
|
||||
.append(",");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String subValueStr = subValue.toString();
|
||||
subValueStr = StringUtils.removeEnd(subValueStr,
|
||||
",");
|
||||
subEntry.setValue(subValueStr);
|
||||
me.addMenuEntry(subEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (line.startsWith("endSubmenu")) {
|
||||
// subMenuList.add(subMenuEntry);
|
||||
MenuEntry closedSubMenu = subMenuList.remove(subMenuCount);
|
||||
subMenuCount--;
|
||||
if (subMenuCount == -1) {
|
||||
menuXml.addMenuEntry(closedSubMenu);
|
||||
} else {
|
||||
subMenuList.get(subMenuCount).addMenuEntry(
|
||||
closedSubMenu);
|
||||
}
|
||||
} else if (line.startsWith("separator")) {
|
||||
MenuEntry sep = new MenuEntry();
|
||||
sep.setFile(null);
|
||||
sep.setType(MenuEntryType.Separator);
|
||||
sep.setId("Separator" + sepCounter++);
|
||||
subMenuList.get(subMenuCount).addMenuEntry(sep);
|
||||
}
|
||||
}
|
||||
|
||||
// Set output file name
|
||||
String inputFileName = menuFile.getName();
|
||||
String outputFileName = null;
|
||||
if (inputFileName.equals(CPC_FILE)) {
|
||||
outputFileName = RedbookMenuSubscriber.CPC_MENU_FILE;
|
||||
} else if (inputFileName.equals(HPC_FILE)) {
|
||||
outputFileName = RedbookMenuSubscriber.HPC_MENU_FILE;
|
||||
} else if (inputFileName.equals(NCO_FILE)) {
|
||||
outputFileName = RedbookMenuSubscriber.NCO_MENU_FILE;
|
||||
} else if (inputFileName.equals(HAZARDS_FILE)) {
|
||||
outputFileName = RedbookMenuSubscriber.HAZARD_MENU_FILE;
|
||||
} else if (inputFileName.equals(MARINE_FILE)) {
|
||||
outputFileName = RedbookMenuSubscriber.MPC_MENU_FILE;
|
||||
} else if (inputFileName.equals(UPPER_AIR_FILE)) {
|
||||
outputFileName = RedbookMenuSubscriber.UA_MENU_FILE;
|
||||
} else {
|
||||
throw new IOException("Error processing file");
|
||||
}
|
||||
|
||||
marshaller.marshal(menuXml, new File(OUTPUT_PATH + outputFileName));
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error occurred processing file: "
|
||||
+ menuFilePath);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of menu keys to menu text.
|
||||
*
|
||||
* @param productButtonKeys
|
||||
* List of strings from redbookProductButtons.txt
|
||||
*
|
||||
* @return Map for key -> menu text
|
||||
*/
|
||||
private Map<String, String> getMenuTextMap(List<String> productButtonKeys) {
|
||||
Map<String, String> menuTextMap = new HashMap<String, String>();
|
||||
for (String line : productButtonKeys) {
|
||||
line = line.trim();
|
||||
// Skip comment lines
|
||||
if (line.startsWith("#") || line.trim().length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] parts = line.split("\\|");
|
||||
menuTextMap.put(parts[0].trim(), parts[2].trim());
|
||||
}
|
||||
|
||||
return menuTextMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of key to substitution values.
|
||||
*
|
||||
* @param dataKeys
|
||||
* List of strings from the redbookDataKeys.txt file
|
||||
* @returnMap for key -> substitution string
|
||||
*/
|
||||
private Map<String, String> getSubstitutionMap(List<String> dataKeys) {
|
||||
Map<String, String> dataKeyMap = new HashMap<String, String>();
|
||||
for (String line : dataKeys) {
|
||||
line = line.trim();
|
||||
// Skip comment lines
|
||||
if (line.startsWith("#") || line.trim().length() == 0) {
|
||||
continue;
|
||||
}
|
||||
String[] parts = line.split("\\|");
|
||||
dataKeyMap.put(parts[0].trim(), parts[10].substring(0, 6));
|
||||
}
|
||||
|
||||
return dataKeyMap;
|
||||
}
|
||||
|
||||
public String getDataKeysPath() {
|
||||
return dataKeysPath;
|
||||
}
|
||||
|
||||
public void setDataKeysPath(String dataKeysPath) {
|
||||
this.dataKeysPath = dataKeysPath;
|
||||
}
|
||||
|
||||
public String getDepictKeysPath() {
|
||||
return depictKeysPath;
|
||||
}
|
||||
|
||||
public void setDepictKeysPath(String depictKeysPath) {
|
||||
this.depictKeysPath = depictKeysPath;
|
||||
}
|
||||
|
||||
public String getMenuFilePath() {
|
||||
return menuFilePath;
|
||||
}
|
||||
|
||||
public void setMenuFilePath(String menuFilePath) {
|
||||
this.menuFilePath = menuFilePath;
|
||||
}
|
||||
|
||||
public void setProductButtonPath(String productButtonPath) {
|
||||
this.productButtonPath = productButtonPath;
|
||||
}
|
||||
|
||||
public String getProductButtonPath() {
|
||||
return this.productButtonPath;
|
||||
}
|
||||
|
||||
private void createContext() {
|
||||
Class[] classes = new Class[] { MenuEntry.class, MenuEntryType.class,
|
||||
RedbookMenusXML.class };
|
||||
|
||||
try {
|
||||
jax = JAXBContext.newInstance(classes);
|
||||
this.marshaller = jax.createMarshaller();
|
||||
this.marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
if (args.length != 2) {
|
||||
System.err.println("Unexpected Arguments");
|
||||
System.err
|
||||
.println("Expecting local NDM directory and NDM File Menu Name");
|
||||
return;
|
||||
}
|
||||
|
||||
String dirPath = args[0];
|
||||
if (!dirPath.endsWith(File.separator)) {
|
||||
dirPath = dirPath.concat(File.separator);
|
||||
}
|
||||
String menuFile = dirPath + args[1];
|
||||
String dataKeysFile = dirPath + "redbookDataKeys.txt";
|
||||
String depictKeysFile = dirPath + "redbookDepictKeys.txt";
|
||||
String productButtonFile = dirPath + "redbookProductButtons.txt";
|
||||
|
||||
NdmMenuConverter converter = new NdmMenuConverter();
|
||||
converter.setDataKeysPath(dataKeysFile);
|
||||
converter.setMenuFilePath(menuFile);
|
||||
converter.setDepictKeysPath(depictKeysFile);
|
||||
converter.setProductButtonPath(productButtonFile);
|
||||
converter.convert();
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue