================================================================================
AlertDisplay v1.1.0 — Building Profiles and Triggers
A companion guide to the AlertDisplay User Manual

Designed and developed by Stephen Clay McGehee, KN4AM
Coding done using Claude Code AI
See SitRepNet.com for more information
================================================================================


ABOUT THIS GUIDE
----------------
This guide is about one job: building the profiles and triggers that
tell AlertDisplay what to show. It explains how the parts fit together,
where every value such as {GROUP} or {MYCALL} comes from, and gives
worked examples you can copy.

The User Manual (AlertDisplay_User_Manual.txt) covers everything else:
installing, the monitor, the Active Alerts tab, callsign lists and
troubleshooting.

The examples use the group @SITREP and a member station N0ABC. Other
callsigns in them are only examples.


THE BIG PICTURE
---------------
  Profile   A file holding a list of triggers, plus a few settings
            shared by all of them (the group callsign and the defaults).
  Trigger   One rule: what to look for, and what to show when it's
            found.

There are two kinds of profile, in exactly the same format:

  Group      Made by a group's coordinator and imported by members.
             Opens read-only. A new release replaces it as a whole.
  Personal   Your own. Only you have it, unless you export it.

There are two kinds of trigger:

  Message triggers       Look at each message JS8Call receives (its
                         DIRECTED.TXT log) for a word, phrase or code.
  Status Board triggers  Look at SitRepMapper's Status Board for
                         stations whose reports are flagged (needs
                         SitRepMapper v1.18.0 or later).

Any number of profiles can be on at once, and a profile can hold both
kinds of trigger.

What happens to each message
  1. AlertDisplay reads the new message and works out who sent it
     (FROM), who it was sent to (TO) and the text.
  2. Each profile that's on, top of the Profiles list first, checks its
     triggers that are on, in their order. A trigger matches when its
     match text is found AND the message passes its From and To
     filters.
  3. If several triggers match, the message still shows only once. An
     alert (ALR) beats a notification (NTF); otherwise the first match
     wins. The winner's banner text is used.
  4. The callsign lists (Callsign Lists tab) can still keep the sender
     out. The log says so.
  5. If the same trigger saw the same sender and the same text within
     its cooldown, it's a repeat and isn't shown again.
  6. Otherwise it goes on SitRepMapper: the red ALERT strip for ALR, the
     notification strip for NTF, for the trigger's Minutes shown.

Every match is written to the Log tab, whether it was shown or not.


WHERE THE VALUES COME FROM
--------------------------
This is the part with the most moving parts. Each value is set in one
place only.

Set in SitRepMapper
  {MYCALL}          Your station callsign, from SitRepMapper's
                    Settings > General > Station callsign. AlertDisplay
                    reads it from SitRepMapper; it isn't set in
                    AlertDisplay at all. Used in a trigger's From or To
                    list. One group profile then works for every member,
                    because each member's {MYCALL} is their own call.
                    Not set: triggers that use {MYCALL} are skipped,
                    with a warning.
  Sub-Optimal       What counts as "flagged" for Status Board triggers
  Thresholds        (SitRepMapper Settings > Sub-Optimal Thresholds).
  Days to include   How many days the Status Board covers (Reports >
                    Status Board in SitRepMapper).

Set in the profile (top of the profile editor)
  {GROUP}           The profile's Group callsign, e.g. @SITREP. Set it
                    once there and every trigger can say {GROUP} instead
                    of repeating it. Used in a trigger's From or To
                    list. Include the @: JS8 group calls start with @,
                    and {GROUP} is replaced exactly as typed, so "SITREP"
                    would never match a message sent to "@SITREP". A
                    trigger that uses {GROUP} in a profile with no Group
                    callsign is an error.
  Defaults          Display, Minutes, Cooldown and Banner text for any
                    trigger in this profile that leaves them blank.
                    (Banner text defaults are for message triggers only;
                    see STATUS BOARD TRIGGERS.)

Set in each trigger
  Match, Match text, From, To, Display, Minutes shown, Cooldown minutes,
  Banner text, On. Blank fields take the profile's default, then the
  built-in value:
      Display            NTF
      Minutes shown      60 for ALR, 30 for NTF
      Cooldown minutes   10
      Banner text        {FROM}: {TEXT}

