fairy

package module
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 23, 2026 License: MIT Imports: 14 Imported by: 0

README

Fairy

A Go library for fetching and enriching Zenless Zone Zero player profiles

CI Game Version Go Version Go Reference

Fetch and enrich Zenless Zone Zero player profiles via the EnkaNetwork API with localized names, calculated agent stats, and ready-to-use assets.


Installation

Requires Go 1.22+

go get github.com/kirinyoku/fairy

Quick Start

Fetch a player's showcase profile and inspect their agents with zero configuration:

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/kirinyoku/fairy"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    profile, err := fairy.GetProfile(ctx, "1504687050")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Player: %s (Inter-Knot Lv.%d • %s)\n",
        profile.Nickname, profile.InterknotLevel, profile.Region)

    for _, agent := range profile.Agents {
        fmt.Printf("  • %s Lv.%d [%s / %s]\n",
            agent.Name, agent.Level, agent.AttributeName, agent.SpecialtyName)
    }
}
Player: LOWLEVEL (Inter-Knot Lv.60 • Europe)
  • Nangong Yu Lv.60 [Ether / Stun]
  • Yixuan Lv.60 [Auric Ink / Rupture]
  • Ye Shunguang Lv.60 [Honed Edge / Attack]
  • Harumasa Lv.60 [Electric / Attack]
  • Miyabi Lv.60 [Frost / Anomaly]
  • Remielle Lv.60 [Lumiflux / Anomaly]

Why Fairy?

The raw EnkaNetwork API returns internal numeric IDs, unlabeled stat keys, and unparsed Unity formula strings. Building apps directly on top of it requires maintaining mapping tables and stat formulas across every game patch.

Fairy handles all of this automatically in-memory.

🔍 Click to compare: Raw EnkaNetwork API vs Fairy Enriched Output
Raw EnkaNetwork API Fairy Enriched Output
{
  "Id": 1511,
  "Level": 60,
  "Exp": 0,
  "PromotionLevel": 6,
  "TalentLevel": 0,
  "SkinId": 3115111,
  "UpgradeId": 0,
  "CoreSkillEnhancement": 6,
  "Weapon": {
    "Id": 15388,
    "Level": 60,
    "StarMark": 1,
    "BreakLevel": 6
  },
  "EquippedList": [{
    "Slot": 1,
    "Equipment": {
      "Id": 33041,
      "Level": 15,
      "MainPropertyList": [{
        "PropertyId": 11103,
        "PropertyValue": 550
      }],
      "RandomPropertyList": [
        {"PropertyId": 12103, "PropertyValue": 19},
        {"PropertyId": 31203, "PropertyValue": 9},
        {"PropertyId": 11102, "PropertyValue": 300},
        {"PropertyId": 12102, "PropertyValue": 300}
      ]
    }
  }]
}
{
  "name": "Nangong Yu",
  "level": 60,
  "rarity": "S",
  "attribute_name": "Ether",
  "specialty_name": "Stun",
  "w_engine": {
    "name": "Neon Fantasies",
    "level": 60,
    "modification": 1,
    "rarity": "S",
    "main_stat": {
      "name": "Base ATK",
      "value": 713
    }
  },
  "drive_discs": {
    "slots": [{
      "slot": 1,
      "set": {"id": 33000, "name": "Phaethon's Melody"},
      "level": 15,
      "main_stat": {"property_id": 11103, "name": "HP", "value": 2200, "is_percent": false},
      "sub_stats": [
        {"property_id": 12103, "name": "ATK",          "value": 38,   "is_percent": false, "rolls": 2},
        {"property_id": 31203, "name": "Anomaly Prof", "value": 27,   "is_percent": false, "rolls": 3},
        {"property_id": 12102, "name": "ATK",          "value": 0.09, "is_percent": true,  "rolls": 3}
      ]
    }],
    "set_bonuses": [{
      "set": {"id": 33000, "name": "Phaethon's Melody"},
      "count": 4
    }]
  },
  "stats": {
    "hp": 11188, "atk": 2866,
    "crit_rate": 0.074, "crit_dmg": 0.548,
    "pen_ratio": 0.24, "energy_regen": 1.2
  }
}

Note: JSON snippets are simplified for illustration. Fairy's models provide complete asset URLs, formulas, and breakdown fields.


Core API

Fairy provides global functions for quick one-liners, and a Client struct for full control over networking, caching, and default language.

Method Description Network
fairy.GetProfile(ctx, uid) Fetch, enrich, and return player profile as *fairy.Profile in default language 🌐 HTTP
fairy.GetProfileWithLang(ctx, uid, lang) Fetch, enrich, and return player profile as *fairy.Profile in a specific language 🌐 HTTP
fairy.GetRawProfile(ctx, uid) Fetch raw unparsed profile (*zzz.Profile) directly from EnkaNetwork API via enkanetwork-go 🌐 HTTP
fairy.Enrich(raw) Transform raw profile (*zzz.Profile) into an enriched model (*fairy.Profile) in default language ⚡ In-memory
fairy.EnrichWithLang(raw, lang) Transform raw profile (*zzz.Profile) into an enriched model (*fairy.Profile) in a specific language ⚡ In-memory
fairy.EnrichAgent(raw) Transform raw avatar data (*zzz.AvatarData) into an enriched Agent model (*fairy.Agent) in default language ⚡ In-memory
fairy.EnrichAgentWithLang(raw, lang) Transform raw avatar data (*zzz.AvatarData) into an enriched Agent model (*fairy.Agent) in a specific language ⚡ In-memory
fairy.AgentHighlightProps(agentID) Retrieve recommended combat property IDs ([]PropertyID) for an agent profile by ID ⚡ In-memory
fairy.AllAgentHighlightProps() Retrieve a map of all agents' recommended profile combat property IDs indexed by agent ID ⚡ In-memory
fairy.AgentRecommendedSubStats(agentID) Retrieve recommended Drive Disc sub-stat property IDs ([]PropertyID) for an agent by ID ⚡ In-memory
fairy.AllAgentRecommendedSubStats() Retrieve a map of all agents' recommended Drive Disc sub-stats indexed by agent ID ⚡ In-memory

Feature Highlights

1. Agent Stats — 3 Flexible Representations

Fairy calculates the complete combat stat sheet from base attributes, W-Engines, and Drive Discs:

Mode Accessor Type Best for
Numeric agent.Stats Stats Math calculations, damage simulators (CritRate: 0.05)
Formatted agent.Stats.Formatted() FormattedStats Text output, logs, summaries (CritRate: "5.0%")
UI Breakdown agent.UIStats UIStats In-game style Base + Added = Total with SVG icons & localized names

📖 See ExampleUIStats_List


2. Drive Disc Analysis & Build Scoring

Deep breakdown of Drive Disc sets, substat aggregations, and roll quality:

[!NOTE] Recommended Drive Disc sub-stats are not subjective community opinions or arbitrary theorycrafting. They are sourced directly from the official Zenless Zone Zero in-game recommendation system.

📖 See ExampleDriveDiscs_SubStatTotals


3. Skills, Scaling & Rich Text
  • Flat & Grouped Views: Access all abilities via agent.Skills, or categorized into the 6 in-game UI tabs (basic, special, dodge, chain, assist, passive) with upgrade levels (1–12 active, 0–6 core) via agent.SkillGroups.
  • Dynamic Formulas: Scaling values and daze ratios are evaluated dynamically per skill level.
  • Unity Rich Text: Built-in converters for in-game markup: FormatHTML(), FormatMarkdown(), or FormatPlainText().

📖 See ExampleAgent_SkillGroups


4. Mindscape Cinema & Potential Vision

📖 See ExampleAgent_Mindscapes


5. Player Showcase & Visual Assets
  • Profile Info: Player Nickname, Inter-Knot Level, Server Region, and Server Cache TTL via profile.CacheTTL().
  • Gradient Titles: Two-color gradient titles with hex color helpers (PrimaryColorHex(), SecondaryColorHex()).
  • Media CDN Assets: Direct URLs for high-resolution splash art (agents & skins), W-Engines, discs, badges, namecards, plus vector SVG stat & attribute icons.

📖 See ExampleProfile


Advanced Configuration & Errors

🔧 Custom Client (Timeouts, Retries, Caching, User-Agent)

Use fairy.NewClient with functional options for production deployments:

// import "github.com/kirinyoku/enkanetwork-go/client/zzz"

client, err := fairy.NewClient(
    fairy.WithDefaultLang(fairy.LangJA),
    fairy.WithEnkaOptions(zzz.Options{
        UserAgent:  "MyApp/1.0 (contact@example.com)",
        HTTPClient: &http.Client{Timeout: 10 * time.Second},
        Retry:      &zzz.RetryOptions{MaxAttempts: 2, Delay: 2 * time.Second},
        // Cache: myCacheInstance, // plug in your own zzz.Cache implementation
    }),
)

profile, err := client.GetProfile(ctx, "1504687050")
🚨 Error Handling & Sentinel Errors

Fairy returns structured sentinel errors for reliable error handling with errors.Is:

Error Description
fairy.ErrInvalidUID UID format is invalid (must be 10 numeric digits starting with 10, 13, 15, or 17).
fairy.ErrProfileNotFound The requested profile does not exist or has showcase hidden.
fairy.ErrRateLimit EnkaNetwork API rate limit exceeded.
fairy.ErrMaintenance API or game servers are under maintenance.
fairy.ErrNetwork Network-level failure (DNS, connection timeout, etc.).
fairy.ErrEnrichment In-memory metadata mapping or formula evaluation error.

Supported Languages

Fairy includes zero-config in-memory localization for all 13 official languages — embedded directly into the binary with no extra network requests.

🌐 Supported Languages Table
Language Native Name Constant Code
English English fairy.LangEN "en"
Russian Русский fairy.LangRU "ru"
Japanese 日本語 fairy.LangJA "ja"
Chinese (Simplified) 简体中文 fairy.LangZHCN "zh-cn"
Chinese (Traditional) 繁體中文 fairy.LangZHTW "zh-tw"
Korean 한국어 fairy.LangKO "ko"
German Deutsch fairy.LangDE "de"
French Français fairy.LangFR "fr"
Spanish Español fairy.LangES "es"
Portuguese Português fairy.LangPT "pt"
Indonesian Bahasa Indonesia fairy.LangID "id"
Thai ภาษาไทย fairy.LangTH "th"
Vietnamese Tiếng Việt fairy.LangVI "vi"

License

Fairy is released under the MIT License.

Documentation

Overview

Package fairy provides a high-performance, modular Go library for fetching, parsing, enriching, and calculating combat stats for Zenless Zone Zero (ZZZ) player profiles via the EnkaNetwork API.

The raw response from Enka.Network contains raw Agent, W-Engine, and Drive Disc IDs. Fairy enriches these raw responses by:

  • Translating IDs into full localized names for Agents, W-Engines, Drive Discs, Skills, and Mindscapes across 13 languages.
  • Constructing complete Enka CDN URLs and inline base64 SVG data URIs for splash arts, avatars, namecards, badges, and stat icons.
  • Calculating exact final combat stats according to the in-game formula (accounting for Agent levels, Promotions, Core Skill Enhancements, W-Engine growth curves, Drive Disc substats, and set bonuses).
  • Evaluating Unity Rich Text formatting, button icon tags, and dynamic level-scaling formulas.
  • Providing Drive Disc substat aggregation, set bonus evaluation, and build quality scoring tools.
  • Validating player UID syntax and resolving server regions locally without network calls.

Key Features

  • Zero-Allocation Metadata Store: Embedded game data loaded once and shared across all queries with lazy-loaded localization.
  • Full Localization: 13 officially supported languages with on-the-fly in-memory enrichment (Enrich, EnrichWithLang, EnrichAgent, EnrichAgentWithLang).
  • Accurate Combat Math: Emulates the exact ZZZ stat calculations including base attributes, weapon scaling, and set bonuses.
  • UI-Ready Stats Breakdown: Pre-calculated base, added, and total values formatted for frontends (UIStats, FormattedStatBreakdown).
  • Rich Text Parsers: Convert game descriptions to clean HTML, Plain Text, or Markdown (Skill.FormatHTML, Skill.FormatPlainText, Skill.FormatMarkdown, SetEffect.FormatHTML).
  • UID Validation & Region Discovery: Instant offline syntax verification (IsValidUID) and server region lookup (RegionFromUID).
  • Cache Governance: Built-in upstream API cache TTL inspection via Profile.CacheTTL.
  • Production-Grade Client: Supports HTTP timeouts, automatic exponential retries, Redis/in-memory caching, and custom User-Agents via zzz.Options.

Architecture & Data Flow

The library separates network fetching, metadata mapping, and combat calculation:

