feat(variants): default a registered account to Erudit + Russian Scrabble
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 22s
CI / ui (pull_request) Successful in 1m16s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m53s
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 22s
CI / ui (pull_request) Successful in 1m16s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m53s
New Game opened on a single variant for everyone, which reads poorly on VK where Russian Scrabble is the familiar game. A registered account now starts with both Russian-alphabet games, so the picker offers a real choice with no pre-selection. A guest stays on Erudit alone and is invited to register for the rest: the device-local guest has no profile at all, so the client-side fallback has to keep matching the server. Registering promotes the set, but only while the guest still carries the untouched guest default. Existing accounts are not backfilled — the set they carry may be a deliberate choice. The Telegram promo start-param becomes additive rather than a replacement, with English Scrabble withheld from a Russian-speaking arrival; otherwise the English campaign link would have taken Russian Scrabble away from every account it onboarded.
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
@@ -76,6 +77,18 @@ var knownVariants = map[string]bool{"erudit_ru": true, "scrabble_ru": true, "scr
|
||||
// in (Erudit, Russian Scrabble, English), independent of the client's order.
|
||||
var canonicalVariantOrder = []string{"erudit_ru", "scrabble_ru", "scrabble_en"}
|
||||
|
||||
// DefaultVariantPreferences is the variant set a newly registered account starts with:
|
||||
// both Russian-alphabet games. It mirrors the accounts.variant_preferences column
|
||||
// default, which is what actually seeds a created row — the constant is here so the
|
||||
// promotion of a guest (ClearGuest) and the tests name the same set as the schema.
|
||||
var DefaultVariantPreferences = []string{"erudit_ru", "scrabble_ru"}
|
||||
|
||||
// GuestVariantPreferences is the variant set an ephemeral guest starts with: Эрудит
|
||||
// alone. A guest is deliberately narrower than a registered player — the New Game
|
||||
// screen offers the single variant and invites the guest to register for the rest —
|
||||
// so ProvisionGuest writes it explicitly instead of taking the column default.
|
||||
var GuestVariantPreferences = []string{"erudit_ru"}
|
||||
|
||||
// validateVariantPreferences cleans a profile's variant-preference set: it drops
|
||||
// duplicates, rejects an unknown label or an empty set (ErrInvalidProfile) and
|
||||
// returns the preferences in canonicalVariantOrder so the stored value is
|
||||
@@ -129,6 +142,33 @@ func SeedVariantsFromStartParam(startParam string) []string {
|
||||
return prefs
|
||||
}
|
||||
|
||||
// MergeVariantSeed resolves the variant-preference set to store for an account that
|
||||
// arrived on a promo deep link. The seed decoded from the link is *added* to current
|
||||
// (the set the account already carries, normally the column default) rather than
|
||||
// replacing it, so a campaign can only ever widen a player's choice. English Scrabble
|
||||
// is the one variant the language gates: it is dropped from seed when languageCode is
|
||||
// Russian, because a Russian-speaking arrival is served by the two Russian-alphabet
|
||||
// games and the English one would only clutter New Game. It returns nil when there is
|
||||
// nothing to write — an empty or invalid seed, or a merge that leaves current as it is
|
||||
// — so the caller can skip the update.
|
||||
func MergeVariantSeed(current, seed []string, languageCode string) []string {
|
||||
if len(seed) == 0 {
|
||||
return nil
|
||||
}
|
||||
extra := seed
|
||||
if supportedLanguage(languageCode) == "ru" {
|
||||
extra = slices.DeleteFunc(slices.Clone(seed), func(v string) bool { return v == "scrabble_en" })
|
||||
}
|
||||
merged, err := validateVariantPreferences(append(slices.Clone(current), extra...))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if base, err := validateVariantPreferences(current); err == nil && slices.Equal(base, merged) {
|
||||
return nil
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
// SetVariantPreferences overwrites only the variant-preference set of the account,
|
||||
// cleaning it to a deduplicated, canonically ordered subset of the known variants
|
||||
// (rejecting an empty or unknown set with ErrInvalidProfile) and bumping updated_at; it
|
||||
|
||||
Reference in New Issue
Block a user