Metadata-Version: 2.4
Name: fjortoft
Version: 0.1.0
Summary: GCP network coherence poller and corru.observer GAD Discord bot
License-Expression: MIT
Project-URL: Homepage, https://github.com/SiteRelEnby/fjortoft
Project-URL: Repository, https://github.com/SiteRelEnby/fjortoft
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: discord
Requires-Dist: discord.py>=2.3.0; extra == "discord"
Dynamic: license-file

# gadcheck

Polls the [GCP 2.0](https://gcp2.net) live data API every 5 minutes and exposes the current Network Coherence value — plus a faithful recreation of the [corru.observer](https://corru.observer) **GAD** mechanic — via HTTP endpoints compatible with Prometheus and old `gcpdot.com` consumers.

## Background

The [Global Consciousness Project](https://gcp2.net) (GCP) operates a worldwide network of hardware random number generators ("eggs"). Statistically, random numbers should be uniformly distributed. When the network shows unusual correlation — more coherent or less coherent than chance would predict — the deviation is measured and exposed as a live metric. The current project home is [gcp2.net](https://gcp2.net), led by the HeartMath Institute; background is also on [Wikipedia](https://en.wikipedia.org/wiki/Global_Consciousness_Project) and the [Institute of Noetic Sciences](https://noetic.org/research/global-consciousness-project/).

The live page visualizes a **Network Variance** (`netvar`) value that represents the degree of deviation across the egg network.

### The old GCP Dot

[gcpdot.com](https://gcpdot.com) was the canonical "live dot" visualization — a colored circle that changed based on the current network state. Its API (`/gcpindex.php?small=1`) returned a decimal **p-value** (0.0–1.0): the cumulative probability that the current network variance is as extreme as it is. A value near 0.5 means the network is behaving exactly as expected; values near 0 or 1 represent anomalies in opposite directions.

gcpdot.com appears to be defunct. gcp2.net exposes a different but related metric (see below).

---

## API reverse-engineering notes

The gcp2.net live page loads three data-related JavaScript files:

| File | Purpose |
|------|---------|
| `/js/data/api_token.js` | Bearer token for API auth |
| `/js/data/gauge.js` | Fetches current netvar, drives gauge animation |
| `/js/data/timeseries1.js` | Fetches 24H history via Web Worker, drives time series chart |

### Endpoints

All endpoints require `Authorization: Bearer <token>` and browser-like headers (Cloudflare blocks the default Python user-agent).

| Endpoint | Method | Response |
|----------|--------|----------|
| `/api/getcurrentnetvar` | GET | `{"netvar": [{"netvar": "108.09"}]}` |
| `/api/getcolorzones` | GET | Array of color band definitions with RGB, label, range |
| `/api/getNetVarAggregate24H` | GET | 1440 objects: `{"end_epoch": ..., "netvar_aggregate": "..."}` |

The gauge polls `getcurrentnetvar` every **60 seconds**. This poller uses **5 minutes** to be polite.

### netvar vs. the old p-value

The old gcpdot p-value was a statistical probability derived from the current network reading. `netvar` is an **absolute variance integer** — not a probability, not a percentile. The two are related but not directly comparable:

- `netvar` high → network is more coherent/anomalous than usual → old dot would show a high p-value
- `netvar` low → network is closer to fully random → old dot would show a low p-value

The gcp2.net site defines color zones for absolute netvar thresholds:

| Label | Range | Color |
|-------|-------|-------|
| Normal | 0–140 | `#e200e2` (magenta) |
| Elevated | 140–166 | `#00c9f8` (cyan) |
| High | 166–219 | `#ffc543` (orange) |
| Very High | 219–279 | `#ffff00` (yellow) |
| Extreme | 279+ | `#fefcda` (near-white) |

---

## How GAD is calculated

### What GAD is

**GAD** (Global Ambient Dissonance) is a game mechanic in [corru.observer](https://corru.observer) by corru. It appears in the system management menu as an integer from -2 to 2 and affects rendering of Mindspike thoughtspaces — low GAD causes graphical degradation and opens normally-inaccessible paths; high GAD lowers music pitch in certain areas.

The game fetches a live value from gcpdot.com and converts it to a GAD level. Since gcpdot.com is defunct, so is the mechanic.

### The conversion table

Source: [corru.observer wiki — Mindspike](https://corru.wiki/wiki/Mindspike)

| GAD | Description | GCP Dot Index | In-game effect |
|-----|-------------|---------------|----------------|
| 2 | `overcoherency block, exercise caution` | above 95th percentile | Almost none* |
| 1 | `overcoherency fluctuation` | 80th–95th percentile | Almost none* |
| 0 | `coherent` | 20th–80th percentile | Normal |
| -1 | `incoherence fluctuation` | 5th–20th percentile | Many graphical changes, opens paths |
| -2 | `widespread incoherency, exercise caution` | below 5th percentile | Same as -1, more degraded visuals |

\* The only overcoherency effect is lowering the pitch of the music in Their Waters by an octave.

### The "GCP Dot Index" is a percentile

The key detail: "GCP Dot Index" is not the raw netvar — it's a **percentile** of the current value within the recent distribution. The old gcpdot p-value naturally encoded this (0.95 = 95th percentile of expected deviation). With gcp2.net's absolute netvar, we reconstruct the percentile by:

1. Fetching the full 24H history (`/api/getNetVarAggregate24H` — 1440 one-minute points)
2. Sorting it
3. Computing where the current value falls: `percentile = bisect(sorted_history, current_netvar) / 1440 * 100`
4. Mapping the percentile to GAD via the table above

This means **GAD is always relative to the past 24 hours**, not an absolute threshold. A `netvar` of 50 might be GAD 0 on a quiet day and GAD 2 on a very low-activity day. The 24H history is refreshed every 30 minutes.

### Why this matters

The gcp2.net color zones (Normal/Elevated/High/etc.) answer "how extreme is this in absolute terms?" GAD answers "how unusual is this *right now* compared to recent history?" These diverge: a low-but-stable `netvar` can read as "Normal" on the gauge while GAD is -1 (incoherence) because it's in the bottom 16% of today's values.

---

## Add Fjortoft to your server

**[Click here to add Fjortoft](https://discord.com/oauth2/authorize?client_id=1491715011179970671)**

Source: [github.com/SiteRelEnby/fjortoft](https://github.com/SiteRelEnby/fjortoft)

Requires a server admin to approve. Commands available after install:
- `/gad` — current GAD level
- `/gcpstatus` — full network coherence detail
- `/fjortoft-status` — bot and poller health

---

## Running

```bash
python3 gcp_poller.py          # listens on :9101
python3 gcp_poller.py 8080     # custom port
```

No dependencies beyond the Python 3.12+ standard library.

Startup takes ~8–10 seconds: three sequential API calls (color zones, 24H history, initial poll) all go through Cloudflare.

---

## Endpoints

### `GET /status`

Full JSON snapshot:

```json
{
  "netvar": 94.05,
  "percentile": 62.3,
  "gad": 0,
  "gad_description": "coherent",
  "label": "Normal",
  "color": "#e200e2",
  "updated_at": 1775710364.5,
  "history_updated_at": 1775710360.2,
  "stale": false,
  "poll_count": 7,
  "poll_errors": 0
}
```

### `GET /metrics`

Prometheus text format (pull model). Metrics exposed:

| Metric | Type | Description |
|--------|------|-------------|
| `gcp_network_coherence_netvar` | gauge | Raw netvar value |
| `gcp_network_coherence_percentile` | gauge | Percentile within past 24H (0–100) |
| `gcp_network_coherence_gad` | gauge | GAD level (-2 to 2) |
| `gcp_network_coherence_stale` | gauge | 1 if last poll > 2× interval ago |
| `gcp_network_coherence_last_updated_seconds` | gauge | Unix timestamp of last poll |
| `gcp_network_coherence_poll_total` | counter | Successful polls since start |
| `gcp_network_coherence_poll_errors_total` | counter | Failed polls since start |
| `gcp_network_coherence_info` | gauge | Labels: `label`, `color`, `gad_description` |

Prometheus scrape config:

```yaml
scrape_configs:
  - job_name: gcp_coherence
    static_configs:
      - targets: ['localhost:9101']
    scrape_interval: 60s   # no point scraping faster than the poll interval
```

### `GET /dot`

Bare uppercase hex color string (e.g. `E200E2`). Drop-in replacement for the old `gcpdot.com/gcpindex.php?small=1` response format that the [quartzjer gist](https://gist.github.com/quartzjer/6a3270e0252a572236ad) and similar consumers expected.

---

## Grafana dashboard

Import `grafana_dashboard.json` from this repo. You\'ll be prompted to select your Prometheus datasource on import. The dashboard includes:

- Current netvar (gauge panel with gcp2.net color zones)
- Current GAD level (stat panel, color-coded -2 to 2)
- Current percentile (gauge, 0–100)
- Stale data indicator
- 24H netvar time series with zone threshold bands
- 24H GAD time series

---

## References

- [Global Consciousness Project](https://gcp2.net) — current main site
- [GCP live data page](https://gcp2.net/data-results/live-data)
- [Global Consciousness Project — Wikipedia](https://en.wikipedia.org/wiki/Global_Consciousness_Project)
- [GCP — Institute of Noetic Sciences](https://noetic.org/research/global-consciousness-project/)
- [corru.observer](https://corru.observer) — game that uses GAD
- [corru.observer wiki — Mindspike](https://corru.wiki/wiki/Mindspike) — GAD conversion table source
- [gcpdot.com](https://gcpdot.com) — original GCP dot (defunct)
- [quartzjer/gcpdot node wrapper](https://gist.github.com/quartzjer/6a3270e0252a572236ad) — old gcpindex.php color mapping reference