Full Profile Flow:
  [EnkaNetwork API]
         │
         ▼ (HTTP Request via internal API client)
  [zzz.Profile (Raw Upstream Model)]
         │
         ▼ (Enrich / mapper using embedded MetadataStore)
  [fairy.Profile (Enriched Domain Model)]
         ├── Account Info (UID, Nickname, InterknotLevel, Region, Title, Avatar, Badges)
         └── Showcase Agents (max 6)
               ├── Agent Meta (Attribute, Specialty, Rarity, Skin, SplashArt, HighlightProps, RecommendedSubStats)
               ├── Skills & Groups (Basic, Dodge, Special, Chain, Assist, Passives)
               ├── Mindscape Cinema (Ranks 1–6 with unlocked status)
               ├── Potential Vision (Active nodes & descriptions)
               ├── Equipped W-Engine (MainStat, SecondaryStat, Modification)
               ├── Drive Discs (Slots 1–6 with roll counts, active 2-piece & 4-piece Set Bonuses)
               └── Combat Stats Pipeline
                     ├── BaseStats (Agent + W-Engine Base ATK)
                     ├── Stats (Final calculated combat stats)
                     └── UIStats (Pre-formatted Base + Added = Total breakdowns)

Standalone Agent Flow:
  [zzz.AvatarData (Raw Upstream Agent)]
         │
         ▼ (EnrichAgent / mapper using embedded MetadataStore)
  [fairy.Agent (Enriched Domain Model)]

Core Operations

Fairy provides core operations for working with player profiles and individual agents:

Each operation is available as a global top-level function (using a shared thread-safe default client) and as a method on Client.

Quick Start

For standard usage, use the global top-level functions:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

profile, err := fairy.GetProfile(ctx, "1504687050")
if err != nil {
	log.Fatalf("Failed to fetch profile: %v", err)
}

fmt.Printf("Player: %s (Inter-Knot Lv.%d, Server: %s, Cache TTL: %v)\n",
	profile.Nickname, profile.InterknotLevel, profile.Region, profile.CacheTTL())

for _, agent := range profile.Agents {
	fmt.Printf("• %-16s Lv.%-2d [%s / %s]\n",
		agent.Name, agent.Level, agent.AttributeName, agent.SpecialtyName)
}

UID Validation & Server Region Detection

Validate player UIDs and determine their game server region before making network calls:

const uid = "1504687050"
if !fairy.IsValidUID(uid) {
	log.Fatalf("Invalid player UID format: %s", uid)
}

if region, ok := fairy.RegionFromUID(uid); ok {
	fmt.Printf("Server region: %s\n", region) // "Europe"
}

Custom Client Configuration

For production services, configure a custom Client with timeouts, retry policies, custom headers, or persistent caching:

client, err := fairy.NewClient(
	fairy.WithDefaultLang(fairy.LangJA),
	fairy.WithEnkaOptions(zzz.Options{
		UserAgent:  "MyZZZApp/1.0 (contact@example.com)",
		HTTPClient: &http.Client{Timeout: 10 * time.Second},
		Retry: &zzz.RetryOptions{
			MaxAttempts: 3,
			Delay:       1 * time.Second,
		},
		Cache: myCacheInstance, // Implements zzz.Cache interface
	}),
)
if err != nil {
	log.Fatalf("Failed to initialize client: %v", err)
}

profile, err := client.GetProfile(context.Background(), "1504687050")

In-Memory Multi-Language Enrichment

If you need to present the same player profile in multiple languages, fetch the raw profile once and enrich it in memory with Enrich or EnrichWithLang without repeating network requests.

raw, err := fairy.GetRawProfile(ctx, "1504687050")
if err != nil {
	log.Fatal(err)
}

// In-memory mapping — instant, no extra network overhead
enProfile, _ := fairy.Enrich(raw) // Default English
jaProfile, _ := fairy.EnrichWithLang(raw, fairy.LangJA)
ruProfile, _ := fairy.EnrichWithLang(raw, fairy.LangRU)

Individual agents can also be enriched directly without a full profile:

agentEN, _ := fairy.EnrichAgent(rawAvatar)
agentJA, _ := fairy.EnrichAgentWithLang(rawAvatar, fairy.LangJA)

Combat Stat Breakdown & UI Display

Each showcased Agent includes a pre-computed UIStats panel containing formatted breakdowns of base stats vs. added stats (from W-Engines, Drive Discs, and Set Bonuses):

for _, stat := range agent.UIStats.List() {
	fmt.Printf("%-22s %8s (Base: %s + Added: %s)\n",
		stat.Name, stat.Total, stat.Base, stat.Added)
}

Drive Disc & Set Bonus Analysis

Fairy provides helper methods on DriveDiscs and Agent to inspect, evaluate, and score equipped Drive Discs:

// 1. Check active Drive Disc set bonuses (2-piece and 4-piece thresholds)
if agent.DriveDiscs.Has4Piece(fairy.SetPolarMetal) {
	fmt.Println("Polar Metal 4-piece set bonus active!")
}

// 2. Group and sum substats across all 6 disc slots
totals := agent.DriveDiscs.SubStatTotals()
for _, sub := range totals {
	fmt.Printf("%-20s +%-6s (%d rolls)\n", sub.Name, sub.DisplayValue(), sub.Rolls)
}

// 3. Detect recommended / highlighted sub-stats (matching in-game yellow highlights)
for _, disc := range agent.DriveDiscs.Slots {
	for _, sub := range disc.SubStats {
		if agent.IsRecommendedSubStat(sub.PropertyID) {
			fmt.Printf("★ Highlighted: %s +%s\n", sub.Name, sub.DisplayValue())
		}
	}
}

// 4. Count effective substat rolls:
// Automatically evaluated against the agent's recommended sub-stats (RecommendedSubStats):
usefulRolls := agent.CountEffectiveRolls()
fmt.Printf("Recommended Substat Rolls: %d\n", usefulRolls)

// Or evaluated against custom priority stats (e.g. CRIT only):
critRolls := agent.CountEffectiveRolls(fairy.PropCritRate, fairy.PropCritDMG)
fmt.Printf("CRIT Substat Rolls: %d\n", critRolls)

In-Game Recommendation Data

Recommended Drive Disc sub-stats accessed via AgentRecommendedSubStats, AllAgentRecommendedSubStats, and Agent.RecommendedSubStats are verified directly against the official Zenless Zone Zero in-game equipment recommendation system ("Recommend" / L3 build guide). They correspond precisely to the yellow highlight badges displayed next to sub-stats on Drive Discs in the in-game equipment UI.

Error Handling

All API errors map to strongly-typed sentinel errors that can be inspected with errors.Is:

profile, err := fairy.GetProfile(ctx, uid)
if err != nil {
	switch {
	case errors.Is(err, fairy.ErrInvalidUID):
		// Player UID format is invalid (must be 10 digits starting with 10, 13, 15, or 17)
	case errors.Is(err, fairy.ErrProfileNotFound):
		// Profile with specified UID does not exist on game servers
	case errors.Is(err, fairy.ErrRateLimit):
		// Rate limit reached (HTTP 429) — back off and retry
	case errors.Is(err, fairy.ErrMaintenance):
		// Upstream API or game servers are under maintenance
	case errors.Is(err, fairy.ErrNetwork):
		// Network timeout or connectivity issue
	case errors.Is(err, fairy.ErrEnrichment):
		// In-memory transformation, metadata mapping, or stat calculation failed
	default:
		// Other unexpected errors
	}
}

Supported Languages

Supported game languages are defined by the Language type constants: LangEN (English), LangRU (Russian), LangDE (German), LangES (Spanish), LangFR (French), LangID (Indonesian), LangJA (Japanese), LangKO (Korean), LangPT (Portuguese), LangTH (Thai), LangVI (Vietnamese), LangZHCN (Chinese Simplified), and LangZHTW (Chinese Traditional). Use AllLanguages to retrieve the full list programmatically.

Server Regions

Player server regions are identified by the Region type constants: RegionEU (Europe), RegionNA (America), RegionAsia (Asia), and RegionTWHKMO (TW/HK/MO). Use AllRegions to retrieve the full list, or RegionFromUID to resolve a region from a player's UID.

Combat Attributes, Specialties & Drive Disc Sets

Combat attributes, character classes, and equipment sets are defined by strongly-typed constants:

Index

Examples

Constants

View Source
const (
	// EnkaAssetBaseURL is the base HTTPS URL for Enka.Network Zenless Zone Zero CDN UI assets
	// (such as agent splash arts, icons, badges, and W-Engine textures).
	EnkaAssetBaseURL = "https://enka.network/ui/zzz/"
)

Variables

View Source
var (
	// ErrInvalidUID is returned when a provided player UID has an invalid format
	// (e.g. empty, non-numeric characters, length other than 10 digits, or unrecognized server prefix).
	ErrInvalidUID = api.ErrInvalidUID

	// ErrProfileNotFound is returned when the requested player profile with specified UID does not exist
	// or cannot be found by the upstream EnkaNetwork API (HTTP 404).
	ErrProfileNotFound = api.ErrProfileNotFound

	// ErrRateLimit is returned when requests exceed the EnkaNetwork API rate limit (HTTP 429 Too Many Requests).
	// Callers should apply exponential backoff or use a caching layer before retrying.
	ErrRateLimit = api.ErrRateLimit

	// ErrMaintenance is returned when the EnkaNetwork API or upstream game servers are undergoing maintenance,
	// experiencing an outage, or temporarily unavailable (HTTP 500, 502, 503, or 504).
	ErrMaintenance = api.ErrMaintenance

	// ErrNetwork is returned when a transport-level network error occurs while communicating with the API
	// (e.g. DNS resolution failure, connection refused, TLS handshake failure, or context timeout).
	ErrNetwork = api.ErrNetwork

	// ErrEnrichment is returned when in-memory transformation, metadata mapping,
	// or stat calculation fails on raw profile or avatar data.
	ErrEnrichment = errors.New("failed to enrich profile data")
)

Sentinel errors returned by GetProfile, GetProfileWithLang, GetRawProfile, Enrich, EnrichWithLang, EnrichAgent, EnrichAgentWithLang, and *Client methods. Callers should inspect errors using standard errors.Is checks.

Example:

profile, err := fairy.GetProfile(ctx, uid)
if err != nil {
	switch {
	case errors.Is(err, fairy.ErrInvalidUID):
		// Player UID format is invalid (must be 10 digits starting with 10, 13, 15, or 17)
	case errors.Is(err, fairy.ErrProfileNotFound):
		// Player profile does not exist on game servers
	case errors.Is(err, fairy.ErrRateLimit):
		// Rate limit exceeded (HTTP 429) — wait before retrying
	case errors.Is(err, fairy.ErrMaintenance):
		// Upstream API or game servers are under maintenance
	case errors.Is(err, fairy.ErrNetwork):
		// Network connection reset or request timeout
	case errors.Is(err, fairy.ErrEnrichment):
		// In-memory data transformation or metadata mapping failed
	default:
		// Other unexpected error
	}
}

Functions

func AllAgentHighlightProps added in v1.4.0

func AllAgentHighlightProps() map[int][]PropertyID

AllAgentHighlightProps returns a map of all agents' recommended combat property IDs indexed by agent ID, using the shared default client.

Example:

allProps := fairy.AllAgentHighlightProps()
for agentID, props := range allProps {
	fmt.Printf("Agent %d: %v\n", agentID, props)
}

func AllAgentRecommendedSubStats added in v1.4.0

func AllAgentRecommendedSubStats() map[int][]PropertyID

AllAgentRecommendedSubStats returns a map of all known agents to their recommended Drive Disc sub-stats, matching the yellow sub-stat highlights shown in the in-game equipment UI, using the shared default client.

func GetRawProfile

func GetRawProfile(ctx context.Context, uid string) (*zzz.Profile, error)

GetRawProfile fetches the un-enriched zzz.Profile directly from the EnkaNetwork API using the shared default client.

Use this function when you only need the raw numeric IDs from the upstream API without metadata enrichment, or when you want to fetch the upstream payload once and enrich it into multiple languages via EnrichWithLang.

The provided context.Context controls the HTTP request lifecycle, cancellation, and timeout. Returns sentinel errors such as ErrInvalidUID, ErrProfileNotFound, ErrRateLimit, ErrMaintenance, or ErrNetwork.

func IsValidUID added in v1.1.0

func IsValidUID(uid string) bool

IsValidUID reports whether the provided string is a syntactically valid global Zenless Zone Zero UID (10 numeric digits starting with prefix 10, 13, 15, or 17).

Types

type Agent