Filled in from each message (banner text only)
  {FROM}     The station that sent the message first. For a relayed
             message, that's the station after *DE*, not the relay.
  {TO}       Who it was sent to: the first word after "FROM:" (a
             callsign or @GROUP).
  {TEXT}     The message text, after the TO.
  {AFTER}    The text after the part that matched, so a trigger code
             doesn't show. Anything before the match is left out too.
  {TIME}     When it was received, UTC, e.g. 18:42Z.
  {TRIGGER}  The trigger's name.
  {GRID}     The grid sent as GR[...] in the message, or ? if none.
  {DIST}     About how far that grid is from your Station grid
             (SitRepMapper, Settings > General), e.g. ~69 mi.
  {DIR}      Which way it is from your Station grid: N NE E SE S SW W NW.
  {RANGE}    Both, e.g. ~69 mi N. "~" when either grid is only 4
             characters (could be off by up to about 40 miles);
             "Local" when it's your own grid (or one lies inside the
             other); ? when there's no grid or no Station grid.

Filled in from the Status Board (Status Board banner text only)
  {FROM} {GRID} {DIST} {DIR} {RANGE} {TIME} {TRIGGER} {TYPE} {STATUS}
  {REASON} {WAS} {COUNT} {STATIONS} {DAYS}. See STATUS BOARD TRIGGERS.

Set on your own station only (never in the profile)
  - Whether each profile is on, and the order of profiles (Profiles
    tab).
  - Your own on/off choice for a trigger in a group profile (Turn
    On/Off). Kept in your settings, so it survives the group's next
    release.
  - The callsign lists (Callsign Lists tab).
  - Still or scrolling notifications, and the Status Board summary line
    (Settings and Status Board tabs).

So two members with the same group profile can see different things:
their {MYCALL} differs, and each may have turned triggers off or kept
stations out with their callsign lists.


HOW A MESSAGE IS READ
---------------------
JS8Call logs each message received as one line. AlertDisplay looks at
the part after the signal report:

  KN4AM: @SITREP NET ACTIVATED ON 7.078 AT 1900Z ♢
  -----  -------  -------------------------------
  FROM   TO       TEXT

  - FROM is the callsign before the colon.
  - TO is the first word after it: a callsign (N0ABC) or a group
    (@SITREP).
  - TEXT is everything after TO. Match text is looked for here.
  - "♢" marks a complete message. A message without it was only partly
    received; it still triggers, marked "partial".

A relayed message:

  WO7I: @SITREP> ALERT POWER OUT *DE* WD4KAV ♢

  WD4KAV sent it first and WO7I passed it on. FROM is WD4KAV (for
  {FROM}, the From filter and the callsign lists), TO is @SITREP, the
  text is "ALERT POWER OUT", and the banner gets "(via WO7I)" added.

To try any of this, paste a message (or a whole line from DIRECTED.TXT)
into the Test a Message tab. It shows FROM, TO, the text, every trigger
that matched, which one is used, and the exact banner text.


