factcircuit
FactCircuit는 불변 출처와 단계별 검증, 제한된 검색, 재현 가능한 평가를 제공하는 감사 가능한 주장·증거 검증 루프입니다
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Oddsmaker is a single-company, multi-game, multi-environment Game Intelligence Platform with built-in analytics, experimentation and risk — 单公司部署的游戏智能数据平台(实时分析 + 实验 + 风控内建)。
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Oddsmaker 是一套面向单个游戏公司的实时分析与风控平台。 它的定位是一家公司内部统一管理多个游戏、多个环境的数据基础设施。核心隔离边界是 game_id + environment。 Oddsmaker 来自赌场和博彩行业,指负责制定赔率的人。这个角色本质上依赖两类能力: • 数据判断:根据历史行为、概率分布、市场变化和结果反馈不断修正判断。 • 风险控制:赔率不是随便拍脑袋给的,背后一定包含敞口控制、异常识别和动态调整。 这个名字适合当前项目,因为平台的目标也不是单纯“收集事件”,而是把游戏数据分析、实验优化和风险控制放到同一条链路里。 • 实时采集 Web、Android、iOS、Unity、Server 事件 • 会话、留存、漏斗、收入、关卡、虚拟经济、广告分析 • A/B 实验配置、分流、曝光事件与结果分析 • 统一 game_id + environment 数据边界 • Tracking Plan / Schema 治理 • JSON Schema + Avro + Registry • 属性白名单、PII 策略、事件大小限制 • 所有新接入统一使用 game_id + environmentREADME 전문 보기 ↗
Oddsmaker is a real-time analytics and risk control platform built for a single gaming company.
It is positioned as the data infrastructure through which one company manages multiple games across multiple environments. The core isolation boundary is game_id + environment.
Oddsmaker comes from the casino and betting industry and refers to the person responsible for setting odds. The role fundamentally relies on two capabilities:
The name fits this project because the platform's goal is likewise not merely to "collect events", but to place game data analytics, experiment optimization, and risk control on a single pipeline.
dev, staging, and prod.storage_profile.game_id + environment data boundarymark, alert, block, review, throttle, and webhooksgame_id + environmentflowchart TB
subgraph SDK
Web[Web SDK]
Mobile[Android / iOS SDK]
Unity[Unity SDK]
Server[Server SDK]
end
subgraph Ingest
Gateway[Gateway /v1/batch]
Guard[API Key / HMAC / Schema / PII / Risk Guard]
end
subgraph Stream
Kafka[Kafka + Schema Registry]
Enrich[Enrich + Dedup + Identity]
Session[Sessions]
Analytics[Retention / Funnels / Revenue]
Risk[Risk Detection]
end
subgraph Storage
ClickHouse[(ClickHouse)]
Postgres[(PostgreSQL)]
Redis[(Redis)]
Archive[(Object Storage / Archive)]
end
subgraph Apps
Control[Control Service]
Dashboard[Realtime Dashboard]
BI[Superset / Metabase]
Webhook[Game Server Webhook]
end
Web --> Gateway
Mobile --> Gateway
Unity --> Gateway
Server --> Gateway
Gateway --> Guard
Guard --> Kafka
Kafka --> Enrich
Kafka --> Session
Kafka --> Analytics
Kafka --> Risk
Enrich --> ClickHouse
Session --> ClickHouse
Analytics --> ClickHouse
Risk --> ClickHouse
Risk --> Redis
Risk --> Webhook
Control --> Postgres
Control --> Gateway
ClickHouse --> Dashboard
ClickHouse --> BI
Core keys under the target architecture:
game_id = game identifier, e.g. game_demo
environment = dev | staging | prod
storage_profile = shared-nonprod | shared-prod | dedicated-*
event_id = unique ID per event
Events, partitions, queries, experiments, and risk rules all use game_id + environment as the logical boundary.
storage_profile is responsible for physical routing only and never enters the event contract.
services/gateway-service/: ingestion entry point, protocol validation, rate limiting, PII, and pre-ingest risk controlservices/control-service/: games, environments, keys, policies, experiments, and risk managementjobs/flink/: seven job modules — events-enrich (validation, dedup by game/environment/event id, enrichment), sessions, retention, funnels (one fatJar runs both FunnelsJob and ConfigurableFunnelsJob), risk, identity-merge, dimension-syncagents/: dimension-sync-agent — a dimension synchronizer deployed inside the game studio's intranet (zero in-repo dependencies)ml/: the oddsmaker-ml training pipeline — four trainable model families (churn / pltv / risk / propensity) in Python, with heuristic baselines for comparisonlibs/: shared models, authentication, Kafka, and observability componentsschema/: Avro, JSON Schema, ClickHouse DDL, and query scriptssdks/: Web, Android, iOS, Unity, and Server SDKsbi/: Superset resourcesinfra/: Docker Compose, K8s, Helm, Grafana, Prometheusdocs/: architecture, API, operations, redesign, and roadmapweb/: Vue 3 operations console (source under web/src/, built assets ship with releases)scripts/: helper scripts (quickstart, e2e, superset import, perf tooling)tests/: cross-cutting test resourcesdeploy/: deployment resources (K8s manifests, monitoring alerts/dashboards, demo)deploy-rt/: real-time deployment compose stacksMakefile (dev task entry), Dockerfile (multi-stage server image), docker-compose.yml (full stack), docker-compose.quickstart.yml (quickstart stack), pnpm-workspace.yaml (web/docs workspace)Demo site: https://oddsmaker.cuihairu.site/ | Demo account demo (for trial use; data is reset periodically). The demo environment's password is set at deploy time (see deploy/demo/) and may be rotated — it is not a fixed credential distributed with the repo.
The demo site is for trial purposes only: data is reset periodically, so do not store real business data there. The demo account has the read-only VIEWER role. For private deployment, follow the Docker Compose path below.
A single command brings up the server side (control + gateway in a single image) together with all dependencies (PostgreSQL / Redis / Kafka / Apicurio / ClickHouse), with ports, volumes, and health checks fully configured:
# Optional: copy the environment config and adjust ports / passwords / tokens as needed (comments in Chinese)
cp .env.example .env
docker compose -f docker-compose.quickstart.yml up -d
# Check health status (ready once every service is healthy)
docker compose -f docker-compose.quickstart.yml ps
# Verify the APIs
curl http://localhost:38085/actuator/health # control (management plane)
curl http://localhost:38080/actuator/health # gateway (ingestion entry)
The image ships two services in a single artifact: ghcr.io/cuihairu/oddsmaker. At runtime, the SERVICE environment variable selects control (8085) or gateway (8080):
docker pull ghcr.io/cuihairu/oddsmaker:nightly
# Control service (SERVICE=control)
docker run -d --name oddsmaker-control \
-p 38085:8085 \
-e SERVICE=control \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://<pg>:5432/oddsmaker \
-e ODDSMAKER_ADMIN_TOKEN=dev-admin-token \
ghcr.io/cuihairu/oddsmaker:nightly
# Gateway service (SERVICE=gateway)
docker run -d --name oddsmaker-gateway \
-p 38080:8080 \
-e SERVICE=gateway \
-e ODDSMAKER_KAFKA_BOOTSTRAP=<kafka>:9092 \
-e ODDSMAKER_CONTROL_URL=http://<control>:8085 \
-e ODDSMAKER_CONTROL_INTERNAL_TOKEN=dev-internal-token \
ghcr.io/cuihairu/oddsmaker:nightly
The root Dockerfile is a multi-stage build (Gradle compilation → eclipse-temurin:21-jre-alpine runtime), runs as a non-root user, and includes a built-in healthcheck; the build context must be the repository root:
docker build -t ghcr.io/cuihairu/oddsmaker:local .
Image tagging: CI publishes :nightly on the daily schedule and on every push to main (nightly-build.yml), and publishes :<version>, :<major.minor>, :<major>, and :latest on releases (release.yaml).
After the full CI test suite passes, a rolling nightly build (tag fixed at nightly) is published on the Releases page at 00:00 UTC daily and on every push to main: server distribution packages for five platforms — Linux x64/arm64, macOS x64/arm64, and Windows x64 — containing control + gateway, six Flink job fatJars, the dimension-sync agent, Web console/SDK static assets, and startup scripts. Each package carries a BUILD_INFO file, and each release includes VERIFY.md (SHA256 checksums for all assets).
To try out the scripts and streaming jobs:
bash scripts/e2e.sh
bash scripts/superset-import.sh
bash scripts/run_flink.sh
Notes:
./gradlew test --continue (Gradle Wrapper 9.8.1, JDK 21).pnpm -C web test && pnpm -C web build (for development, pnpm -C web dev, which proxies to control on 8085).The current priorities are:
game_id + environmentThe foundation is built on open-source components: Spring Boot, Kafka, Flink, ClickHouse, PostgreSQL, Redis, Superset, and others; what this repository implements itself is the wiring, the business layers, and the SDKs.
The current version is v0.2.0 (unreleased); the repository's positioning and naming have converged:
Oddsmaker, and the package namespace is unified as io.oddsmakerhttps://github.com/cuihairu/oddsmaker.gitDelivered capabilities: ingestion gateway (/v1/batch + event contract v2), control plane (games / environments / keys / 8-role permissions / experiments / risk rules), seven Flink job modules — six fatJars (enrich / sessions / retention / funnels / risk / identity-merge; the production compose runs seven job containers because the funnels fatJar double-runs) plus dimension-sync, which also ships as the in-studio agent (five source types) — SDKs for five platforms, training and batch scoring for four ML model families, and the web console.
Restructure 2.0 batches B1–B10 have all been accepted, including event contract v2 increments, Server SDK, gateway authoritative backfill with self-raised rejection, the risk feature layer (risk_features with three-stage decoupling of FEATURE rule values), the RiskScore/Decision state machine, EventSchema as a first-class resource, experiment platform formalization, the runtime mode matrix, and data quality with a shared feature store; further work proceeds batch by batch per todo.md.