Skip to content
Skip to documentation content

Offense / Artifacts Registry

Artifacts Registry

Choose a recorded artifact, select a Cleaner, Destroyer or Hero role and save village assignments for a three-role capture plan.

At a glance

Product route: /workspaces/{workspace_id}/artifacts-3-waves-plan.

Who can open this page: Verified view_artifact_plan and enabled entitlement; separate from collection. A signed-in user needs enabled workspace entitlement and verified active membership, including the owner. Non-owners also need the named active grant; verified owners bypass the individual grant check, not entitlement or verification. These feature routes do not resolve a current linked game account. Sidebar visibility does not grant endpoint access. The separate view_artifact_plan grant controls viewing and assignment; collection alone is insufficient. The shell shows this entry only when its artifact-plan navigation flag is enabled.

What you see

Step1 Artifact Registry shows artifact name, name-based icon, small/large/unique category, coordinates and saved Cleaner/Cata/Hero labels. Search artifacts by name is a case-insensitive substring filter; All categories/Small/Large/Unique filters size. Cards paginate eight at a time. The initial selection is the first artifact ordered by name, x and y. Mouse, Enter or Space select a card; filtering/paging does not itself choose another artifact. Collected artifact owner and show/game-ID are not displayed.

Step2 Plan shows the selected artifact and an external map link, with Cleaner, Destroyer and Hero cards showing assigned account/village and their map links. An unassigned role says Unassigned / No village assigned and has no active map link. Step3 Select Villages loads candidates only after choosing a role. The table shows Village, Account, Coordinates, Distance, Off, Catas, Treasury, Assign and Assigned artifact icons. Off means offensive crop upkeep, not attack strength. TS, troop slots, tribe and captured update timestamps are not columns here. Assigned icons select that artifact; map links are on the artifact/role cards, not candidate names.

Min off, Min catas and Min Treasury lvl apply locally to the currently loaded candidates. A blank, unparsable or negative integer threshold becomes0; zero leaves all candidates visible. For positive thresholds Cleaner keeps Off strictly greater than the input, Destroyer keeps Catas strictly greater, and Hero keeps Treasury greater than or equal. Treasury input advertises0–20. The endpoint returns only the first50 nearest villages; filtering cannot find qualifying villages outside that batch. The summary total can describe all villages while the filtered status counts visible loaded rows. No manual village tag is required or shown in this candidate list.

Click the selected role tag in a candidate row to assign it. Clicking its filled tag again clears the role; selecting a different village replaces its previous coordinate. Each artifact stores one coordinate per role, not a troop quantity or a wave schedule. The same village can occupy multiple roles and multiple artifacts. The three steps organize selection and capture responsibilities; this page does not schedule three timed waves, publish operation commands or launch attacks.

Who fills in each field

Field or data What it means Who fills it in Can it be changed here? When it updates
Artifact name, size, icon and coordinates Collected artifact name, small/large/unique size, derived name icon and coordinates; collected artifact owner/show are not displayed. extension-collected, backend-derived Read-only Connected extension artifact observation
Cleaner/destroyer/hero assignments Authorized planner stores one village coordinate per Cleaner/Destroyer/Hero role; selecting the same coordinate again clears that role. Local thresholds filter the loaded candidates, not endpoint eligibility. signed-in-member view_artifact_plan Role toggle
Candidate village, account, coordinates, distance, Off, Catas and Treasury Captured workspace villages and linked account labels; roster supplies tribe coefficients. Off is base crop upkeep for configured offensive slots, Catas is raw catapult count, Treasury is recorded level and distance wraps map edges. TS is not displayed. roster-ingest, extension-collected, signed-in-member, backend-derived Read-only Page load from latest recorded values

Calculations

Wrapped map distance

Calculation ID: map.wrapped-distance. Shortest Euclidean distance on a toroidal Travian world.

Rule: size=2*radius+1; dx=min(abs(x1-x2),size-abs(x1-x2)); same for dy; hypot(dx,dy). Default radius200 means401coordinates per axis, so -200 and200 are adjacent.

Input Who supplies it Unit Optional / fallback
Source/destination coordinates signed-in-member, roster-ingest, extension-collected map coordinates Required; Required; no fallback
radius backend-derived fields Optional; 200