MESSAGE TRIGGERS
----------------
Match types
  Matching ignores case and takes the text literally: no character has a
  special meaning, so punctuation codes work. A trigger can have several
  match texts, one per line; any one of them is enough.

  Contains               Anywhere in the text.
                           ALERT matches ALERTS, ALERTED, "MAGNETIC
                           STORM ALERT".
  Whole word or phrase   With no letter or digit touching it on either
                         side.
                           ALERT matches "ALERT:" and "ALERT POWER OUT",
                           but not ALERTS or ALERTED.
                           Add ALERTS as a second match text if you want
                           it too.
  Starts with            The text begins with it, right after the TO.
                           MSG matches "N0ABC MSG CALL ME" but not
                           "N0ABC PLS SEND MSG".
                         A quoted or forwarded copy doesn't set it
                         off, but a message sent with MSG ("@SITREP
                         MSG ...") doesn't start with the code either.

From (optional)
  Only these sending stations, one per line. Blank = any station.
  - KN4AM also covers KN4AM/P and other suffixes. List KN4AM/P to
    cover only that one.
  - {MYCALL} and {GROUP} work here too.

To (optional)
  Only messages sent to these, one per line: callsigns, @GROUPs,
  {MYCALL}, {GROUP}. Blank = sent to anyone.
  - To: {MYCALL} means "sent to my station", including your call with a
    suffix (N0ABC/P).
  - To: {GROUP} means "sent to the profile's group".
  - A message sent to @ALLCALL or another group doesn't count as sent
    to you or to your group.

Display
  ALR   The red ALERT strip. Can't be closed in SitRepMapper. Turns the
        toolbar block red. For things that must not be missed.
  NTF   The notification strip. Can be closed in SitRepMapper.

Minutes shown
  How long it stays up, unless cleared sooner on the Active Alerts tab.

Cooldown minutes
  JS8 messages are often repeated and relayed. The same trigger, the
  same sending station and the same text inside this time is ignored
  (and logged as a repeat). 0 = no cooldown. A different station, or
  different text, is not a repeat.

Banner text
  What SitRepMapper shows. Plain text plus any placeholders (see WHERE
  THE VALUES COME FROM). Keep it short: SitRepMapper allows 500
  characters per strip, shared by everything showing there.


ORDER AND PRIORITY
------------------
  - Profiles are checked top to bottom of the Profiles list; triggers
    top to bottom within each profile.
  - One message shows once, however many triggers match.
  - ALR beats NTF, whatever the order.
  - Among the same level, the first match gives the banner text.
  - So put specific triggers ABOVE general ones. A "net activation"
    trigger above a plain "ALERT" trigger gives the better banner when
    a message matches both.

A useful pattern: two triggers for the same word. The first, limited
to your group, is an ALR; the second, for anyone, is an NTF. A message
to your group comes up red; the same word elsewhere is only a
notification. See Example 6.


STATUS BOARD TRIGGERS
---------------------
Needs SitRepMapper v1.18.0 or later. Added with "Add Status Board..."
in the profile editor.

SitRepMapper's Status Board keeps each station's latest report of each
type (F!104, F!309, F!505, F!500, CommStat) and flags the ones that
cross its Sub-Optimal Thresholds. Status Board triggers watch for
changes in those flags.

  Event                    Fires when
  Station newly flagged    A report of a watched type becomes flagged
                           (including a station's first report).
  Station got worse        A flagged report gets worse, or a station
                           already flagged on one type is flagged on
                           another. Same F!309 severity, now "Ongoing,
                           Deteriorating": worse too.
  Station improved         Still flagged, but better than before
                           (lower severity, or the same F!309 severity
                           now "Ongoing, Improving").
  Station cleared          The station sends a NEWER report that isn't
                           flagged, or its F!309 is no longer flagged
                           because it's Resolved or has expired. A
                           report that only ages out of the window
                           doesn't count.
  Flagged count reaches N  N or more stations flagged.
  Flagged share reaches X% That percent of the stations reporting are
                           flagged, with at least the minimum number
                           reporting (default 5).
  Count and share can also show a notification when they drop back
  below ("Also notify (NTF) when it drops back below", with its own
  text).

  Report types     Tick the types to watch. None ticked = all.
  Narrow it down   Optional. F!104 Problems only, CommStat Red only,
                   F!309 minimum severity or categories, F!505 score
                   below a number, F!500 worst answer one of a list.
                   These only narrow SitRepMapper's flags; they can't
                   flag anything SitRepMapper doesn't. To change what
                   counts as flagged, change the thresholds in
                   SitRepMapper.
  Display, Minutes shown, Cooldown minutes, On
                   As for message triggers. The cooldown is per station
                   and report type.
  Banner text      Its own placeholders:
                     {FROM}      the station's callsign (its grid if it
                                 has none)
                     {GRID}      the report's grid (an F!309's is
                                 where the incident is)
                     {DIST} {DIR} {RANGE}
                                 how far and which way that grid is
                                 from your Station grid, as for
                                 message triggers
                     {TIME}      the report's time, UTC
                     {TYPE}      e.g. F!104
                     {STATUS}    the new status, e.g. Problems
                     {REASON}    SitRepMapper's reason for the flag
                     {WAS}       the status before
                     {COUNT}     stations flagged
                     {STATIONS}  stations reporting
                     {DAYS}      days the Status Board covers
                     {TRIGGER}   the trigger's name
                   Left blank, it uses a built-in text for the event
                   (e.g. "{FROM} flagged {TYPE}: {STATUS} ({GRID})"),
                   NOT the profile's default banner text, whose
                   placeholders ({TEXT} and so on) mean nothing here.