type Agent struct {
	// ID is the internal numeric identifier of the Agent.
	ID int `json:"id"`

	// Name is the localized display name of the Agent (e.g. "Ellen", "Zhu Yuan", "Miyabi").
	Name string `json:"name"`

	// Level is the current level of the Agent (1–60).
	Level int `json:"level"`

	// Promotion is the current Promotion (ascension) phase of the Agent (0–5).
	Promotion int `json:"promotion"`

	// MindscapeCinema is the unlocked Mindscape Cinema level of the Agent (0–6).
	MindscapeCinema int `json:"mindscape_cinema"`

	// CoreSkillEnhancement is the Core Skill Enhancement level of the Agent (0–6 / Core A–F).
	CoreSkillEnhancement int `json:"core_skill_enhancement"`

	// Attribute is the elemental combat damage type of the Agent (e.g. [AttributeIce], [AttributeEther]).
	Attribute Attribute `json:"attribute"`

	// AttributeName is the localized display name of the Agent's elemental attribute (e.g. "Ice", "Ether").
	AttributeName string `json:"attribute_name"`

	// Specialty is the combat role of the Agent (e.g. [SpecialtyAttack], [SpecialtyStun]).
	Specialty Specialty `json:"specialty"`

	// SpecialtyName is the localized display name of the Agent's combat specialty (e.g. "Attack", "Stun").
	SpecialtyName string `json:"specialty_name"`

	// Rarity is the rarity rank of the Agent ([RarityS] or [RarityA]).
	Rarity Rarity `json:"rarity"`

	// HighlightProps contains the recommended combat property IDs for this Agent
	// displayed on the agent's profile screen (e.g. [PropBaseATK], [PropBaseCritRate], [PropBasePENRatio]).
	// It is always initialized to a non-nil slice (empty [] if no recommendations exist).
	HighlightProps []PropertyID `json:"highlight_props"`

	// RecommendedSubStats contains the recommended Drive Disc sub-stat property IDs for this Agent
	// (e.g. [PropCritRate], [PropCritDMG], [PropATKPercent]).
	// These values reflect the official in-game Drive Disc recommendation system in Zenless Zone Zero
	// (matching the yellow highlight badges displayed on disc sub-stats in the equipment UI).
	// Used for Drive Disc sub-stat highlighting and calculating the in-game Active Modifier Count.
	// It is always initialized to a non-nil slice (empty [] if no recommendations exist).
	RecommendedSubStats []PropertyID `json:"recommended_sub_stats"`

	// Skin is the currently equipped cosmetic outfit. May be nil if default appearance is used.
	Skin *Skin `json:"skin"`

	// SplashArtURL is the absolute HTTPS URL pointing to the Agent's full splash art on the EnkaNetwork CDN.
	SplashArtURL string `json:"splash_art_url"`

	// Skills is the flat list of all individual combat abilities and passives.
	Skills []Skill `json:"skills"`

	// SkillGroups contains the Agent's skills categorized into 6 UI groups matching in-game skill tabs.
	SkillGroups []SkillGroup `json:"grouped_skills"`

	// Mindscapes contains all 6 [MindscapeNode] levels (Cinema 1–6) with their unlocked status.
	Mindscapes []MindscapeNode `json:"mindscapes"`

	// PotentialVision holds Potential Vision upgrade status and nodes (nil if Agent has no Potential Vision).
	PotentialVision *PotentialVision `json:"potential_vision"`

	// WEngine is the currently equipped W-Engine. May be nil if no weapon is equipped.
	WEngine *WEngine `json:"w_engine"`

	// DriveDiscs holds the equipped Drive Discs (slots 1–6) and active set bonuses.
	DriveDiscs DriveDiscs `json:"drive_discs"`

	// BaseStats contains the Agent's innate combat stats (Agent level growth + W-Engine Base ATK).
	BaseStats Stats `json:"base_stats"`

	// Stats contains the Agent's final calculated combat stats after applying all gear and buffs.
	Stats Stats `json:"stats"`

	// UIStats contains pre-formatted combat stat breakdowns (Base + Added = Total) with localized names and icons ready for frontend rendering.
	UIStats UIStats `json:"ui_stats"`
}

Agent represents an enriched Agent showcased on a player's Profile. A profile can showcase up to 6 agents. It aggregates combat metadata, equipped gear (WEngine, DriveDisc entries), active set bonuses, and final combat Stats.

func EnrichAgent added in v1.3.0

func EnrichAgent(raw *zzz.AvatarData) (*Agent, error)

EnrichAgent transforms a raw upstream zzz.AvatarData into an enriched Agent using the default Language (English).

This function operates completely in-memory using the embedded metadata store and makes ZERO network requests. It resolves all agent metadata, progression data, equipped gear (WEngine, DriveDisc entries), active set bonuses, computes scaled combat stats, and formats UI stats. Returns ErrEnrichment if the raw avatar payload is nil or refers to an unknown avatar ID.

Example

ExampleEnrichAgent demonstrates enriching a standalone raw zzz.AvatarData payload directly into an enriched fairy.Agent model using fairy.EnrichAgent and fairy.EnrichAgentWithLang without needing a full profile.

package main

import (
	"fmt"
	"log"

	"github.com/kirinyoku/enkanetwork-go/client/zzz"
	"github.com/kirinyoku/fairy"
)

func main() {
	rawAvatar := &zzz.AvatarData{
		ID:                   1011, // Anby Demara
		Level:                60,
		PromotionLevel:       5,
		TalentLevel:          6,
		CoreSkillEnhancement: 6,
	}

	// 1. Enrich into default language (English)
	agentEN, err := fairy.EnrichAgent(rawAvatar)
	if err != nil {
		log.Fatalf("EnrichAgent failed: %v", err)
	}
	fmt.Printf("%s [%s / %s]\n", agentEN.Name, agentEN.AttributeName, agentEN.SpecialtyName)

	// 2. Enrich into Japanese localization
	agentJA, err := fairy.EnrichAgentWithLang(rawAvatar, fairy.LangJA)
	if err != nil {
		log.Fatalf("EnrichAgentWithLang (JA) failed: %v", err)
	}
	fmt.Printf("%s [%s / %s]\n", agentJA.Name, agentJA.AttributeName, agentJA.SpecialtyName)
}

func EnrichAgentWithLang added in v1.3.0

func EnrichAgentWithLang(raw *zzz.AvatarData, lang Language) (*Agent, error)

EnrichAgentWithLang transforms a raw upstream zzz.AvatarData into an enriched Agent in the requested Language.

This function operates completely in-memory using the embedded metadata store and makes ZERO network requests. It is ideal for multi-language applications that fetch player data once and render individual agents dynamically across different languages. Returns ErrEnrichment if the raw avatar payload is nil or refers to an unknown avatar ID.

func (*Agent) CountEffectiveRolls

func (a *Agent) CountEffectiveRolls(customProps ...PropertyID) int

CountEffectiveRolls returns the total number of useful substat upgrade rolls across all equipped Drive Discs (matching the in-game "Active Modifier Count"). If customProps are provided, it evaluates against them via DriveDiscs.CountEffectiveRolls. If no arguments are passed, it evaluates against this Agent's recommended disc sub-stats (Agent.RecommendedSubStats) or falls back to Agent.HighlightProps if no disc sub-stats are configured.

func (*Agent) IsHighlightProp added in v1.4.0

func (a *Agent) IsHighlightProp(prop PropertyID) bool

IsHighlightProp reports whether the given property matches one of the recommended combat stats for this Agent's profile screen (Base Stats).

func (*Agent) IsRecommendedSubStat added in v1.4.0

func (a *Agent) IsRecommendedSubStat(prop PropertyID) bool

IsRecommendedSubStat reports whether the given Drive Disc sub-stat property is recommended for this Agent, corresponding to the yellow highlight indicator displayed on Drive Disc sub-stats in the in-game equipment UI. It matches percentage modifiers (ATK%, HP%, DEF%) and flat properties according to the Agent's specific sub-stat recommendations.

type Attribute

type Attribute string

Attribute represents the elemental combat attribute (damage type) of an Agent.

const (
	// AttributePhysical represents the Physical damage attribute.
	AttributePhysical Attribute = "Physical"
	// AttributeHonedEdge represents the Honed Edge attribute (Physical variant).
	AttributeHonedEdge Attribute = "HonedEdge"
	// AttributeFire represents the Fire damage attribute.
	AttributeFire Attribute = "Fire"
	// AttributeIce represents the Ice damage attribute.
	AttributeIce Attribute = "Ice"
	// AttributeFrost represents the Frost attribute (Ice variant).
	AttributeFrost Attribute = "Frost"
	// AttributeElectric represents the Electric damage attribute.
	AttributeElectric Attribute = "Electric"
	// AttributeEther represents the Ether damage attribute.
	AttributeEther Attribute = "Ether"
	// AttributeAuricInk represents the Auric Ink attribute (Ether variant).
	AttributeAuricInk Attribute = "AuricInk"
	// AttributeWind represents the Wind damage attribute.
	AttributeWind Attribute = "Wind"
	// AttributeLumiflux represents the Lumiflux damage attribute.
	AttributeLumiflux Attribute = "Lumiflux"
)

Supported elemental combat attributes in Zenless Zone Zero.

func AllAttributes added in v0.10.0

func AllAttributes() []Attribute

AllAttributes returns a newly allocated slice containing all 10 supported Attribute constants. The returned slice is a defensive copy and can be safely mutated by the caller.

func (Attribute) BaseAttribute added in v0.6.0

func (a Attribute) BaseAttribute() Attribute

BaseAttribute returns the core elemental attribute that this attribute deals damage as. For example, AttributeAuricInk deals Ether DMG, AttributeHonedEdge deals Physical DMG, and AttributeFrost deals Ice DMG.

func (Attribute) IconURL added in v0.5.0

func (a Attribute) IconURL() string

IconURL returns a base64-encoded Data URI string ("data:image/svg+xml;base64,...") containing the attribute's SVG icon for direct use in web frontend <img> tags.

func (Attribute) IsValid added in v0.10.0

func (a Attribute) IsValid() bool

IsValid reports whether the attribute is one of the recognized Attribute constants.

func (Attribute) SVG added in v0.5.0

func (a Attribute) SVG() string

SVG returns the raw inline SVG markup string for the attribute icon.

type Avatar

type Avatar struct {
	// ID is the internal numeric identifier of the avatar asset.
	ID int `json:"id"`

	// URL is the absolute HTTPS URL pointing to the avatar's image asset on the EnkaNetwork CDN.
	URL string `json:"url"`
}

Avatar represents a player's equipped profile avatar (profile picture).

type Badge

type Badge struct {
	// ID is the internal numeric identifier of the badge icon.
	ID int `json:"id"`

	// Title is the localized title/name of the badge achievement.
	Title string `json:"title"`

	// Value is the progression value or score associated with the badge.
	Value int `json:"value"`

	// IconURL is the absolute HTTPS URL pointing to the badge's visual icon on the EnkaNetwork CDN.
	IconURL string `json:"icon_url"`
}

Badge represents a collectible achievement medal displayed in a player's profile showcase.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client coordinates fetching player profile data from the EnkaNetwork API and enriching it with localized names, CDN asset URLs, and combat stat calculations using an embedded metadata store.

A Client is safe for concurrent use by multiple goroutines.

func NewClient

func NewClient(opts ...Option) (*Client, error)

NewClient creates a new configured Client instance.

If WithDefaultLang is omitted, the client defaults to English (LangEN). Returns an error if the embedded game metadata store fails to load its internal data files.

Example:

client, err := fairy.NewClient(
	fairy.WithDefaultLang(fairy.LangJA),
	fairy.WithEnkaOptions(zzz.Options{
		UserAgent:  "MyZZZApp/1.0 (contact@example.com)",
		HTTPClient: &http.Client{Timeout: 10 * time.Second},
	}),
)
Example

ExampleNewClient demonstrates configuring a custom Client for production backend services with a custom User-Agent, HTTP client timeout, retry policy, caching layer, and default language.

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/kirinyoku/enkanetwork-go/client/zzz"
	"github.com/kirinyoku/fairy"
)