Output unit: fields. Precision: Floating point hypot. Rounding: No rounding. Clamp: No output clamp. Timezone: not-applicable.

Edge cases: Same coordinate returns zero. Assumes coordinates in the configured world; this helper does not validate/wrap arbitrary out-of-world values. Browser radius null also defaults200; mirrors are separately hashed and not proof of equivalence.

On a default world, synthetic (−200|0) and (200|0) are one field apart. Same coordinates give zero. The candidate list sorts by the full floating-point distance, then casefold account, village name, x and y; it displays one decimal field. No timezone applies. The browser/extension copies are independently reviewed, not proof of equivalence.

Canonical source and dependencies are reviewed below.

Calculation source references - Canonical: `src/trapitan/core/travian.py` — `travian_distance`. - Non-canonical mirror: `src/trapitan/web/static/js/travian-distance.js` — bounded calculation region. - Non-canonical mirror: `extension/chromium/lib/def-call-dispatch.js` — bounded calculation region.

Used on: Villages, Def Calls, Counter Scout Plan, Artifacts Registry, Operation Dashboard.

Off/Deff crop upkeep

Calculation ID: grain.offense-defense. Separate configured role-weighted crop totals.

Rule: For each positive count, add count*grain_upkeep to offensive_grain if counts_as_off and to defensive_grain if counts_as_deff. Flags are independent: a slot may contribute to both or neither. Members/Villages DTO strength properties carry these grain totals. Base upkeep excludes reductions.

Input Who supplies it Unit Optional / fallback
counts by slot extension-collected troops Optional; Missing slot =>0; counts<=0 contribute nothing
Versioned tribe coefficients backend-derived attack/defense points, crop per troop and role flags Optional; Missing/unseeded tribe coefficient mapping => all-zero numeric result; active version configuration selects dataset

Output unit: crop upkeep per hour. Precision: Exact integer. Rounding: No rounding. Clamp: No output clamp. Timezone: not-applicable.

Edge cases: Does not use attack/defense combat coefficients. No artifact/trough/upkeep reductions are applied. Role flags come from the active coefficient dataset, not member classification. Compact UI formatting: abs>=1million =>one decimal M, abs>=1000 =>one decimal K; trim .0; below1000 truncate to integer. Numeric derivation remains exact. None formats0.

Artifacts shows only the offensive crop-upkeep total under Off; no Deff column is rendered. Synthetic 10 troops with upkeep2 and the offensive flag contribute20 crop/hour. The flags can overlap; classification and combat attack points do not replace them. The local Cleaner threshold compares the raw total, before compact formatting.

Canonical source and dependencies are reviewed below.

Calculation source references - Canonical: `src/trapitan/intelligence/calculator.py` — `compute_strength`. - Dependency: `src/trapitan/intelligence/calculator.py` — `CoefficientSet`. - Dependency: `src/trapitan/intelligence/calculator.py` — `COMBAT_CLASS`. - Dependency: `src/trapitan/intelligence/calculator.py` — `SIEGE_CLASS`. - Dependency: `src/trapitan/intelligence/calculator.py` — `BASIS`. - Dependency: `src/trapitan/intelligence/calculator.py` — `load_coefficients`. - Dependency: `src/trapitan/intelligence/service.py` — `IntelligenceService._coefficients_for_tribe`. - Dependency: `src/trapitan/intelligence/calculator.py` — `GRAIN_BASIS`. - Dependency: `src/trapitan/intelligence/service.py` — `IntelligenceService.list_members`. - Dependency: `src/trapitan/intelligence/service.py` — `IntelligenceService.list_villages`. - Dependency: `src/trapitan/core/config.py` — `Settings.active_coefficient_version`. - Dependency: `src/trapitan/web/formatting.py` — `format_compact_number`. - Dependency: `src/trapitan/web/formatting.py` — `_trim_decimal`. - Non-canonical mirrors: none registered.

Used on: Villages, Members, Artifacts Registry.

Rams and catapults

Calculation ID: siege.split. Separate raw siege unit counts from combat strength.

Rule: For positive counts where unit_class==siege, a seeded unit_name containing ram case-insensitively increments rams; every other siege unit increments catapults. These raw counts are used in derived intelligence/planning and auto tags, not added to offensive strength.

