1 Lottery Colour Prediction – Hot/Cold Digits, Trends & Fun Stats
Updated: · KeralaLottery.info Editorial
This page computes hot/cold digits, colour distribution (Red/Green/Violet), streaks, and a simple transition (Markov) model from the live API. It is educational & for fun only — results are chance-based; please play responsibly (18+).
Live Data & Window
Key Stats
Hot Digits
Cold Digits
Colour Share
Current Streak
Longest Streak
Next-Colour (Markov, fun)
Distributions & Transition Matrix
| Digit | Count | Share |
|---|---|---|
| Loading… | ||
| Current ↓ / Next → | Red | Green | Violet |
|---|---|---|---|
| Loading… | |||
Last Results (Preview)
| # | Period | Time | Result | Colour |
|---|---|---|---|---|
| Loading… | ||||
How These “Predictions” Are Calculated
- Windowed stats: You choose a window (20/50/100/200). We compute digit frequencies, colour shares and streaks on that subset.
- Markov (transition) model: We estimate a first-order transition matrix P(next_colour | current_colour) from the window. The “Next-Colour” line shows the highest probability given the latest colour. This is fun-only, not financial advice.
- Live data: We call /wp-json/one/v1/today plus (if available) /wp-json/one/v1/history. We support ETag (conditional GET) to reduce bandwidth.
- Limits: Chance-based outcomes can deviate from short-term stats; patterns can break anytime. Please play responsibly (18+).
Tip: Larger windows are smoother but slower to react; smaller windows are more reactive but noisy.
1 Lottery API – Production Checklist & Best Practices
This section documents the public read endpoints used on this site and the recommended server behaviors for smooth, low-latency widgets.
1) Endpoints & Schemas
- GET /wp-json/one/v1/today → Live window for the current day.
Response (example):{ "date": "2025-09-16", "timezone": "+05:30", "items": [ {"period":"20250916-1200","time":"12:00","result":"7","colour":"Green"}, {"period":"20250916-1201","time":"12:01","result":"0","colour":"Violet"} ] } - GET /wp-json/one/v1/history?limit=&offset=&since=&after=&order= → historical slice.
Recommended query params:- limit (1–500, default 200), offset (for pagination)
- since=YYYY-MM-DD (UTC date) or after=YYYYMMDD-HHMM (period id)
- order=desc|asc (default desc)
- POST /wp-json/one/v1/admin/push (write) & POST /wp-json/one/v1/admin/reset (maintenance) — authenticated.
2) Caching & Freshness
- ETag + 304 on /today and /history to avoid re-sending unchanged JSON.
- Cache-Control for /today: public, max-age=5, stale-while-revalidate=30 — keeps widgets snappy with minimal flicker.
- Stable hashing: compute ETag from the exact JSON payload (e.g., md5( wp_json_encode( $data ) )).
WordPress snippet — add ETag/Cache headers
/** In your plugin main file */
add_filter('rest_post_dispatch', function($result, $server, $request){
$route = $request->get_route();
if (strpos($route, '/one/v1/today') !== false || strpos($route, '/one/v1/history') !== false) {
$data = $result->get_data();
$json = wp_json_encode($data);
$etag = '"' . md5($json) . '"';
// Conditional GET
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : '';
if ($if_none_match === $etag) {
// 304, no body
header('ETag: ' . $etag);
header('Cache-Control: public, max-age=5, stale-while-revalidate=30');
status_header(304);
exit; // stop further output
}
// Fresh
header('ETag: ' . $etag);
header('Cache-Control: public, max-age=5, stale-while-revalidate=30');
header('Content-Type: application/json; charset=utf-8');
}
return $result;
}, 10, 3);
/** Public CORS (read-only). Keep admin writes auth-only & no wildcard CORS. */
add_action('rest_api_init', function(){
add_action('rest_pre_serve_request', function($served, $result, $request){
$route = $request->get_route();
if (strpos($route, '/one/v1/') !== false && $request->get_method() === 'GET') {
header('Access-Control-Allow-Origin: *');
header('Vary: Origin');
}
return $served;
}, 10, 3);
});
3) Filtering, Paging & Incremental Sync
- since: /history?since=2025-09-01 — return all rows on/after that date.
- after: /history?after=20250916-1200 — return rows strictly after that period id.
- Order & paging: ensure deterministic results with order=asc|desc, plus limit/offset.
WordPress snippet — support since / after
register_rest_route('one/v1', '/history', [
'methods' => 'GET',
'callback' => function(WP_REST_Request $req){
$limit = max(1, min(500, intval($req->get_param('limit') ?: 200)));
$offset = max(0, intval($req->get_param('offset') ?: 0));
$since = sanitize_text_field($req->get_param('since') ?: '');
$after = sanitize_text_field($req->get_param('after') ?: '');
$order = strtolower($req->get_param('order') ?: 'desc');
$order = in_array($order, ['asc','desc'], true) ? $order : 'desc';
// Example: read from your storage (file/DB). Filter by $since/$after.
$rows = one_lottery_storage_read_all(); // return most-recent-first array
if ($since) { $rows = array_filter($rows, fn($r)=>substr($r['period'],0,8) >= str_replace('-','',$since)); }
if ($after) { $rows = array_filter($rows, fn($r)=>strcmp($r['period'],$after) > 0); }
if ($order === 'asc') { $rows = array_reverse($rows); }
$slice = array_slice(array_values($rows), $offset, $limit);
return ['items' => $slice];
},
'permission_callback' => '__return_true',
]);
4) Compression
- Enable gzip/brotli for JSON to cut bandwidth.
Nginx (example)
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types application/json application/javascript text/plain text/css;
# If you use brotli:
brotli on;
brotli_comp_level 5;
brotli_types application/json application/javascript text/plain text/css;
5) Security
- Writes require auth: use WordPress Application Passwords (Basic Auth) or a long random Bearer token stored server-side.
- Rate limit public reads (e.g., 60 req/min/IP) to absorb spikes. Return HTTP 429 with Retry-After.
- Validate input on /admin/push: period matches ^\d{8}-\d{4}$, time is HH:MM, result in 0–9, colour in {Red, Green, Violet}.
- Audit log for writes with timestamp/user/IP and rotate logs.
WordPress snippet — simple read rate-limit
add_filter('rest_request_before_callbacks', function($response, $handler, $request){
$route = $request->get_route();
if (strpos($route, '/one/v1/') !== false && $request->get_method()==='GET') {
$ip = $_SERVER['REMOTE_ADDR'] ?? 'na';
$key = 'one_rl_' . md5($ip);
$hits = (int) get_transient($key);
if ($hits > 60) { // >60 req/min
return new WP_Error('rate_limited','Too Many Requests', ['status'=>429, 'Retry-After'=>60]);
}
set_transient($key, $hits+1, MINUTE_IN_SECONDS);
}
return $response;
}, 10, 3);
6) Versioning & Time
- Namespace already includes version (one/v1); reserve v2 for breaking changes.
- All times are IST (UTC+05:30). period uses YYYYMMDD-HHMM in IST.
7) Errors
- Content-Type: application/json; charset=utf-8
- Shape (example): { "error": { "code":"rate_limited", "message":"Too Many Requests" } }
- Use proper HTTP status: 200/304/400/401/403/404/429/500.
8) cURL Examples
# Conditional GET with ETag (client-side caching)
curl -i -H "If-None-Match: <etag-from-last-response>" \
https://www.keralalottery.info/wp-json/one/v1/today
# Historical slice since a date
curl -s "https://www.keralalottery.info/wp-json/one/v1/history?since=2025-09-01&limit=200&order=asc"
# Incremental fetch after a period id
curl -s "https://www.keralalottery.info/wp-json/one/v1/history?after=20250916-1200&limit=200"
# Admin push (WordPress Application Password)
curl -u "KeralaLottery:<YOUR_APP_PASSWORD>" \
-H "Content-Type: application/json" \
-d '{"period":"20250916-1300","time":"13:00","result":"5","colour":"Red"}' \
https://www.keralalottery.info/wp-json/one/v1/admin/push
9) Optional: OpenAPI Sketch
openapi: 3.0.0
info:
title: 1 Lottery API
version: 1.0.0
servers:
- url: https://www.keralalottery.info/wp-json/one/v1
paths:
/today:
get:
summary: Live results for today
responses:
"200": {description: OK}
"304": {description: Not Modified}
/history:
get:
summary: Historical results
parameters:
- {name: limit, in: query, schema: {type: integer, minimum: 1, maximum: 500}}
- {name: offset, in: query, schema: {type: integer, minimum: 0}}
- {name: since, in: query, schema: {type: string, pattern: "^\d{4}-\d{2}-\d{2}$"}}
- {name: after, in: query, schema: {type: string, pattern: "^\d{8}-\d{4}$"}}
- {name: order, in: query, schema: {type: string, enum: [asc,desc]}}
responses:
"200": {description: OK}
"304": {description: Not Modified}
/admin/push:
post:
security: [{basicAuth: []}]
responses: {"200": {description: OK}}
components:
securitySchemes:
basicAuth: {type: http, scheme: basic}
10) Monitoring
- Add X-Trace-Id and log it with each request to correlate errors.
- Expose a lightweight /wp-json/one/v1/health for uptime checks (returns 200 + storage status).
FAQ – Colour Prediction
Is this reliable?
No. These are retrospective statistics for fun. Outcomes are chance-based and can diverge from short-term patterns.
How often should I refresh?
The widget auto-refreshes every 60s. You can also click “Refresh Now”.
What window is best?
Try 50 or 100 for balance. 20 is very reactive; 200 is smoother but slower.
Why do colours sometimes cluster?
Random sequences can show streaks or clusters; that’s a normal property of randomness.