func main() {
	// Optional: initialize a custom persistent or in-memory cache instance
	// redisCache := NewRedisCache(rdb)

	client, err := fairy.NewClient(
		fairy.WithDefaultLang(fairy.LangJA),
		fairy.WithEnkaOptions(zzz.Options{
			UserAgent: "MyZZZApp/v1.0.0 (contact@example.com)",
			HTTPClient: &http.Client{
				Timeout: 10 * time.Second,
			},
			Retry: &zzz.RetryOptions{
				MaxAttempts: 3,
				Delay:       1 * time.Second,
			},
			// Cache: redisCache, // Plug in your cache implementation
		}),
	)
	if err != nil {
		log.Fatalf("Failed to initialize fairy client: %v\n", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	profile, err := client.GetProfile(ctx, "1504687050")
	if err != nil {
		log.Printf("Profile request failed: %v\n", err)
		return
	}

	fmt.Printf("Player: %s\n", profile.Nickname)
	for _, agent := range profile.Agents {
		fmt.Printf("  • %s Lv.%-2d [%s / %s]\n",
			agent.Name, agent.Level, agent.AttributeName, agent.SpecialtyName)
	}
}

func (*Client) AgentHighlightProps added in v1.4.0

func (c *Client) AgentHighlightProps(agentID int) []PropertyID

AgentHighlightProps returns the recommended combat property IDs (PropertyID) for an Agent by their numeric ID, or nil if the agent is not found. The returned slice is a defensive copy and can be safely mutated by the caller.

func (*Client) AgentRecommendedSubStats added in v1.4.0

func (c *Client) AgentRecommendedSubStats(agentID int) []PropertyID

AgentRecommendedSubStats returns the recommended Drive Disc sub-stat property IDs (PropertyID) for an Agent by numeric ID. These values correspond directly to the official in-game Drive Disc recommendation system (yellow highlights in equipment UI).

func (*Client) AllAgentHighlightProps added in v1.4.0

func (c *Client) AllAgentHighlightProps() map[int][]PropertyID

AllAgentHighlightProps returns a map of all agents' recommended combat property IDs indexed by agent ID. This is useful for code generation, static tooling, or caching build recommendation tables.

func (*Client) AllAgentRecommendedSubStats added in v1.4.0

func (c *Client) AllAgentRecommendedSubStats() map[int][]PropertyID

AllAgentRecommendedSubStats returns a map of all known agents to their recommended Drive Disc sub-stats, matching the in-game equipment UI sub-stat highlights.

func (*Client) Enrich added in v1.0.0

func (c *Client) Enrich(raw *zzz.Profile) (*Profile, error)

Enrich transforms a raw upstream zzz.Profile into an enriched Profile using the client's configured default Language.

This method operates entirely in-memory using the client's metadata store and performs ZERO network calls. It resolves all progression data, computes scaled combat stats, parses Unity Rich Text into HTML, and assembles the full domain model. Returns ErrEnrichment if the raw profile payload is nil or corrupt.

func (*Client) EnrichAgent added in v1.3.0

func (c *Client) EnrichAgent(raw *zzz.AvatarData) (*Agent, error)

EnrichAgent transforms a raw upstream zzz.AvatarData into an enriched Agent using the client's configured default Language.

This method operates entirely in-memory using the client's metadata store and performs ZERO network calls. It resolves all agent metadata, progression data, equipped gear (WEngine, DriveDisc entries), active set bonuses, computes scaled combat stats, and formats UI stats. Returns ErrEnrichment if the raw avatar payload is nil or refers to an unknown avatar ID.

func (*Client) EnrichAgentWithLang added in v1.3.0

func (c *Client) EnrichAgentWithLang(raw *zzz.AvatarData, lang Language) (*Agent, error)

EnrichAgentWithLang transforms a raw upstream zzz.AvatarData into an enriched Agent using the specified Language localization.

This method operates entirely in-memory using the client's metadata store and performs ZERO network calls. It is ideal for multi-language applications that fetch player data once and render individual agents dynamically across different languages. Returns ErrEnrichment if the raw avatar payload is nil or refers to an unknown avatar ID.

func (*Client) EnrichWithLang added in v1.0.0

func (c *Client) EnrichWithLang(raw *zzz.Profile, lang Language) (*Profile, error)

EnrichWithLang transforms a raw upstream zzz.Profile into an enriched Profile using the specified Language localization.

This method operates entirely in-memory using the client's metadata store and performs ZERO network calls. It is ideal for multi-language applications that fetch a player's raw profile once via Client.GetRawProfile and render it dynamically across different languages. Returns ErrEnrichment if the raw profile payload is nil or corrupt.

func (*Client) GetProfile

func (c *Client) GetProfile(ctx context.Context, uid string) (*Profile, error)

GetProfile fetches a player profile by UID from the EnkaNetwork API and enriches it using the client's configured default Language.

The returned Profile contains:

  • Player account details (UID, Nickname, Inter-Knot Level, Region, Title, Avatar, Badges).
  • Showcase Agent list (up to 6 agents), where each agent contains:
  • Metadata (localized name, Attribute, Specialty, Rarity, Skin, CDN asset URLs).
  • Progression (categorized SkillGroup entries, MindscapeNode unlock states, PotentialVision).
  • Equipped WEngine (with level-scaled stats and refinement modification effects).
  • Equipped DriveDisc entries (slots 1–6 with roll counts) and active DriveDiscSetBonus thresholds.
  • Pre-calculated combat Stats and frontend-ready UIStats breakdowns.

The provided context.Context controls the HTTP request lifecycle, cancellation, and timeout. Returns sentinel errors such as ErrInvalidUID, ErrProfileNotFound, ErrRateLimit, ErrMaintenance, ErrNetwork, or ErrEnrichment.

func (*Client) GetProfileWithLang

func (c *Client) GetProfileWithLang(ctx context.Context, uid string, lang Language) (*Profile, error)

GetProfileWithLang fetches a player profile by UID from the EnkaNetwork API and enriches it using the specified Language localization.

This method overrides the client's default language for the single request without modifying the client instance, making it safe for concurrent multi-language usage.

The provided context.Context controls the HTTP request lifecycle, cancellation, and timeout. Returns sentinel errors such as ErrInvalidUID, ErrProfileNotFound, ErrRateLimit, ErrMaintenance, ErrNetwork, or ErrEnrichment.

func (*Client) GetRawProfile

func (c *Client) GetRawProfile(ctx context.Context, uid string) (*zzz.Profile, error)

GetRawProfile fetches the raw, un-enriched zzz.Profile directly from the EnkaNetwork API.

Use this method if you only need the raw numeric IDs provided by the upstream API, or when you want to fetch the payload once and enrich it into multiple languages via Client.EnrichWithLang.

The provided context.Context controls the HTTP request lifecycle, cancellation, and timeout. Returns sentinel errors such as ErrInvalidUID, ErrProfileNotFound, ErrRateLimit, ErrMaintenance, or ErrNetwork.

type DriveDisc

type DriveDisc struct {
	// ID is the internal numeric identifier of the specific disc variation.
	ID int `json:"id"`

	// UID is the unique instance identifier of this specific Drive Disc piece.
	UID string `json:"uid"`

	// Set is the Drive Disc [Set] metadata this disc belongs to.
	Set Set `json:"set"`

	// Slot is the equip partition slot position (1 to 6).
	Slot int `json:"slot"`

	// Level is the current upgrade level of the Drive Disc (0–15).
	Level int `json:"level"`

	// Rarity is the rarity rank of the disc ([RarityS], [RarityA], or [RarityB]).
	Rarity Rarity `json:"rarity"`

	// IconPath is the absolute HTTPS URL pointing to the disc's partition icon on the EnkaNetwork CDN.
	IconPath string `json:"icon_path"`

	// MainStat is the primary stat provided by this disc, scaled by disc level.
	MainStat StatValue `json:"main_stat"`

	// SubStats is the list of randomly rolled sub-stats (up to 4), including upgrade roll counts.
	SubStats []StatValue `json:"sub_stats"`
}

DriveDisc represents an equipped Drive Disc on an Agent.

An Agent can equip up to 6 Drive Discs across partition slots 1 through 6:

  • Slots 1–3 have fixed main stats (Slot 1: Flat HP, Slot 2: Flat ATK, Slot 3: Flat DEF).
  • Slots 4–6 have randomized main stats (e.g. CRIT Rate, CRIT DMG, Attribute DMG Bonus, Energy Regen, Anomaly Mastery).

func (*DriveDisc) CountEffectiveRolls

func (d *DriveDisc) CountEffectiveRolls(targetProps ...PropertyID) int

CountEffectiveRolls returns the total number of sub-stat upgrade rolls on this specific DriveDisc that match any of the provided target property IDs.

Example:

// Count useful rolls for an Attack Agent on a single disc:
rolls := disc.CountEffectiveRolls(fairy.PropCritRate, fairy.PropCritDMG, fairy.PropATKPercent)

type DriveDiscSetBonus

type DriveDiscSetBonus struct {
	// Set is the Drive Disc [Set] metadata (ID and localized name).
	Set Set `json:"set"`

	// Count is the total number of pieces from this set currently equipped on the Agent (e.g. 2, 4, 5).
	Count int `json:"count"`

	// Effects contains the 2-piece and 4-piece [SetEffect] thresholds with their activation status.
	Effects []SetEffect `json:"effects"`
}

DriveDiscSetBonus represents an aggregated Drive Disc set equipped on an Agent, detailing the equipped piece count and active/inactive set threshold bonuses.

type DriveDiscs added in v1.0.0

type DriveDiscs struct {
	// Slots is the list of equipped [DriveDisc] pieces (up to 6 discs, partition slots 1–6).
	Slots []DriveDisc `json:"slots"`
	// SetBonuses is the list of active 2-piece and 4-piece Drive Disc set bonuses.
	SetBonuses []DriveDiscSetBonus `json:"set_bonuses"`
}

DriveDiscs represents the complete Drive Disc equipment layout on an Agent, containing the equipped discs in partition slots 1–6 and active 2-piece and 4-piece set bonuses.

func (DriveDiscs) BySlot added in v1.0.0

func (d DriveDiscs) BySlot(slot int) *DriveDisc

BySlot returns a pointer to the DriveDisc equipped in the specified partition slot (1–6), or nil if no disc is equipped in that slot.

func (DriveDiscs) CountEffectiveRolls added in v1.0.0

func (d DriveDiscs) CountEffectiveRolls(targetProps ...PropertyID) int

CountEffectiveRolls returns the total number of sub-stat upgrade rolls across all DriveDisc entries in the collection that match any of the provided target property IDs (also known as "effective" or "useful" rolls for build evaluation).

Example:

// Evaluate build quality on an Attack Agent across all 6 equipped discs:
rolls := agent.DriveDiscs.CountEffectiveRolls(fairy.PropCritRate, fairy.PropCritDMG, fairy.PropATKPercent)
fmt.Printf("Effective rolls: %d\n", rolls)

func (DriveDiscs) Has2Piece added in v1.0.0

func (d DriveDiscs) Has2Piece(setID SetID) bool

Has2Piece reports whether at least 2 pieces of the specified SetID are equipped.

Example:

if agent.DriveDiscs.Has2Piece(fairy.SetSwingJazz) {
	fmt.Println("Swing Jazz 2-pc is active (+20% Energy Regen)")
}

func (DriveDiscs) Has4Piece added in v1.0.0

func (d DriveDiscs) Has4Piece(setID SetID) bool

Has4Piece reports whether at least 4 pieces of the specified SetID are equipped.

Example:

if agent.DriveDiscs.Has4Piece(fairy.SetWoodpeckerElectro) {
	fmt.Println("Woodpecker Electro 4-pc is active")
}

func (DriveDiscs) SetCounts added in v1.0.0

func (d DriveDiscs) SetCounts() map[Set]int

SetCounts groups equipped discs by their Set and returns the count of pieces equipped for each set.

func (DriveDiscs) SubStatTotals added in v1.0.0

func (d DriveDiscs) SubStatTotals() []StatValue

SubStatTotals aggregates and sums sub-stat values and roll counts across all discs in the collection. It groups them by PropertyID and preserves the deterministic appearance order of the sub-stats.

Example:

totals := agent.DriveDiscs.SubStatTotals()
for _, stat := range totals {
	fmt.Printf("%-20s +%-6s (%d rolls)\n", stat.Name, stat.DisplayValue(), stat.Rolls)
}
Example

ExampleDriveDiscs_SubStatTotals demonstrates comprehensive gear and build quality analysis: detecting active 2-pc / 4-pc set bonuses, aggregating substats, and scoring priority rolls.

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/kirinyoku/fairy"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	profile, err := fairy.GetProfile(ctx, "1504687050")
	if err != nil || len(profile.Agents) == 0 {
		return
	}

	agent := profile.Agents[0]
	fmt.Printf("=== Drive Disc Analysis: %s ===\n", agent.Name)

	// 1. Detect active Drive Disc Set Bonuses (2-piece and 4-piece thresholds)
	fmt.Println("Active Set Bonuses:")
	for _, bonus := range agent.DriveDiscs.SetBonuses {
		fmt.Printf("  • %s (%d pieces equipped)\n", bonus.Set.Name, bonus.Count)
		for _, effect := range bonus.Effects {
			if effect.IsActive {
				fmt.Printf("    [%d-Piece Active]: %s\n", effect.PieceCount, effect.FormatPlainText())
			}
		}
	}

	// 2. Aggregate substat totals and upgrade roll counts across all 6 equipped discs
	fmt.Println("\nSubstat Totals Across All 6 Discs:")
	for _, stat := range agent.DriveDiscs.SubStatTotals() {
		fmt.Printf("  • %-22s +%-8s (%d rolls)\n",
			stat.Name, stat.DisplayValue(), stat.Rolls)
	}

	// 3. Count effective upgrade rolls automatically evaluated against the agent's recommended stats (RecommendedSubStats)
	usefulRolls := agent.CountEffectiveRolls()
	fmt.Printf("\nBuild Rating: %d effective substat rolls on recommended stats\n", usefulRolls)

	// Alternatively, evaluate against custom priority stats (e.g. only CRIT stats):
	critRolls := agent.CountEffectiveRolls(fairy.PropCritRate, fairy.PropCritDMG)
	fmt.Printf("CRIT Roll Rating: %d rolls on CRIT Rate / CRIT DMG\n", critRolls)
}

type FormattedStatBreakdown

type FormattedStatBreakdown struct {
	// PropertyID is the strongly-typed [PropertyID] of the stat.
	PropertyID PropertyID `json:"property_id"`

	// Name is the localized display name of the stat.
	Name string `json:"name"`

	// Base is the pre-formatted innate base stat value.
	Base string `json:"base"`

	// Added is the pre-formatted added stat value from W-Engines, Drive Discs, and set bonuses.
	Added string `json:"added"`

	// Total is the pre-formatted final combat stat value.
	Total string `json:"total"`

	// IconURL is the base64 Data URI string containing the stat's SVG icon.
	IconURL string `json:"icon_url"`
}

FormattedStatBreakdown represents a single combat stat broken down into its base and added components, pre-formatted as human-readable strings ready for UI display.

type FormattedStats

type FormattedStats struct {
	// HP is the formatted Health Points string.
	HP string `json:"hp"`

	// ATK is the formatted Attack string.
	ATK string `json:"atk"`

	// DEF is the formatted Defense string.
	DEF string `json:"def"`

	// Impact is the formatted Impact string.
	Impact string `json:"impact"`

	// CritRate is the formatted Critical Rate percentage string (e.g. "50.0%").
	CritRate string `json:"crit_rate"`

	// CritDMG is the formatted Critical Damage percentage string (e.g. "150.0%").
	CritDMG string `json:"crit_dmg"`

	// AttributeDMGBonus is the formatted Attribute Damage Bonus percentage string (e.g. "30.0%").
	AttributeDMGBonus string `json:"attribute_dmg_bonus"`

	// AnomalyMastery is the formatted Anomaly Mastery string.
	AnomalyMastery string `json:"anomaly_mastery"`

	// AnomalyProficiency is the formatted Anomaly Proficiency string.
	AnomalyProficiency string `json:"anomaly_proficiency"`

	// PenRatio is the formatted Penetration Ratio percentage string (e.g. "24.0%").
	PenRatio string `json:"pen_ratio"`

	// PenFlat is the formatted Flat Penetration string.
	PenFlat string `json:"pen_flat"`

	// EnergyRegen is the formatted Energy Regeneration string (e.g. "1.20").
	EnergyRegen string `json:"energy_regen"`

	// SheerForce is the formatted Sheer Force string.
	SheerForce string `json:"sheer_force"`

	// SharpCritDMG is the formatted Laceration DMG string.
	SharpCritDMG string `json:"sharp_crit_dmg"`
}

FormattedStats contains the agent's combat stats pre-formatted as human-readable strings. This is convenient for frontend rendering where formatted values (e.g. "50.0%", "3,120") are required directly.

type Language

type Language string

Language represents a supported localization language for in-game text. It determines the translation strings retrieved from the embedded metadata store for Agent names, W-Engine titles, Drive Disc sets, Skill descriptions, Mindscape Cinema nodes, and combat stat labels.

const (
	// LangEN represents English localization ("en").
	LangEN Language = "en"
	// LangRU represents Russian localization ("ru").
	LangRU Language = "ru"
	// LangDE represents German localization ("de").
	LangDE Language = "de"
	// LangES represents Spanish localization ("es").
	LangES Language = "es"
	// LangFR represents French localization ("fr").
	LangFR Language = "fr"
	// LangID represents Indonesian localization ("id").
	LangID Language = "id"
	// LangJA represents Japanese localization ("ja").
	LangJA Language = "ja"
	// LangKO represents Korean localization ("ko").
	LangKO Language = "ko"
	// LangPT represents Portuguese localization ("pt").
	LangPT Language = "pt"
	// LangTH represents Thai localization ("th").
	LangTH Language = "th"
	// LangVI represents Vietnamese localization ("vi").
	LangVI Language = "vi"
	// LangZHCN represents Simplified Chinese localization ("zh-cn").
	LangZHCN Language = "zh-cn"
	// LangZHTW represents Traditional Chinese localization ("zh-tw").
	LangZHTW Language = "zh-tw"
)

Supported in-game localization languages matching the official Zenless Zone Zero game clients.

func AllLanguages added in v0.10.0

func AllLanguages() []Language

AllLanguages returns a newly allocated slice containing all 13 supported Language localizations. The returned slice is a defensive copy and can be safely mutated by the caller.

func (Language) IsValid added in v0.10.0

func (l Language) IsValid() bool

IsValid reports whether the language is one of the 13 officially supported Language constants.

type MindscapeNode added in v0.7.0

type MindscapeNode struct {
	// Rank is the Mindscape Cinema level (1 to 6).
	Rank int `json:"rank"`

	// Name is the localized name of the Mindscape Cinema node.
	Name string `json:"name"`

	// Description is the localized description text of the Mindscape Cinema node effect.
	Description string `json:"description"`

	// FormattedHTML is the web-ready HTML description with inline CSS colors.
	FormattedHTML string `json:"formatted_html,omitempty"`

	// Unlocked indicates whether this Mindscape Cinema node is unlocked on the Agent (MindscapeCinema >= Rank).
	Unlocked bool `json:"unlocked"`
}

MindscapeNode represents a single Mindscape Cinema level (M1–M6) for an Agent.

func (MindscapeNode) FormatHTML added in v0.7.0

func (m MindscapeNode) FormatHTML() string

FormatHTML returns the Mindscape Cinema node description formatted as HTML with inline CSS styling.

func (MindscapeNode) FormatMarkdown added in v0.7.0

func (m MindscapeNode) FormatMarkdown() string

FormatMarkdown returns the Mindscape Cinema node description formatted with Markdown syntax (bold highlights).

func (MindscapeNode) FormatPlainText added in v0.7.0

func (m MindscapeNode) FormatPlainText() string

FormatPlainText returns the Mindscape Cinema node description stripped of Unity Rich Text formatting.

type Namecard

type Namecard struct {
	// ID is the internal numeric identifier of the namecard asset.
	ID int `json:"id"`

	// URL is the absolute HTTPS URL pointing to the namecard's background asset on the EnkaNetwork CDN.
	URL string `json:"url"`
}

Namecard represents a player's equipped background calling card image.

type Option

type Option func(*Options)

Option defines a functional option for configuring a Client in NewClient.

func WithDefaultLang

func WithDefaultLang(lang Language) Option

WithDefaultLang sets the default localization Language for the Client. If not specified, the client defaults to English (LangEN).

func WithEnkaOptions

func WithEnkaOptions(enkaOpts zzz.Options) Option

WithEnkaOptions configures the underlying enkanetwork-go client settings, including custom [http.Client] timeouts, User-Agent strings, retry policies (zzz.RetryOptions), and persistent caching implementations (zzz.Cache).

type Options

type Options struct {
	// DefaultLang specifies the default localization language used for profile enrichment.
	// Defaults to [LangEN] if not specified.
	DefaultLang Language

	// EnkaOpts specifies configuration settings for the underlying EnkaNetwork HTTP client,
	// such as custom HTTP transport, User-Agent, retry policies, and cache implementations.
	EnkaOpts zzz.Options
}

Options holds configuration settings for initializing a Client.

type PotentialVision added in v0.7.0

type PotentialVision struct {
	// IsUnlocked indicates whether the Potential Vision mechanic is unlocked.
	IsUnlocked bool `json:"is_unlocked"`

	// CurrentID is the currently active upgrade node ID.
	CurrentID int `json:"current_id"`

	// Nodes contains all Potential Vision upgrade nodes for the Agent.
	Nodes []PotentialVisionNode `json:"nodes"`
}

PotentialVision holds Potential Vision upgrade mechanics and nodes for an Agent.

type PotentialVisionNode added in v0.7.0

type PotentialVisionNode struct {
	// ID is the internal numeric identifier of the upgrade node.
	ID int `json:"id"`

	// Level is the level threshold of the node (1 to 6).
	Level int `json:"level"`

	// LevelName is the localized level title.
	LevelName string `json:"level_name"`

	// Title is the localized title of the upgrade effect.
	Title string `json:"title"`

	// Description is the localized effect description.
	Description string `json:"description"`

	// FormattedHTML is the web-ready HTML description with inline CSS colors.
	FormattedHTML string `json:"formatted_html,omitempty"`

	// IsActive indicates whether this upgrade node is currently active on the Agent.
	IsActive bool `json:"is_active"`
}

PotentialVisionNode represents a single Potential Vision upgrade node.

func (PotentialVisionNode) FormatHTML added in v0.7.0

func (p PotentialVisionNode) FormatHTML() string

FormatHTML returns the PotentialVisionNode description formatted as HTML with inline CSS styling.

func (PotentialVisionNode) FormatMarkdown added in v0.7.0

func (p PotentialVisionNode) FormatMarkdown() string

FormatMarkdown returns the PotentialVisionNode description formatted with Markdown syntax.

func (PotentialVisionNode) FormatPlainText added in v0.7.0

func (p PotentialVisionNode) FormatPlainText() string

FormatPlainText returns the PotentialVisionNode description stripped of Unity Rich Text formatting.

type Profile

type Profile struct {
	// UID is the unique in-game identifier of the player (typically a 10-digit string).
	UID string `json:"uid"`

	// TTL indicates the remaining cache lifetime in seconds returned by the upstream EnkaNetwork API.
	// Making repeated requests before this TTL expires consumes rate limit quota without yielding newer game data.
	TTL int `json:"ttl"`

	// Nickname is the display name chosen by the player. Can be empty if omitted by upstream API.
	Nickname string `json:"nickname"`

	// InterknotLevel is the player's overall account progression level (Inter-Knot Level).
	InterknotLevel int `json:"interknot_level"`

	// Region is the game server region hosting the player's account.
	Region Region `json:"region"`

	// Title is the active achievement title equipped on the profile. May be nil if no title is equipped.
	Title *Title `json:"title"`

	// Avatar is the active profile picture equipped by the player. May be nil if none is set.
	Avatar *Avatar `json:"avatar"`

	// Namecard is the active profile background image (calling card). May be nil if none is set.
	Namecard *Namecard `json:"namecard"`

	// Badges is the list of collectible showcase medals displayed on the profile. May be empty.
	Badges []Badge `json:"badges"`

	// Agents is the list of up to 6 showcased [Agent] entries configured by the player in-game.
	// May be empty if the player's in-game showcase is empty or has details hidden.
	Agents []Agent `json:"agents"`
}

Profile represents an enriched Zenless Zone Zero player profile. It aggregates account-level metadata and the player's showcased Agent lineup.

Example

ExampleProfile demonstrates extracting and rendering player showcase customization data, such as avatar icons, namecard backgrounds, achievement badges, and two-color gradient titles.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/kirinyoku/fairy"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	profile, err := fairy.GetProfile(ctx, "1504687050")
	if err != nil {
		log.Printf("Failed to fetch profile: %v\n", err)
		return
	}

	fmt.Printf("=== Player Showcase: %s (UID: %s) ===\n", profile.Nickname, profile.UID)
	fmt.Printf("Inter-Knot Level: %d | Server: %s\n", profile.InterknotLevel, profile.Region)

	if profile.Avatar != nil && profile.Avatar.URL != "" {
		fmt.Printf("Avatar URL: %s\n", profile.Avatar.URL)
	}

	if profile.Namecard != nil && profile.Namecard.URL != "" {
		fmt.Printf("Namecard URL: %s\n", profile.Namecard.URL)
	}

	if profile.Title != nil {
		// Generate an HTML gradient style using the Title's primary and secondary hex colors
		gradientCSS := fmt.Sprintf("background: linear-gradient(90deg, %s, %s); -webkit-background-clip: text;",
			profile.Title.PrimaryColorHex(), profile.Title.SecondaryColorHex())
		fmt.Printf("Title: <span style=\"%s\">%s</span>\n", gradientCSS, profile.Title.Text)
	}

	if len(profile.Badges) > 0 {
		fmt.Println("Showcased Badges:")
		for _, badge := range profile.Badges {
			fmt.Printf("  • %-24s Value: %-5d (Icon: %s)\n", badge.Title, badge.Value, badge.IconURL)
		}
	}
}