Input Who supplies it Unit Optional / fallback
counts by slot extension-collected troops Optional; Missing slot =>0; counts<=0 contribute nothing
Versioned tribe coefficients backend-derived attack/defense points, crop per troop and role flags Optional; Missing/unseeded tribe coefficient mapping => all-zero numeric result; active version configuration selects dataset

Output unit: siege units. Precision: Exact integer. Rounding: No rounding. Clamp: No output clamp. Timezone: not-applicable.

Edge cases: Translated UI labels are not used to detect rams. Unknown coefficients yield zero. Off/Deff crop flags can independently include siege upkeep. Compact UI formatting: abs>=1million =>one decimal M, abs>=1000 =>one decimal K; trim .0; below1000 truncate to integer. Numeric derivation remains exact. None formats0.

Artifacts shows Catas, not Rams. Synthetic 10 positive siege units with a seeded ram name contribute10 rams and zero catas; 10 other siege units contribute10 catas. Destroyer filtering uses the raw count. Unknown coefficients can give zero despite a nonempty capture.

Canonical source and dependencies are reviewed below.

Calculation source references - Canonical: `src/trapitan/intelligence/calculator.py` — `compute_strength`. - Dependency: `src/trapitan/intelligence/calculator.py` — `CoefficientSet`. - Dependency: `src/trapitan/intelligence/calculator.py` — `COMBAT_CLASS`. - Dependency: `src/trapitan/intelligence/calculator.py` — `SIEGE_CLASS`. - Dependency: `src/trapitan/intelligence/calculator.py` — `BASIS`. - Dependency: `src/trapitan/intelligence/calculator.py` — `load_coefficients`. - Dependency: `src/trapitan/intelligence/service.py` — `IntelligenceService._coefficients_for_tribe`. - Dependency: `src/trapitan/intelligence/calculator.py` — `_is_ram`. - Dependency: `src/trapitan/core/config.py` — `Settings.active_coefficient_version`. - Dependency: `src/trapitan/web/formatting.py` — `format_compact_number`. - Dependency: `src/trapitan/web/formatting.py` — `_trim_decimal`. - Non-canonical mirrors: none registered.

Used on: Villages, Members, Artifacts Registry.

Freshness and updates

The authenticated extension artifact submission uses view_artifact_plan, resolves active membership by submitting user/server and upserts records by workspace and artifact name. It updates coordinates, size, owner and show for included records, preserving role assignments; absent artifacts are not removed. Submission collected_at is accepted but not used by this upsert and no capture timestamp is displayed. Names/sizes are validated; accepted size is small, large or unique.

Reloading the registry refreshes saved artifacts, assignments and account/village labels. Selecting a role requests current captured workspace villages, sorted by full wrapped distance and capped at50. Captured village counts/buildings can be stale; Treasury can also have been manually changed on Troops Overview. Successful role toggles update card/plan labels and the clicked role tags in the browser. Assigned artifact icons are generated on candidate load, so they can lag a subsequent toggle until the role list reloads. Threshold/search/category controls change local display only; no periodic collection or polling occurs.

Actions and permissions

Who can perform each action / Who can take action: access to a page does not replace its write guards.

Action Actor Permission
Assign artifact role signed-in-member Verified view_artifact_plan, enabled entitlement; workspace-scoped artifact/village, role enum and same origin; no troop, tag or Treasury eligibility check

Every candidate load and assignment repeats view_artifact_plan authorization. The write requires same origin, an artifact in this workspace, a recorded village belonging to a workspace account and one of cleaner/destroyer/hero. It does not enforce Min off/Min catas/Min Treasury, tags, hero availability, positive troop counts or distinct villages. Any verified grantee may assign; workspace-manager status, operation ownership and the caller's own linked village are not additional endpoint requirements. A missing/cross-workspace artifact or village is404; unsupported role is rejected by enum validation. External game links do not dispatch troops.

States and edge cases

“No artifacts registered” shows when no records exist; Plan asks to register an artifact, but this web page has no registration form. “No artifacts match your filters” is a local filtered state and does not delete the current selection. Initially Select Villages says “Choose a plan role.” Role loading shows a busy message; failure says “Villages unavailable” and asks to select the role again. With no candidate rows the partial says no collected villages are available. Thresholds that hide every loaded row can leave an empty table with zero-visible status, not the no-capture message.

