.. include:: ../variables.rst .. _challenges-concepts: Concepts and Building Blocks ============================ Before creating your first challenge it helps to understand the five ideas |APPNAME| ties together: **metric**, **scope**, **threshold**, **reward**, and **close**. .. figure:: /images/challenges/lightmode/challenge-concepts-diagram.png :align: center :width: 85 % |br| Metric -- what you are measuring -------------------------------- The metric decides *how* a participant is scored. |APPNAME| supports four: .. list-table:: :header-rows: 1 :widths: 25 20 55 * - Metric - Value code - Meaning * - Observation count - ``0`` - Raw number of hand-hygiene observations in scope. * - Compliance % - ``1`` - Percentage of observations where a rub or wash was recorded. * - Improvement delta - ``2`` - Current-period compliance **minus** prior-period compliance (in percentage points). Requires prior-period dates. * - Longest streak - ``3`` - Length (in days) of the longest consecutive run where daily compliance stayed at or above the configured streak threshold. Scope -- who is competing ------------------------- The scope decides *who* is eligible. Every challenge resolves its scope to a **list of participants** at compute time; each participant is scored independently: .. list-table:: :header-rows: 1 :widths: 25 15 60 * - Scope - Code - Participants * - Facility - ``0`` - Every facility in the corporation (or one specific facility, if set). * - Unit - ``1`` - Every patient-care area (unit) under the corporation's facilities. * - Auditor - ``2`` - Every user who has recorded at least one session. * - HCP Type - ``3`` - Every distinct healthcare-provider type that appears in the data. * - Team - ``4`` - Every active team defined under :ref:`challenges-teams`. Threshold and comparator -- the goal ------------------------------------ The **threshold** is the number a participant must reach; the **comparator** is the direction. * **Comparator 0 (≥)** -- participant meets the goal when their metric is **at or above** the threshold. * **Comparator 1 (≤)** -- participant meets the goal when their metric is **at or below** the threshold. Combined examples: * *"≥ 90% compliance this month"* -- metric = Compliance %, threshold = ``90``, comparator = ≥. * *"Record at least 50 observations this quarter"* -- metric = Count, threshold = ``50``, comparator = ≥. * *"Improve by at least 5 percentage points"* -- metric = Improvement delta, threshold = ``5``, comparator = ≥. * *"Maintain a 14-day streak at 85%"* -- metric = Longest streak, threshold = ``14``, streak threshold = ``85``. Reward -- what winners receive ------------------------------ Each challenge can award: * **Points** -- any non-negative integer. Points accumulate in the :ref:`challenges-points-ledger`. * **Badge** -- any badge from the catalogue. The badge is granted once per winner, permanently. Rewards are optional. A challenge with zero points and no badge still records who met the goal -- the results can be used for recognition, reporting, or downstream manual rewards. Close -- when the awards happen ------------------------------- A challenge moves through three states: #. **Active** -- within its date window; results can be previewed and recomputed. #. **Closed** -- the admin (or the auto-close job) has run **Close**. At close time |APPNAME|: * Writes the final results snapshot to ``challenge_results``. * Inserts points and badge grants for every winner (``met = 1``). * Evaluates :ref:`challenges-badge-auto-rules` for each winner and grants any tier badges whose thresholds are now satisfied. * Queues an email notification in the mail outbox for auditor winners who have an email on file. #. **Inactive** -- the challenge is disabled but not closed; no awards are ever made from this state. Close is **idempotent**. Running it twice has no effect the second time -- a unique constraint on the ledger prevents double-awards, and the state check short-circuits immediately. The ledger ---------- Every point grant, redemption, expiry or adjustment lives in ``challenge_points_ledger``. Entries are signed: * **Earned** (``reason = 0``) -- positive. Created on challenge close. * **Redeemed** (``reason = 1``) -- negative. Created by the redemption endpoint. * **Expired** (``reason = 2``) -- negative. Created when points age out. * **Adjusted** (``reason = 3``) -- positive or negative. Manual correction by an administrator. A participant's current balance is simply ``SUM(points)`` across all their ledger rows. The :ref:`challenges-participant-profile` page computes this for you.