func Enrich added in v1.0.0

func Enrich(raw *zzz.Profile) (*Profile, error)

Enrich transforms a raw upstream zzz.Profile into an enriched Profile using the default Language (English).

This function operates completely in-memory using the embedded metadata store and makes ZERO network requests. It resolves all progression data, computes scaled combat stats, parses Unity Rich Text into HTML, and assembles the full domain model. Returns ErrEnrichment if the raw profile payload is nil or corrupt.

Example

ExampleEnrich demonstrates fetching raw API data once with GetRawProfile, caching it, and enriching it into multiple languages in memory using Enrich and EnrichWithLang with zero additional network requests.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/kirinyoku/fairy"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 1. Fetch the raw upstream profile once over HTTP
	rawProfile, err := fairy.GetRawProfile(ctx, "1504687050")
	if err != nil {
		log.Printf("Failed to fetch raw profile: %v", err)
		return
	}

	// 2. Enrich in memory with zero extra network overhead
	// Default English:
	enProfile, err := fairy.Enrich(rawProfile)
	if err != nil {
		log.Printf("English enrichment failed: %v", err)
		return
	}

	// Specific languages on the fly:
	jaProfile, err := fairy.EnrichWithLang(rawProfile, fairy.LangJA)
	if err != nil {
		log.Printf("Japanese enrichment failed: %v", err)
		return
	}

	ruProfile, err := fairy.EnrichWithLang(rawProfile, fairy.LangRU)
	if err != nil {
		log.Printf("Russian enrichment failed: %v", err)
		return
	}

	fmt.Println("English Agent 0:", enProfile.Agents[0].Name, "—", enProfile.Agents[0].SpecialtyName)
	fmt.Println("Japanese Agent 0:", jaProfile.Agents[0].Name, "—", jaProfile.Agents[0].SpecialtyName)
	fmt.Println("Russian Agent 0:", ruProfile.Agents[0].Name, "—", ruProfile.Agents[0].SpecialtyName)
}