Things to know
  - Not affected by From, To or match text; they don't apply.
  - Nothing fires for stations already flagged when the monitor starts.
  - An ALR clears by itself when the station sends a newer report that
    isn't flagged (or no longer meets the narrowing), or when a count
    drops back below its level. A "got worse" ALR also clears when the
    station's newer report is still flagged but better.
  - Always Ignore and IGNORE.TXT apply. "Ignore all except" doesn't.
  - A message trigger and a Status Board trigger for the same station
    and report type within about 2 minutes show once.
  - Not tested on the Test a Message tab; the Status Board tab shows
    what they're watching.


BUILDING A PERSONAL PROFILE, STEP BY STEP
-----------------------------------------
  1. Profiles tab: New Personal Profile... Give it a name, e.g.
     "My alerts". It's made, turned on and opened.
  2. Optional: in the profile editor, fill in Group callsign (with the
     @) if your triggers will use {GROUP}, and any Defaults you want.
  3. Add... for a message trigger, or Add Status Board... for a Status
     Board trigger. Fill it in (see the examples) and click OK.
  4. Order the triggers with Move Up / Move Down: specific ones first.
  5. Save.
  6. Test a Message: paste a message that should match, and one that
     shouldn't. Show on SitRepMapper puts it on the real screen for 2
     minutes, marked "TEST:".


BUILDING A GROUP PROFILE (COORDINATOR)
--------------------------------------
Every station already has SitRepNet's profile, SitRepNet (@SITREP),
which covers the Status Board, weather, evacuation and traffic for
each station. So a group profile only needs the triggers tied to the
group's own callsign. The quickest start is
AlertDisplay_Group_Template.json in the program folder: import it, set
the Name and Group callsign, edit the two YOUR GROUP triggers, and
export it (see "Adding your group" in AlertDisplay_Overview.txt).

Personal while you work on it, group when you send it: your own copy
stays a personal profile so you can edit it, and Export as Group
Profile writes the copy your members import, marked as a group profile
(read-only for them). There's no other step to "make it a group".

To build one from scratch instead:

  1. Build it as a personal profile first (above), with Group callsign
     set, e.g. @SITREP. Use {GROUP} in To lists, and {MYCALL} where a
     trigger is about each member's own station, so the one file works
     for everyone.
  2. Give each trigger a clear name and a description: members see them
     read-only, and JSON has no comments.
  3. Test every trigger on Test a Message.
  4. Profiles tab: select it, Export as Group Profile... Check Author,
     Group callsign and Profile ID, accept the offered Release (e.g.
     2026-11-10.1) and save the file.
  5. Send the file to members. Each uses Import Group Profile...

For later releases: open your own (personal) copy, change it and
Save, then Export again with the same Profile ID. (If you only have the
group profile itself, open it and use Edit Anyway... first.) Members
import it over the old one; the triggers they turned on or off
themselves stay that way.

Rules that keep members' choices working
  - Never reuse or renumber a trigger's id. Members' on/off choices are
    tied to it. (The settings window makes ids from names when a
    trigger is added; renaming a trigger later keeps its id.)
  - Never change the profile_id. It's how a new release finds the old
    one to replace.
  - Starting from another group's profile (Duplicate as Personal)?
    Export offers a new Profile ID from your group callsign. Keep it:
    if two groups used the same ID, a member of both would lose one
    profile when importing the other.
  - Use "enabled": false (unticked On) for triggers members may want but
    shouldn't get by default, such as net check-ins.
  - Status Board triggers need SitRepMapper v1.18.0 or later on each
    member's station. Say so when you send the file.


EXAMPLES
--------
Each example shows the settings-window fields, the profile file (JSON)
version, a message, and what SitRepMapper shows. The profile's Group
callsign is @SITREP and the member's station is N0ABC. All banners were
checked against AlertDisplay itself.

