Elite and fully elite are separate conditions

isElite is populated from account elite-vehicle membership or qualifying default-elite descriptor status. The default-elite branch excludes types found in the dossier cache's tech trees. It is not simply a premium-vehicle check.

isFullyElite additionally requires every unlock target in unlocksDescrs to be present in the account unlock set. Both flags start false before synchronized construction supplies their values. A displayed progress count or the currently installed modules alone cannot replace these checks.

Fragment tooltip discounts have their own rounding stages

The blueprint requester separates a fragment's discount payload from the cumulative blueprint discount. getRequiredCountAndDiscount returns the total configured fragment count and a rounded integer percentage. It normally starts with the configured per-level fragment fraction; only when totalCount - filledCount == 1 does it use the residual 1 - filledCount * fraction instead.

getFragmentDiscountAndCost then multiplies the supplied full XP cost by that already-rounded percentage and rounds the XP result. The tooltip context supplies the full unlock price from the tech-tree calculation. The fragment and empty-slot tooltips consume this percentage/XP pair. This is a displayed discount amount, not a fragment purchase price or permission to convert fragments.

Cumulative getBlueprintDiscount instead rounds fraction * filledCount * 100 after its own gates and returns 100 when a nonzero filled count reaches or exceeds the configured total. These are separate projections. With a synthetic fraction 0.126, four total slots and full XP cost 1000, the ordinary fragment payload is (13, 130). Moving the supplied filled count from one to two changes the cumulative percentage from 13 to 25: its difference is 12, not the fragment payload's 13. With three filled slots, the final-fragment residual produces (62, 620).

These values came from selected original requester methods and the original rounding helper's host Python 3 branch, using inert configuration/count/cache adapters. They demonstrate stage order and the exact one-slot residual condition, not supported stock tuning, real account costs, server acceptance, tooltip rendering or execution in the client Python 2 runtime. Preserve the fragment payload separately from total unlock savings; do not reconstruct either by summing rounded fragment rows.

Training XP estimates use different horizons

The GUI tankman exposes two similarly named cost helpers. getNextLevelXpCost takes one level-up increment and subtracts the descriptor's retained freeXP. getNextSkillXpCost sums the increments from the selected current level through level 99, then subtracts that retained XP once. Its horizon is completing the selected training to 100, rather than gaining only the next level.

Both helpers select role training or the last selected skill under their unfinished-training guard. Their skill sequence excludes free skills; role training uses sequence zero. When the guard fails they return None, not a zero-cost training operation. The descriptor's retained XP is a separate input from account Free XP.

The tankman dossier studying block publishes its nextSkillXPLeft field using the next-level helper, and its battles estimate uses the same horizon with additional history/readiness gates. The private results-side estimate instead uses the full-training helper when supplied average XP is positive. Follow the actual helper rather than inferring the horizon from a field name containing Skill. That private calculation does not by itself establish which result cards are displayed or that a new perk was earned.

The requester supplies the tankman's own descriptor and dossier together with an external dossier: the tankman's vehicle dossier when isInTank, otherwise the account dossier. The tankman dossier retains external total, clan and global-map statistics for its mean XP: (totalXP - clanXP + globalMapXP) divided by the analogous battle count, using old_div and returning zero for a zero denominator. Its participation count instead reads the tankman's own dossier. An external mean can therefore be available while the own-history gate still returns no battle estimate. This mean is not that crew member's personal XP per battle or a forecast of future earnings. Requester routing and separate inputs were checked with recording/inert adapters, including an integer-division substitute; actual dossier construction and reassignment/cache transitions were not exercised.

The studying block also has a separate premium comparison. Only the battle-estimate row enables this factor projection; the XP-left row does not. The row packer passes the already-computed battle estimate to a helper that selects the default premium crew-XP factor, or the captured vehicle factor when the current vehicle is premium. For nonzero values it applies max(1, old_div(value, factor)); zero and unavailable values remain separate. Both values are formatted afterward. This is a projection of the existing estimate, not a fresh calculation that applies the factor to average XP before rounding the battle estimate. Selected helper/packer checks used supplied floating factors and recording format adapters; actual compatibility-helper behavior, localized formatting and future premium earnings were not tested.

With an inert linear cost table, selected original methods at level 98, earned-skill sequence one and retained XP 50 returned next-level cost 150 and full-training cost 350. These synthetic values establish the different horizons, not production XP costs or a prediction of future earnings. The host checks do not verify Python 2 division or battle-count rounding. Full descriptors, actual training tables, UI admission/rendering, server training and execution in the client Python 2 runtime were not exercised.