func EnrichWithLang added in v1.0.0

func EnrichWithLang(raw *zzz.Profile, lang Language) (*Profile, error)

EnrichWithLang transforms a raw upstream zzz.Profile into an enriched Profile in the requested Language.

This function operates completely in-memory using the embedded metadata store and makes ZERO network requests. It is ideal for multi-language applications that fetch a player's raw profile once via GetRawProfile and render it dynamically across different languages. Returns ErrEnrichment if the raw profile payload is nil or corrupt.

func GetProfile

func GetProfile(ctx context.Context, uid string) (*Profile, error)

GetProfile fetches a player profile by UID via the EnkaNetwork API and enriches it using the shared default client in English (LangEN).

The returned Profile contains:

  • Player account details (UID, Nickname, Inter-Knot Level, Region, Title, Avatar, Badges).
  • Showcase Agent list (up to 6 agents), where each agent contains:
  • Metadata (localized name, Attribute, Specialty, Rarity, Skin, CDN asset URLs).
  • Progression (categorized SkillGroup entries, MindscapeNode unlock states, PotentialVision).
  • Equipped WEngine (with level-scaled stats and refinement modification effects).
  • Equipped DriveDisc entries (slots 1–6 with roll counts) and active DriveDiscSetBonus thresholds.
  • Pre-calculated combat Stats and frontend-ready UIStats breakdowns.

The provided context.Context controls the HTTP request lifecycle, cancellation, and timeout. Returns sentinel errors such as ErrInvalidUID, ErrProfileNotFound, ErrRateLimit, ErrMaintenance, ErrNetwork, or ErrEnrichment.

Example

ExampleGetProfile demonstrates the standard quick-start workflow: fetching a player's showcase profile with a context timeout and handling sentinel errors with errors.Is.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/kirinyoku/fairy"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	const uid = "1504687050"

	profile, err := fairy.GetProfile(ctx, uid)
	if err != nil {
		switch {
		case errors.Is(err, fairy.ErrProfileNotFound):
			log.Printf("Player %s not found on game servers\n", uid)
		case errors.Is(err, fairy.ErrRateLimit):
			log.Printf("EnkaNetwork API rate limit reached, back off required\n")
		case errors.Is(err, fairy.ErrMaintenance):
			log.Printf("EnkaNetwork API or game servers are under maintenance\n")
		case errors.Is(err, fairy.ErrNetwork):
			log.Printf("Network transport or timeout error\n")
		default:
			log.Printf("Unexpected error fetching profile %s: %v\n", uid, err)
		}
		return
	}

	fmt.Printf("Player: %s (Inter-Knot Lv.%d, Server: %s)\n",
		profile.Nickname, profile.InterknotLevel, profile.Region)

	for _, agent := range profile.Agents {
		weapon := "None"
		if agent.WEngine != nil {
			weapon = fmt.Sprintf("%s (Lv.%d, M%d)", agent.WEngine.Name, agent.WEngine.Level, agent.WEngine.Modification)
		}
		fmt.Printf("  • %-16s Lv.%-2d [%s / %s]  W-Engine: %s\n",
			agent.Name, agent.Level, agent.AttributeName, agent.SpecialtyName, weapon)
	}
}

func GetProfileWithLang

func GetProfileWithLang(ctx context.Context, uid string, lang Language) (*Profile, error)

GetProfileWithLang fetches a player profile by UID via the EnkaNetwork API and enriches it using the specified Language localization.

This is identical to GetProfile, but overrides the default language for the single request without modifying the shared default client.

The provided context.Context controls the HTTP request lifecycle, cancellation, and timeout. Returns sentinel errors such as ErrInvalidUID, ErrProfileNotFound, ErrRateLimit, ErrMaintenance, ErrNetwork, or ErrEnrichment.

func (*Profile) CacheTTL added in v1.1.0

func (p *Profile) CacheTTL() time.Duration

CacheTTL returns the remaining cache lifetime as a time.Duration. Returns 0 if the profile is nil or TTL is non-positive.

type PropertyID

type PropertyID int

PropertyID represents a strongly-typed numeric identifier for combat attributes and stats in Zenless Zone Zero.

The naming conventions categorize stats into three distinct layers:

const (
	// PropBaseHP represents the base Health Points stat.
	PropBaseHP PropertyID = 11101
	// PropHPPercent represents a percentage increase to Health Points.
	PropHPPercent PropertyID = 11102
	// PropHPFlat represents a flat increase to Health Points.
	PropHPFlat PropertyID = 11103
	// PropHPPercentBonus represents an additional percentage bonus to Health Points.
	PropHPPercentBonus PropertyID = 11104
	// PropHPFlatBonus represents an additional flat bonus to Health Points.
	PropHPFlatBonus PropertyID = 11105

	// PropBaseATK represents the base Attack stat.
	PropBaseATK PropertyID = 12101
	// PropATKPercent represents a percentage increase to Attack.
	PropATKPercent PropertyID = 12102
	// PropATKFlat represents a flat increase to Attack.
	PropATKFlat PropertyID = 12103

	// PropBaseDEF represents the base Defense stat.
	PropBaseDEF PropertyID = 13101
	// PropDEFPercent represents a percentage increase to Defense.
	PropDEFPercent PropertyID = 13102
	// PropDEFFlat represents a flat increase to Defense.
	PropDEFFlat PropertyID = 13103

	// PropBaseImpact represents the base Impact stat (influences Daze build-up).
	PropBaseImpact PropertyID = 12201
	// PropImpactPercent represents a percentage increase to Impact.
	PropImpactPercent PropertyID = 12202
	// PropImpactFlat represents a flat increase to Impact.
	PropImpactFlat PropertyID = 12203

	// PropBaseCritRate represents the base Critical Rate stat.
	PropBaseCritRate PropertyID = 20101
	// PropCritRate represents an increase to Critical Rate.
	PropCritRate PropertyID = 20103
	// PropBaseCritDMG represents the base Critical Damage stat.
	PropBaseCritDMG PropertyID = 21101
	// PropCritDMG represents an increase to Critical Damage.
	PropCritDMG PropertyID = 21103

	// PropBasePENRatio represents the base Penetration Ratio stat.
	PropBasePENRatio PropertyID = 23101
	// PropPENRatio represents an increase to Penetration Ratio.
	PropPENRatio PropertyID = 23103
	// PropBasePENFlat represents the base flat Penetration stat.
	PropBasePENFlat PropertyID = 23201
	// PropPENFlat represents an increase to flat Penetration.
	PropPENFlat PropertyID = 23203

	// PropBaseEnergyRegen represents the base Energy Regeneration stat.
	PropBaseEnergyRegen PropertyID = 30501
	// PropEnergyRegenPercent represents a percentage increase to Energy Regeneration.
	PropEnergyRegenPercent PropertyID = 30502
	// PropEnergyRegen represents an increase to Energy Regeneration.
	PropEnergyRegen PropertyID = 30503

	// PropBaseAnomalyProficiency represents the base Anomaly Proficiency stat (scales Anomaly damage).
	PropBaseAnomalyProficiency PropertyID = 31201
	// PropAnomalyProficiencyPercent represents a percentage increase to Anomaly Proficiency.
	PropAnomalyProficiencyPercent PropertyID = 31202
	// PropAnomalyProficiency represents an increase to Anomaly Proficiency.
	PropAnomalyProficiency PropertyID = 31203

	// PropBaseAnomalyMastery represents the base Anomaly Mastery stat (scales Anomaly build-up speed).
	PropBaseAnomalyMastery PropertyID = 31401
	// PropAnomalyMasteryPercent represents a percentage increase to Anomaly Mastery.
	PropAnomalyMasteryPercent PropertyID = 31402
	// PropAnomalyMastery represents an increase to Anomaly Mastery.
	PropAnomalyMastery PropertyID = 31403

	// PropBaseSheerForce represents the base Sheer Force stat (for Rupture agents).
	PropBaseSheerForce PropertyID = 12301
	// PropSheerForce represents an increase to Sheer Force.
	PropSheerForce PropertyID = 12303

	// PropBaseRpRecover represents the base Adrenaline Auto-Accumulation stat (for Rupture agents).
	PropBaseRpRecover PropertyID = 32001
	// PropRpRecoverPercent represents a percentage increase to Adrenaline Auto-Accumulation.
	PropRpRecoverPercent PropertyID = 32002
	// PropRpRecover represents an increase to Adrenaline Auto-Accumulation.
	PropRpRecover PropertyID = 32003

	// PropBaseEpRecover represents the base Automatic Sharpness Accumulation stat (for Armorer agents).
	PropBaseEpRecover PropertyID = 32401
	// PropEpRecoverPercent represents a percentage increase to Automatic Sharpness Accumulation.
	PropEpRecoverPercent PropertyID = 32402
	// PropEpRecover represents an increase to Automatic Sharpness Accumulation.
	PropEpRecover PropertyID = 32403

	// PropBaseSharpCritDMG represents the base Laceration DMG stat.
	PropBaseSharpCritDMG PropertyID = 21301
	// PropSharpCritDMG represents an increase to Laceration DMG.
	PropSharpCritDMG PropertyID = 21303

	// PropPhysicalDMGBonus represents the Physical Damage Bonus stat.
	PropPhysicalDMGBonus PropertyID = 31505
	// PropFireDMGBonus represents the Fire Damage Bonus stat.
	PropFireDMGBonus PropertyID = 31605
	// PropIceDMGBonus represents the Ice Damage Bonus stat.
	PropIceDMGBonus PropertyID = 31705
	// PropElectricDMGBonus represents the Electric Damage Bonus stat.
	PropElectricDMGBonus PropertyID = 31805
	// PropEtherDMGBonus represents the Ether Damage Bonus stat.
	PropEtherDMGBonus PropertyID = 31905
	// PropWindDMGBonus represents the Wind Damage Bonus stat.
	PropWindDMGBonus PropertyID = 32305
)

Strongly-typed PropertyID constants for all combat attributes.

func AgentHighlightProps added in v1.4.0

func AgentHighlightProps(agentID int) []PropertyID

AgentHighlightProps returns the recommended combat property IDs (PropertyID) for an Agent by their numeric ID, or nil if the agent is not found or fails to initialize the shared default client. The returned slice is a defensive copy and can be safely mutated by the caller.

Example:

props := fairy.AgentHighlightProps(1011) // Anby Demara
// props -> [PropBaseImpact] (12201)

func AgentRecommendedSubStats added in v1.4.0

func AgentRecommendedSubStats(agentID int) []PropertyID

AgentRecommendedSubStats returns the recommended Drive Disc sub-stat property IDs for the given agent ID, using the shared default client.

These stats reflect the official in-game recommendation system in Zenless Zone Zero, matching the yellow highlight indicators displayed on Drive Disc sub-stats in the equipment and tuning UI for each specific agent.