Example 1: Net activation by the net managers only
  Match: Contains   Match text: NET ACTIVATED
  From: KN4AM, W4XYZ          To: {GROUP}
  Display: ALR   Minutes: 120   Banner: NET ACTIVATION ({FROM}): {TEXT}

    {
      "id": "net-activation",
      "name": "Net activation",
      "match": { "type": "contains", "text": ["NET ACTIVATED"] },
      "from": ["KN4AM", "W4XYZ"],
      "to": ["{GROUP}"],
      "display": "ALR",
      "minutes": 120,
      "banner_text": "NET ACTIVATION ({FROM}): {TEXT}"
    }

  KN4AM: @SITREP NET ACTIVATED ON 7.078 AT 1900Z
    -> red strip: NET ACTIVATION (KN4AM): NET ACTIVATED ON 7.078 AT 1900Z
  W1AW: @SITREP NET ACTIVATED
    -> nothing (W1AW isn't in From)

Example 2: The group alert code, with the code hidden
  The standard form is the group name and -ALERT. This is the trigger
  in SitRepNet's profile; another group uses its own name, e.g.
  LCARES-ALERT.
  Match: Whole word or phrase   Match text: SITREP-ALERT   To: {GROUP}
  Display: ALR   Minutes: 120   Banner: GROUP ALERT ({FROM}): {AFTER}

    {
      "id": "group-alert-code",
      "name": "SitRep alert code",
      "match": { "type": "word", "text": ["SITREP-ALERT"] },
      "to": ["{GROUP}"],
      "display": "ALR",
      "minutes": 120,
      "banner_text": "GROUP ALERT ({FROM}): {AFTER}"
    }

  K4ABC: @SITREP SITREP-ALERT STORM SURGE WARNING FOR DAYTONA BEACH
    -> red strip: GROUP ALERT (K4ABC): STORM SURGE WARNING FOR DAYTONA
       BEACH
  K4ABC: @SITREP MSG SITREP-ALERT ROAD CLOSED
    -> red strip: GROUP ALERT (K4ABC): ROAD CLOSED
  K4ABC: @SITREP SITREP-ALERT
    -> red strip: GROUP ALERT (K4ABC): SitRep alert code
       (nothing after the code, so {AFTER} shows the trigger's name)

  Whole word, not Starts with, so it also works when sent with MSG.
  It uses only letters and a hyphen, so it arrives intact; send it
  over the air once anyway before relying on it.

Example 3: Traffic for my station
  Match: Starts with   Match text: MSG   To: {MYCALL}
  Display: NTF   Banner: {FROM} has traffic for you ({TIME})

    {
      "id": "traffic-for-me",
      "name": "Traffic for my station",
      "match": { "type": "starts_with", "text": ["MSG"] },
      "to": ["{MYCALL}"],
      "display": "NTF",
      "banner_text": "{FROM} has traffic for you ({TIME})"
    }

  W4XYZ: N0ABC MSG CALL ME ON 2M
    -> notification: W4XYZ has traffic for you (18:42Z)
  W4XYZ: N0ABC/P MSG HELLO
    -> notification: W4XYZ has traffic for you (18:42Z)

  {MYCALL} is N0ABC because that's the Station callsign in this
  member's SitRepMapper. Another member gets their own messages.

Example 4: Incident reports, showing the grid
  Match: Contains   Match text: F!309   To: {GROUP}
  Display: NTF   Banner: F!309 from {FROM} in {GRID}

    {
      "id": "incident-report",
      "name": "Incident report",
      "match": { "type": "contains", "text": ["F!309"] },
      "to": ["{GROUP}"],
      "display": "NTF",
      "banner_text": "F!309 from {FROM} in {GRID}"
    }

  W2KI: @SITREP F!309 2A3141 DS[TREE DOWN] GR[EM15AB] #KCMA
    -> notification: F!309 from W2KI in EM15AB

  A report with no GR[...] would show "in ?".

Example 5: Weather warnings from anyone
  Match: Whole word or phrase
  Match text: TORNADO WARNING, FLASH FLOOD WARNING (one per line)
  Display: ALR   Banner: WX: {TEXT}

    {
      "id": "weather",
      "name": "Weather warnings",
      "match": { "type": "word",
                 "text": ["TORNADO WARNING", "FLASH FLOOD WARNING"] },
      "display": "ALR",
      "banner_text": "WX: {TEXT}"
    }

  K5DEF: @ALLCALL TORNADO WARNING FOR LAKE COUNTY UNTIL 2100Z
    -> red strip: WX: TORNADO WARNING FOR LAKE COUNTY UNTIL 2100Z

Example 6: The same word, red for the group, yellow for everyone else
  Two triggers, in this order:
    1. "ALERT to the group"   Whole word: ALERT, EMERGENCY
                              To: {GROUP}   Display: ALR
                              Banner: ALERT {FROM}: {TEXT}
    2. "ALERT anywhere"       Whole word: ALERT, EMERGENCY
                              Display: NTF
                              Banner: {FROM} mentioned ALERT: {TEXT}

  K5DEF: @SITREP ALERT: SHELTER OPEN AT FIRE STATION 3
    -> red strip: ALERT K5DEF: ALERT: SHELTER OPEN AT FIRE STATION 3
       (both matched; ALR wins, shown once)
  K5DEF: @HFNET MAGNETIC STORM ALERT
    -> notification: K5DEF mentioned ALERT: MAGNETIC STORM ALERT
  K5DEF: @HFNET THEY ALERTED US
    -> nothing (whole word only)
  WO7I: @SITREP> ALERT POWER OUT *DE* WD4KAV
    -> red strip: ALERT WD4KAV: ALERT POWER OUT (via WO7I)

Example 7: Net check-ins, off unless a member wants them
  Match: Whole word or phrase   Match text: QRV, CHECKING IN
  To: {GROUP}   Display: NTF   Minutes: 5   Cooldown: 30
  Banner: {FROM} checked in   On: unticked

    {
      "id": "checkins",
      "name": "Net check-ins",
      "enabled": false,
      "match": { "type": "word", "text": ["QRV", "CHECKING IN"] },
      "to": ["{GROUP}"],
      "display": "NTF",
      "minutes": 5,
      "cooldown_minutes": 30,
      "banner_text": "{FROM} checked in"
    }

  Members who want it turn it on with Turn On/Off; that choice survives
  new releases.

Example 8 (Status Board): A station reports F!104 Problems
  Add Status Board...   Event: Station newly flagged
  Report types: F!104   Narrow it down: F!104 Problems only
  Display: ALR   Minutes: 120   Banner: {FROM} F!104: {STATUS} ({GRID})

    {
      "id": "board-f104-problems",
      "name": "Station reports F!104 Problems",
      "source": "statusboard",
      "event": "newly_flagged",
      "types": ["f104"],
      "conditions": { "f104_codes": ["3"] },
      "display": "ALR",
      "minutes": 120,
      "banner_text": "{FROM} F!104: {STATUS} ({GRID})"
    }

  KJ5MIW's F!104 goes from Normal to Problems
    -> red strip: KJ5MIW F!104: Problems (EM15)
  It clears by itself when KJ5MIW sends a newer F!104 that isn't
  flagged. Degraded doesn't set it off, even though SitRepMapper flags
  it, because of the narrowing.

Example 9 (Status Board): Station back to normal
  Event: Station cleared   Display: NTF   Minutes: 20   Banner: (blank)

    {
      "id": "board-cleared",
      "name": "Station back to normal",
      "source": "statusboard",
      "event": "cleared",
      "display": "NTF",
      "minutes": 20
    }

  KJ5MIW sends a new F!104, Normal
    -> notification: KJ5MIW F!104 back to Normal   (built-in banner)

Example 10 (Status Board): Widespread trouble
  Event: Flagged share reaches X%   Percent: 33   Min. stations: 5
  Display: ALR   Minutes: 180
  Banner: {COUNT} of {STATIONS} stations flagged ({DAYS} days)

    {
      "id": "board-widespread",
      "name": "Widespread problems",
      "source": "statusboard",
      "event": "share",
      "percent": 33,
      "min_stations": 5,
      "display": "ALR",
      "minutes": 180,
      "banner_text": "{COUNT} of {STATIONS} stations flagged ({DAYS} days)"
    }

  4 of 12 stations become flagged
    -> red strip: 4 of 12 stations flagged (7 days)
  It fires once when the share reaches 33%, clears when it drops back
  below, and can fire again after that.

Example 11 (Status Board): Water shortages
  Event: Station newly flagged   Report types: F!500
  Narrow it down: F!500 questions: water
  Display: ALR   Banner: {FROM} short of water ({GRID})

    {
      "id": "board-water",
      "name": "Water shortage",
      "source": "statusboard",
      "event": "newly_flagged",
      "types": ["f500"],
      "conditions": { "f500_questions": ["water"] },
      "display": "ALR",
      "banner_text": "{FROM} short of water ({GRID})"
    }

  Fires when a station's F!500 is flagged and its worst answer is the
  water question. The F!500 question names are: mood eggs milk bread
  water gasoline diesel propane batteries containers ammo materials.


A WHOLE PROFILE FILE
--------------------
The settings window writes this for you; it's shown so a coordinator
can read or hand-edit one. It's for a made-up group, @MYGROUP: give a
real one its own profile_id. ("sitrep" belongs to SitRepNet's profile;
a file using it would replace SitRepNet's on a member's station.)
AlertDisplay_SitRep_Group_Profile.json, in the program folder, is a
complete one in use.

    {
      "format": "alertdisplay_profile",
      "version": "1.1",
      "kind": "group",
      "profile_id": "mygroup",
      "name": "My Group (@MYGROUP)",
      "profile_version": "2026-11-10.1",
      "author": "KN4AM",
      "date": "2026-11-10",
      "description": "Alerts for MYGROUP members.",
      "group": "@MYGROUP",
      "defaults": {
        "display": "NTF",
        "minutes": 30,
        "cooldown_minutes": 10,
        "banner_text": "{FROM}: {TEXT}"
      },
      "triggers": [
        { "id": "net-activation", "name": "Net activation",
          "match": { "type": "contains", "text": ["NET ACTIVATED"] },
          "from": ["KN4AM", "W4XYZ"], "to": ["{GROUP}"],
          "display": "ALR", "minutes": 120,
          "banner_text": "NET ACTIVATION ({FROM}): {TEXT}" },
        { "id": "traffic-for-me", "name": "Traffic for my station",
          "match": { "type": "starts_with", "text": ["MSG"] },
          "to": ["{MYCALL}"],
          "banner_text": "{FROM} has traffic for you ({TIME})" }
      ]
    }

  format, version   Always "alertdisplay_profile" and "1.1".
  kind              "group" or "personal".
  profile_id        Lower case letters, digits and hyphens. Never change
                    it.
  profile_version,  Stamped by Export as Group Profile.
  author, date
  group             Where {GROUP} comes from. Include the @.
  defaults          Used by triggers that leave a value out.
  triggers          In the order they're checked.

  The second trigger has no display, minutes or cooldown_minutes, so it
  takes the defaults: NTF, 30 minutes, cooldown 10.

  File rules: a field left out means "no limit" (from, to) or "use the
  default"; an empty list ("from": []) is an error; fields AlertDisplay
  doesn't know are kept and ignored. Full field lists are in the User
  Manual, PROFILE FILE FORMAT.


COMMON MISTAKES
---------------
"{GROUP}" never matches
  The Group callsign is missing its @ ("SITREP" instead of "@SITREP"),
  or the message was sent to a different group.

A {MYCALL} trigger is skipped
  No Station callsign is set in SitRepMapper (Settings > General).

"Whole word" misses ALERTS
  It's a different word. Add ALERTS as another match text, or use
  Contains.

"Starts with" never fires
  It must be right after the TO. "@SITREP MSG SITREP-ALERT ..." doesn't
  start with SITREP-ALERT; use Whole word for a code. Try the message
  on Test a Message.

The wrong banner text shows
  A more general trigger is above a specific one, or an ALR trigger
  elsewhere also matched (ALR always wins). Move the specific trigger
  up; Test a Message lists every match and which one is used.

A relayed message doesn't match From
  From is the station after *DE* (who sent it first), not the relay.

A message matched but nothing showed
  Check the Log tab: the sender may be kept out by a callsign list, or
  it was a repeat inside the cooldown.

Too many alerts
  Use a code such as SITREP-ALERT, add a From or To, make it NTF, or raise
  the cooldown. Plain words turn up in chatter and automated weather
  posts.

A Status Board trigger never fires
  See the Status Board tab: the file must be found and not stale. The
  station may already have been flagged when the monitor started, or
  the narrowing may be stricter than meant. Remember "flagged" is
  decided by SitRepMapper's thresholds.

A trigger works for you but not for a member
  Their {MYCALL}, their callsign lists, or their own on/off choice for
  that trigger may differ. Their Log tab shows what happened.


================================================================================
  End of AlertDisplay — Building Profiles and Triggers
  Designed and developed by Stephen Clay McGehee, KN4AM
  Coding done using Claude Code AI
  See SitRepNet.com for more information
================================================================================