An assignment request disables its button while pending; failure shows “Assignment unavailable” and retains the prior displayed state. Unknown artifact names get an empty sprite; unknown roster tribe or missing coefficient mapping gives zero derived Off/Catas. An assignment coordinate with no current village label falls back to its coordinate instead of inventing an account. If a capture moves an artifact, stored role coordinates remain until explicitly changed.

Distance displays one decimal while sorting uses unrounded distance. Compact Off/Catas preserve sign, use K at absolute1,000 and M at1,000,000, round the scaled float to one decimal and remove trailing .0; smaller values truncate toward zero and None formats0. There is no clamp or timezone. Thus synthetic1,250 displays1.2K under Python float formatting, while filtering still compares1250. Distance world wrapping assumes valid world coordinates; it does not validate arbitrary coordinates. The browser's threshold integer parsing and zero fallback are UI filters, not server eligibility guarantees.

Targets, Villages, Troops Overview, Operation Dashboard.

Source references

Stable page ID: offense.artifacts.

Source reviewed: 2026-10-07

Reviewed handlers, visible controls and producers - `src/trapitan/api/routes/web.py` — `artifacts_3_waves_plan_page`. - `src/trapitan/web/templates/artifacts_3_waves_plan.html` — `bounded template/browser region`. - `src/trapitan/api/routes/web.py` — `_shell_context`. - `src/trapitan/api/routes/web.py` — `artifacts_3_waves_plan_villages`. - `src/trapitan/web/templates/partials/artifact_villages_table.html` — `bounded template/browser region`. - `src/trapitan/web/static/js/artifacts-3-waves-plan.js` — `bounded template/browser region`. - `src/trapitan/web/artifacts_3_waves_plan.py` — `present_artifacts`. - `src/trapitan/web/artifacts_3_waves_plan.py` — `plan_roles_for`. - `src/trapitan/web/artifacts_3_waves_plan.py` — `_assignment_details`. - `src/trapitan/web/artifacts_3_waves_plan.py` — `_assignment_label`. - `src/trapitan/web/artifacts_3_waves_plan.py` — `assigned_artifacts_by_coordinate`. - `src/trapitan/web/artifacts_3_waves_plan.py` — `icon_index_for_name`. - `src/trapitan/web/artifacts_3_waves_plan.py` — `ARTIFACT_ICON_SPRITE_RULES`. - `src/trapitan/intelligence/service.py` — `IntelligenceService.list_villages`. - `src/trapitan/intelligence/service.py` — `IntelligenceService._sort_villages`. - `src/trapitan/intelligence/repository.py` — `IntelligenceRepository.list_workspace_village_rows`. - `src/trapitan/web/formatting.py` — `format_compact_number`. - `src/trapitan/web/formatting.py` — `_trim_decimal`. - `src/trapitan/api/routes/extension_collection.py` — `submit_artifacts`. - `src/trapitan/api/routes/extension_collection.py` — `_upsert_artifacts`. - `src/trapitan/api/routes/extension_collection.py` — `ExtensionArtifactsSubmission`. - `src/trapitan/api/routes/extension_collection.py` — `ExtensionArtifactSubmission`. - `src/trapitan/api/routes/extension_collection.py` — `_authorize_server_action`. - `src/trapitan/api/routes/extension_collection.py` — `_resolve_active_membership_workspace`. - `src/trapitan/api/routes/extension_auth.py` — `require_extension_connection`. - `src/trapitan/authorization/dependencies.py` — `require_workspace_permission`. - `src/trapitan/authorization/policy.py` — `authorize_workspace_action`. - `src/trapitan/authorization/policy.py` — `_authorize_from_database`. - `src/trapitan/authorization/policy.py` — `is_membership_verified`. - `src/trapitan/authorization/policy.py` — `_active_membership`. - `src/trapitan/authorization/policy.py` — `_is_workspace_entitled`. - `src/trapitan/authorization/policy.py` — `_has_active_permission`. - `src/trapitan/authorization/policy.py` — `WorkspaceAction`. - `src/trapitan/authorization/policy.py` — `GRANTABLE_ACTIONS`. - `src/trapitan/api/routes/web.py` — `toggle_artifact_village_assignment`. - `src/trapitan/api/routes/guards.py` — `is_same_origin`.