If a curated list exists in [agentRecommendedSubStats], a defensive copy is returned. Otherwise, it computes a safe fallback from AgentHighlightProps, converting attributes to percentage-only sub-stats and excluding flat ATK, flat HP, flat DEF, and flat PEN.

func (PropertyID) IconURL added in v0.7.0

func (p PropertyID) IconURL() string

IconURL returns a base64-encoded Data URI string ("data:image/svg+xml;base64,...") containing the stat property's SVG icon for direct use in frontend <img> tags.

func (PropertyID) SVG added in v0.7.0

func (p PropertyID) SVG() string

SVG returns the raw inline SVG markup string for the stat property.

type Rarity

type Rarity string

Rarity represents the rarity tier (rank) of an Agent, WEngine, or DriveDisc.

const (
	// RarityS represents the S-Rank tier.
	RarityS Rarity = "S"
	// RarityA represents the A-Rank tier.
	RarityA Rarity = "A"
	// RarityB represents the B-Rank tier (used for W-Engines and Drive Discs).
	RarityB Rarity = "B"
)

Supported rarity ranks in Zenless Zone Zero.

func AllRarities added in v0.10.0

func AllRarities() []Rarity

AllRarities returns a newly allocated slice containing all supported Rarity constants. The returned slice is a defensive copy and can be safely mutated by the caller.

func (Rarity) IconURL added in v0.5.0

func (r Rarity) IconURL() string

IconURL returns the official EnkaNetwork CDN icon URL for the rarity tier.

func (Rarity) IsValid added in v0.10.0

func (r Rarity) IsValid() bool

IsValid reports whether the rarity is one of the recognized Rarity constants.

type Region

type Region string

Region represents the game server region hosting a player's account.

const (
	// RegionEU represents the European game server region ("Europe").
	RegionEU Region = "Europe"
	// RegionNA represents the North American game server region ("America").
	RegionNA Region = "America"
	// RegionAsia represents the Asian game server region ("Asia").
	RegionAsia Region = "Asia"
	// RegionTWHKMO represents the Taiwan / Hong Kong / Macau game server region ("TW/HK/MO").
	RegionTWHKMO Region = "TW/HK/MO"
)

Supported server region constants.

func AllRegions added in v0.10.0

func AllRegions() []Region

AllRegions returns a newly allocated slice containing all supported Region server constants. The returned slice is a defensive copy and can be safely mutated by the caller.

func RegionFromUID added in v1.1.0

func RegionFromUID(uid string) (Region, bool)

RegionFromUID determines the game server Region from the prefix of a 10-digit international ZZZ UID without performing any network requests.

Recognized 10-digit prefixes:

Returns the matched Region and true, or empty string and false if the UID prefix is not recognized.

func (Region) IsValid added in v0.10.0

func (r Region) IsValid() bool

IsValid reports whether the region is one of the recognized Region server constants.

type Set

type Set struct {
	// ID is the unique numeric identifier of the Drive Disc set (see [SetID] constants, e.g. [SetWoodpeckerElectro]).
	ID SetID `json:"id"`

	// Name is the localized display name of the set (e.g. "Woodpecker Electro", "Polar Metal", "Fanged Metal").
	Name string `json:"name"`
}

Set represents a Drive Disc equipment set. A Set grants bonus combat effects when an Agent equips 2 or 4 pieces belonging to the same set.

type SetEffect added in v0.7.0

type SetEffect struct {
	// PieceCount is the required piece count threshold (2 or 4).
	PieceCount int `json:"piece_count"`

	// Description is the localized description text of the set bonus effect.
	Description string `json:"description"`

	// FormattedHTML is the web-ready HTML description with inline CSS colors.
	FormattedHTML string `json:"formatted_html,omitempty"`

	// IsActive indicates whether this set effect is currently active on the Agent (Count >= PieceCount).
	IsActive bool `json:"is_active"`
}

SetEffect represents a specific Drive Disc set effect threshold (2-piece or 4-piece bonus).

func (SetEffect) FormatHTML added in v0.7.0

func (e SetEffect) FormatHTML() string

FormatHTML returns the set effect description formatted as HTML with inline CSS styling.

func (SetEffect) FormatMarkdown added in v0.7.0

func (e SetEffect) FormatMarkdown() string

FormatMarkdown returns the set effect description formatted with Markdown syntax.

func (SetEffect) FormatPlainText added in v0.7.0

func (e SetEffect) FormatPlainText() string

FormatPlainText returns the set effect description as clean plain text with all Rich Text tags stripped.

type SetID added in v1.0.0

type SetID int

SetID represents the unique numeric identifier of a Drive Disc set.

const (
	// SetWoodpeckerElectro represents the Woodpecker Electro set.
	SetWoodpeckerElectro SetID = 31000
	// SetPufferElectro represents the Puffer Electro set.
	SetPufferElectro SetID = 31100
	// SetShockstarDisco represents the Shockstar Disco set.
	SetShockstarDisco SetID = 31200
	// SetFreedomBlues represents the Freedom Blues set.
	SetFreedomBlues SetID = 31300
	// SetHormonePunk represents the Hormone Punk set.
	SetHormonePunk SetID = 31400
	// SetSoulRock represents the Soul Rock set.
	SetSoulRock SetID = 31500
	// SetSwingJazz represents the Swing Jazz set.
	SetSwingJazz SetID = 31600
	// SetChaosJazz represents the Chaos Jazz set.
	SetChaosJazz SetID = 31800
	// SetProtoPunk represents the Proto Punk set.
	SetProtoPunk SetID = 31900
	// SetInfernoMetal represents the Inferno Metal set.
	SetInfernoMetal SetID = 32200
	// SetChaoticMetal represents the Chaotic Metal set.
	SetChaoticMetal SetID = 32300
	// SetThunderMetal represents the Thunder Metal set.
	SetThunderMetal SetID = 32400
	// SetPolarMetal represents the Polar Metal set.
	SetPolarMetal SetID = 32500
	// SetFangedMetal represents the Fanged Metal set.
	SetFangedMetal SetID = 32600
	// SetBranchBladeSong represents the Branch & Blade Song set.
	SetBranchBladeSong SetID = 32700
	// SetAstralVoice represents the Astral Voice set.
	SetAstralVoice SetID = 32800
	// SetShadowHarmony represents the Shadow Harmony set.
	SetShadowHarmony SetID = 32900
	// SetPhaethonsMelody represents the Phaethon's Melody set.
	SetPhaethonsMelody SetID = 33000
	// SetYunkuiTales represents the Yunkui Tales set.
	SetYunkuiTales SetID = 33100
	// SetKingOfTheSummit represents the King of the Summit set.
	SetKingOfTheSummit SetID = 33200
	// SetDawnsBloom represents the Dawn's Bloom set.
	SetDawnsBloom SetID = 33300
	// SetMoonlightLullaby represents the Moonlight Lullaby set.
	SetMoonlightLullaby SetID = 33400
	// SetWhiteWaterBallad represents the White Water Ballad set.
	SetWhiteWaterBallad SetID = 33500
	// SetShiningAria represents the Shining Aria set.
	SetShiningAria SetID = 33600
	// SetBunnyInWonderland represents the Bunny in Wonderland set.
	SetBunnyInWonderland SetID = 33700
	// SetNotesFromTheChained represents the Notes From the Chained set.
	SetNotesFromTheChained SetID = 33800
	// SetWutheringSalon represents the Wuthering Salon set.
	SetWutheringSalon SetID = 33900
	// SetTheSkyAblaze represents the The Sky Ablaze set.
	SetTheSkyAblaze SetID = 34000
	// SetFeatheredFate represents the Feathered Fate set.
	SetFeatheredFate SetID = 34100
	// SetThornedRose represents the Thorned Rose set.
	SetThornedRose SetID = 34200
)

Strongly-typed Drive Disc SetID constants for all equipment sets in Zenless Zone Zero.

func AllSetIDs added in v1.0.0

func AllSetIDs() []SetID

AllSetIDs returns a newly allocated slice containing all known SetID constants. The returned slice is a defensive copy and can be safely mutated by the caller.

func (SetID) IsValid added in v1.0.0

func (s SetID) IsValid() bool

IsValid reports whether s is a recognized SetID.

type Skill

type Skill struct {
	// Level is the current progression level of the skill.
	Level int `json:"level"`

	// Name is the localized display name of the skill.
	Name string `json:"name"`

	// Description is the localized description text with Unity Rich Text formatting and formula tags.
	Description string `json:"description"`

	// FormattedHTML is the web-ready HTML description with inline colors, icon tags, and evaluated formulas.
	FormattedHTML string `json:"formatted_html,omitempty"`

	// Type is the categorized [SkillType] of the skill (basic, dodge, assist, special, chain, passive).
	Type SkillType `json:"type"`

	// TypeName is the localized name of the skill category (e.g. "Basic Attack", "EX Special Attack").
	TypeName string `json:"type_name"`

	// Params is the list of calculated numeric parameters and multipliers evaluated for the skill's current level.
	Params []SkillParam `json:"params,omitempty"`
}

Skill represents an individual combat ability or passive effect of an Agent.

func (Skill) EvaluatedDescription added in v0.5.0

func (s Skill) EvaluatedDescription() string

EvaluatedDescription returns the skill description with all dynamic scaling formulas ({CAL:...}) evaluated for the skill's current level.

func (Skill) FormatHTML added in v0.5.0

func (s Skill) FormatHTML() string

FormatHTML returns the skill description formatted as HTML with inline CSS styling, embedded Enka CDN icon tags, and scaling formulas evaluated for the skill's current level.

func (Skill) FormatMarkdown added in v0.5.0

func (s Skill) FormatMarkdown() string

FormatMarkdown returns the skill description formatted in Markdown (bold highlights for colored text) with scaling formulas evaluated for the skill's current level.

func (Skill) FormatPlainText added in v0.5.0

func (s Skill) FormatPlainText() string

FormatPlainText returns the skill description as clean plain text with all Unity Rich Text tags stripped and scaling formulas evaluated for the skill's current level.

type SkillGroup added in v0.8.0

type SkillGroup struct {
	// Type is the group category key ([SkillTypeBasic], [SkillTypeSpecial], etc.).
	Type SkillType `json:"type"`

	// TypeName is the localized category tab name.
	TypeName string `json:"type_name"`

	// Level is the progression level of the group (1–12 for active skills, 0–6 for core passives).
	Level int `json:"level"`

	// Skills is the list of individual [Skill] abilities belonging to this category group tab.
	Skills []Skill `json:"skills"`
}

SkillGroup represents a categorized group of skills matching the 6 in-game UI skill tabs/buttons.

type SkillParam added in v0.8.0

type SkillParam struct {
	// Name is the localized parameter label (e.g. "1-Hit DMG").
	Name string `json:"name"`

	// Value is the pre-formatted value string with level scaling evaluated (e.g. "124.5%").
	Value string `json:"value"`
}

SkillParam represents a calculated numeric parameter or damage multiplier for a skill.

type SkillType added in v0.8.0

type SkillType string

SkillType represents a categorized category of combat skill matching in-game button inputs.

const (
	// SkillTypeBasic represents Basic Attack combos.
	SkillTypeBasic SkillType = "basic"
	// SkillTypeDodge represents Dodge, Dash Attack, and Dodge Counter.
	SkillTypeDodge SkillType = "dodge"
	// SkillTypeAssist represents Quick Assist, Defensive Assist, and Evasive Assist.
	SkillTypeAssist SkillType = "assist"
	// SkillTypeSpecial represents Special Attack and EX Special Attack.
	SkillTypeSpecial SkillType = "special"
	// SkillTypeChain represents Chain Attack and Ultimate.
	SkillTypeChain SkillType = "chain"
	// SkillTypePassive represents Core Passive and Additional Ability.
	SkillTypePassive SkillType = "passive"
)

Supported combat skill categories in Zenless Zone Zero.

func AllSkillTypes added in v0.10.0

func AllSkillTypes() []SkillType

AllSkillTypes returns a newly allocated slice containing all 6 supported SkillType categories. The returned slice is a defensive copy and can be safely mutated by the caller.

func (SkillType) IsValid added in v0.10.0

func (st SkillType) IsValid() bool

IsValid reports whether the skill type is one of the recognized SkillType categories.

type Skin

type Skin struct {
	// ID is the internal numeric identifier of the skin.
	ID int `json:"id"`

	// Name is the localized name of the skin.
	Name string `json:"name"`

	// Description is the localized lore or description of the skin.
	Description string `json:"description"`

	// SplashArtURL is the absolute HTTPS URL pointing to the skin's splash art on the EnkaNetwork CDN.
	SplashArtURL string `json:"splash_art_url"`
}

Skin represents an equipped cosmetic skin (outfit) of an Agent.

type Specialty

type Specialty string

Specialty represents the combat role or class of an Agent.

const (
	// SpecialtyAttack represents the Attack role.
	SpecialtyAttack Specialty = "Attack"
	// SpecialtyStun represents the Stun role.
	SpecialtyStun Specialty = "Stun"
	// SpecialtyAnomaly represents the Anomaly role.
	SpecialtyAnomaly Specialty = "Anomaly"
	// SpecialtySupport represents the Support role.
	SpecialtySupport Specialty = "Support"
	// SpecialtyDefense represents the Defense role.
	SpecialtyDefense Specialty = "Defense"
	// SpecialtyRupture represents the Rupture role.
	SpecialtyRupture Specialty = "Rupture"
	// SpecialtyArmorer represents the Armorer role.
	SpecialtyArmorer Specialty = "Armorer"
)

Supported combat specialties in Zenless Zone Zero.

func AllSpecialties added in v0.10.0

func AllSpecialties() []Specialty

AllSpecialties returns a newly allocated slice containing all 7 supported Specialty constants. The returned slice is a defensive copy and can be safely mutated by the caller.

func (Specialty) IconURL added in v0.5.0

func (s Specialty) IconURL() string

IconURL returns the official EnkaNetwork CDN icon URL for the specialty.

func (Specialty) IsValid added in v0.10.0

func (s Specialty) IsValid() bool

IsValid reports whether the specialty is one of the recognized Specialty constants.

type StatValue

type StatValue struct {
	// PropertyID is the internal strongly-typed [PropertyID] (e.g. [PropATKPercent]).
	PropertyID PropertyID `json:"property_id"`

	// Name is the localized display name of the stat (e.g. "ATK", "CRIT Rate").
	Name string `json:"name"`

	// Value is the calculated numerical value of the stat. Percentage stats are stored in decimal format (e.g. 0.048 for 4.8%).
	Value float64 `json:"value"`

	// IsPercent indicates whether the stat represents a percentage value.
	IsPercent bool `json:"is_percent"`

	// Rolls is the number of times this stat was upgraded (1 for base roll, up to 5 with upgrades).
	Rolls int `json:"rolls"`

	// IconURL is the base64 Data URI string ("data:image/svg+xml;base64,...") containing the stat's SVG icon.
	IconURL string `json:"icon_url"`
}

StatValue represents a single combat stat or sub-stat entry (such as a Drive Disc main stat or substat roll).

func (StatValue) DisplayValue

func (s StatValue) DisplayValue() string

DisplayValue returns the stat's value formatted as a human-readable string (e.g. "4.8%" or "310").

func (StatValue) SVG added in v0.7.0

func (s StatValue) SVG() string

SVG returns the raw inline SVG markup string for the stat value.

type Stats

type Stats struct {
	// HP is the total Health Points.
	HP float64 `json:"hp"`

	// ATK is the total Attack.
	ATK float64 `json:"atk"`

	// DEF is the total Defense.
	DEF float64 `json:"def"`

	// Impact is the Impact stat (influences Daze accumulation rate).
	Impact float64 `json:"impact"`

	// CritRate is the Critical Hit Rate as a decimal fraction (e.g. 0.05 for 5%).
	CritRate float64 `json:"crit_rate"`

	// CritDMG is the Critical Hit Damage as a decimal fraction (e.g. 1.50 for 150%).
	CritDMG float64 `json:"crit_dmg"`

	// AttributeDMGBonus is the matching elemental Damage Bonus as a decimal fraction (e.g. 0.30 for 30%).
	AttributeDMGBonus float64 `json:"attribute_dmg_bonus"`

	// AnomalyMastery is the Anomaly Mastery stat (influences Anomaly Buildup speed).
	AnomalyMastery float64 `json:"anomaly_mastery"`

	// AnomalyProficiency is the Anomaly Proficiency stat (scales Anomaly damage).
	AnomalyProficiency float64 `json:"anomaly_proficiency"`

	// PenRatio is the Penetration Ratio as a decimal fraction (ignores a percentage of enemy DEF).
	PenRatio float64 `json:"pen_ratio"`

	// PenFlat is the flat Penetration stat (ignores a flat amount of enemy DEF).
	PenFlat float64 `json:"pen_flat"`

	// EnergyRegen is the Energy Regeneration rate per second (e.g. 1.20).
	EnergyRegen float64 `json:"energy_regen"`

	// SheerForce is the Sheer Force stat (damage multiplier for Rupture agents, ignoring DEF).
	SheerForce float64 `json:"sheer_force"`

	// SharpCritDMG is the Laceration DMG stat (damage multiplier for Armorer agents, scaling with DEF).
	SharpCritDMG float64 `json:"sharp_crit_dmg"`

	// EnergyPropertyID is the specific property ID for the agent's energy regeneration mechanism
	// (PropBaseEnergyRegen for standard agents, PropBaseRpRecover for Rupture, PropBaseEpRecover for Armorer).
	EnergyPropertyID PropertyID `json:"energy_property_id,omitempty"`
}

Stats represents the complete aggregated numerical combat stats of an Agent.

Value representations:

Use Stats.Formatted or Agent.UIStats to retrieve pre-formatted string representations.

func (*Stats) Formatted

func (s *Stats) Formatted() FormattedStats

Formatted returns a new FormattedStats struct where all numerical stats are converted into precise, human-readable strings (e.g. "50.0%" instead of 0.5, "3120" instead of 3120.0).

func (Stats) List added in v0.11.0

func (s Stats) List() []StatValue

List returns all numeric combat stats as a slice of StatValue in canonical in-game display order.

type Title

type Title struct {
	// ID is the internal numeric identifier of the title.
	ID int `json:"id"`

	// Text is the fully localized title text.
	Text string `json:"text"`

	// PrimaryColor is the 6-character hex color code for the starting gradient color (without #).
	PrimaryColor string `json:"primary_color"`

	// SecondaryColor is the 6-character hex color code for the ending gradient color (without #).
	SecondaryColor string `json:"secondary_color"`
}

Title represents an achievement or status title displayed on a player's profile.

Many titles in Zenless Zone Zero feature a two-color linear gradient. Use Title.PrimaryColorHex and Title.SecondaryColorHex to retrieve CSS-ready hex color strings.

func (*Title) PrimaryColorHex

func (t *Title) PrimaryColorHex() string

PrimaryColorHex returns the primary gradient color formatted as a standard CSS hex string (e.g. "#F7BA3F"). Returns an empty string if t is nil or if PrimaryColor is not set.

func (*Title) SecondaryColorHex

func (t *Title) SecondaryColorHex() string

SecondaryColorHex returns the secondary gradient color formatted as a standard CSS hex string (e.g. "#E74C3C"). Returns an empty string if t is nil or if SecondaryColor is not set.

type UIStats

type UIStats struct {
	// HP is the Health Points breakdown.
	HP FormattedStatBreakdown `json:"hp"`

	// ATK is the Attack breakdown.
	ATK FormattedStatBreakdown `json:"atk"`

	// DEF is the Defense breakdown.
	DEF FormattedStatBreakdown `json:"def"`

	// Impact is the Impact breakdown.
	Impact FormattedStatBreakdown `json:"impact"`

	// CritRate is the Critical Rate breakdown.
	CritRate FormattedStatBreakdown `json:"crit_rate"`

	// CritDMG is the Critical Damage breakdown.
	CritDMG FormattedStatBreakdown `json:"crit_dmg"`

	// AttributeDMGBonus is the matching elemental Damage Bonus breakdown.
	AttributeDMGBonus FormattedStatBreakdown `json:"attribute_dmg_bonus"`

	// AnomalyMastery is the Anomaly Mastery breakdown.
	AnomalyMastery FormattedStatBreakdown `json:"anomaly_mastery"`

	// AnomalyProficiency is the Anomaly Proficiency breakdown.
	AnomalyProficiency FormattedStatBreakdown `json:"anomaly_proficiency"`

	// PenRatio is the Penetration Ratio breakdown.
	PenRatio FormattedStatBreakdown `json:"pen_ratio"`

	// PenFlat is the Flat Penetration breakdown.
	PenFlat FormattedStatBreakdown `json:"pen_flat"`

	// EnergyRegen is the Energy Regeneration breakdown.
	EnergyRegen FormattedStatBreakdown `json:"energy_regen"`

	// SheerForce is the Sheer Force breakdown (for Rupture agents).
	SheerForce FormattedStatBreakdown `json:"sheer_force"`

	// SharpCritDMG is the Laceration DMG breakdown (for Armorer agents).
	SharpCritDMG FormattedStatBreakdown `json:"sharp_crit_dmg"`
}

UIStats contains all combat stats broken down into Base + Added = Total components, with localized names and icon URLs, structured for frontend profile and agent inspect panels.

func (UIStats) List added in v0.11.0

func (u UIStats) List() []FormattedStatBreakdown

List returns all combat stat breakdowns as a slice in the canonical in-game display order.

Example

ExampleUIStats_List demonstrates rendering an Agent's combat stats panel with pre-formatted Base + Added = Total breakdowns and localized stat names matching the in-game attributes screen.

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/kirinyoku/fairy"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	profile, err := fairy.GetProfile(ctx, "1504687050")
	if err != nil || len(profile.Agents) == 0 {
		return
	}

	agent := profile.Agents[0]
	fmt.Printf("=== Agent Stats: %s Lv.%d ===\n", agent.Name, agent.Level)

	for _, stat := range agent.UIStats.List() {
		fmt.Printf("%-24s %10s  (Base: %s + Added: %s)\n",
			stat.Name, stat.Total, stat.Base, stat.Added)
	}
}

type WEngine

type WEngine struct {
	// ID is the internal numeric identifier of the W-Engine.
	ID int `json:"id"`

	// UID is the unique instance identifier of this specific W-Engine.
	UID string `json:"uid"`

	// Name is the localized display name of the W-Engine (e.g. "Deep Sea Visitor", "The Brimstone").
	Name string `json:"name"`

	// Level is the current progression level of the W-Engine (1–60).
	Level int `json:"level"`

	// Phase is the ascension / star phase of the W-Engine (0–5).
	Phase int `json:"phase"`

	// Modification is the refinement level of the W-Engine's passive skill (1–5 / M1–M5).
	Modification int `json:"modification"`

	// Rarity is the rarity tier of the W-Engine ([RarityS], [RarityA], or [RarityB]).
	Rarity Rarity `json:"rarity"`

	// Specialty is the recommended combat role for this W-Engine (e.g. [SpecialtyAttack], [SpecialtyStun]).
	Specialty Specialty `json:"specialty"`

	// SpecialtyName is the localized display name of the intended specialty.
	SpecialtyName string `json:"specialty_name"`

	// IconURL is the absolute HTTPS URL pointing to the W-Engine's visual icon on the EnkaNetwork CDN.
	IconURL string `json:"icon_url"`

	// MainStat is the primary stat provided by the W-Engine ([PropBaseATK]), scaled by level and phase.
	MainStat StatValue `json:"main_stat"`

	// SecondaryStat is the secondary stat provided by the W-Engine (e.g. CRIT Rate, ATK%, PEN Ratio), scaled by level.
	SecondaryStat StatValue `json:"secondary_stat"`

	// PassiveDescription is the localized description text of the W-Engine's passive ability.
	PassiveDescription string `json:"passive_description"`

	// FormattedHTML is the web-ready HTML description with inline CSS colors and evaluated modification parameters.
	FormattedHTML string `json:"formatted_html,omitempty"`
}

WEngine represents an enriched W-Engine (weapon) equipped by an Agent. It provides base combat stats, scaling secondary stats, and a unique passive ability.

func (*WEngine) FormatHTML added in v0.6.0

func (w *WEngine) FormatHTML() string

FormatHTML returns the W-Engine passive description formatted as HTML with inline CSS styling. Returns an empty string if w is nil.

func (*WEngine) FormatMarkdown added in v0.6.0

func (w *WEngine) FormatMarkdown() string

FormatMarkdown returns the W-Engine passive description formatted with Markdown syntax. Returns an empty string if w is nil.

func (*WEngine) FormatPlainText added in v0.6.0

func (w *WEngine) FormatPlainText() string

FormatPlainText returns the W-Engine passive description as clean plain text with all Rich Text tags stripped. Returns an empty string if w is nil.

Directories

Path Synopsis
internal
api
Package api provides a thin adapter layer over the upstream enkanetwork-go client.
Package api provides a thin adapter layer over the upstream enkanetwork-go client.
assets
Package assets provides embedded binary data for the fairy library.
Package assets provides embedded binary data for the fairy library.
store
Package store provides an abstraction over the Zenless Zone Zero datamined game data.
Package store provides an abstraction over the Zenless Zone Zero datamined game data.
tools/extractor command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL