package secretbox import ( "fmt" "honoka-chan/internal/middleware" unitmodel "honoka-chan/internal/model/unit" "honoka-chan/internal/router" secretboxapischema "honoka-chan/internal/schema/api/secretbox" secretboxschema "honoka-chan/internal/schema/secretbox" "honoka-chan/internal/session" honokautils "honoka-chan/internal/utils" "math/rand" "time" "github.com/gin-gonic/gin" ) func pon(ctx *gin.Context) { ss := session.Get(ctx) defer ss.Finalize() ponReq := secretboxschema.PonReq{} err := honokautils.ParseRequestData(ctx, &ponReq) if ss.CheckErr(err) { return } data, err := drawData(ctx, ponReq.SecretBoxID, ponReq.ID) if ss.CheckErr(err) { return } ss.Respond(secretboxschema.PonResp{ ResponseData: data, ReleaseInfo: []any{}, StatusCode: 200, }) } func init() { router.AddHandler("main.php", "POST", "/secretbox/pon", middleware.Common, pon) } func drawData(ctx *gin.Context, secretBoxID, costID int) (secretboxschema.PonData, error) { if secretBoxID <= 0 || costID <= 0 { return secretboxschema.PonData{}, fmt.Errorf("invalid secretbox draw params: secret_box_id=%d id=%d", secretBoxID, costID) } ss := session.Get(ctx) config, err := loadSecretBoxAllData() if err != nil { return secretboxschema.PonData{}, err } memberCategory, page, err := findSecretBoxPage(config, secretBoxID) if err != nil { return secretboxschema.PonData{}, err } button, cost, err := findSecretBoxCost(page, costID) if err != nil { return secretboxschema.PonData{}, err } rng := rand.New(rand.NewSource(time.Now().UnixNano())) drawnUnits, lowestRarity, err := buildDrawUnits(ss, rng, memberCategory, page, button, cost) if err != nil { return secretboxschema.PonData{}, err } for i := range page.ButtonList { for j := range page.ButtonList[i].CostList { page.ButtonList[i].CostList[j].Payable = true } } page.SecretBoxInfo.PonCount += cost.UnitCount itemList := config.Result.ItemList for i := range itemList { if itemList[i].Amount < 999 { itemList[i].Amount = 999 } } return secretboxschema.PonData{ IsUnitMax: false, ItemList: itemList, GaugeInfo: secretboxapischema.GaugeInfo{ MaxGaugePoint: 100, GaugePoint: 0, }, ButtonList: page.ButtonList, SecretBoxInfo: page.SecretBoxInfo, SecretBoxItems: secretboxschema.SecretBoxItems{Unit: drawnUnits, Item: []secretboxschema.SecretBoxRewardItem{}}, BeforeUserInfo: ss.GetUserInfo(), AfterUserInfo: ss.GetUserInfo(), FreeMuseGachaFlag: false, FreeAqoursGachaFlag: false, LowestRarity: lowestRarity, PromotionPerformanceRate: 25, SecretBoxParcelType: 2, LimitBonusInfo: []any{}, LimitBonusRewards: []any{}, UnitSupportList: []any{}, }, nil } func buildDrawUnits(ss *session.Session, rng *rand.Rand, memberCategory int, page secretboxapischema.SecretBoxPage, button secretboxapischema.SecretBoxButton, cost secretboxapischema.SecretBoxCost) ([]secretboxschema.SecretBoxUnitItem, int, error) { drawCount := cost.UnitCount if drawCount <= 0 { drawCount = 1 } rarities := make([]int, 0, drawCount) for i := 0; i < drawCount; i++ { rarities = append(rarities, pickRarity(rng, page, button, i == drawCount-1 && drawCount > 1)) } if drawCount > 1 { guaranteedRarity := raritySR if hasGuaranteedUR(button, cost) { guaranteedRarity = rarityUR } guaranteed := false for _, rarity := range rarities { if satisfiesGuaranteedRarity(rarity, guaranteedRarity) { guaranteed = true break } } if !guaranteed { if guaranteedRarity == rarityUR { rarities[drawCount-1] = rarityUR } else { rarities[drawCount-1] = pickGuaranteedRarity(rng, page, button) } } } result := make([]secretboxschema.SecretBoxUnitItem, 0, drawCount) lowestRarity := 0 for _, rarity := range rarities { unitID, err := randomUnitID(ss, rng, memberCategory, page, button, rarity) if err != nil { return nil, 0, err } unitData, err := getUserUnitByUnitID(ss, unitID) if err != nil { return nil, 0, err } item := buildUnitItem(unitData) item.IsHit = shouldShowDirectURHit(rng, page, button, rarity) result = append(result, item) if lowestRarity == 0 || isLowerQualityRarity(rarity, lowestRarity) { lowestRarity = rarity } } return result, lowestRarity, nil } func buildUnitItem(unitData unitmodel.UnitDataMap) secretboxschema.SecretBoxUnitItem { isSupportMember := unitData.MaxLove == 0 && unitData.UnitSkillLevel == 0 && unitData.UnitRemovableSkillCapacity == 0 insertDate := time.Unix(unitData.InsertDate, 0).Format("2006-01-02 15:04:05") return secretboxschema.SecretBoxUnitItem{ UnitOwningUserID: unitData.UnitOwningUserID, UnitOwningIDs: []int{unitData.UnitOwningUserID}, UnitID: unitData.UnitID, Exp: unitData.Exp, NextExp: 0, Level: unitData.Level, MaxLevel: unitData.MaxLevel, LevelLimitID: unitData.LevelLimitID, Rank: unitData.Rank, MaxRank: unitData.MaxRank, Love: unitData.Love, MaxLove: unitData.MaxLove, UnitSkillLevel: unitData.UnitSkillLevel, SkillLevel: unitData.UnitSkillLevel, UnitSkillExp: unitData.UnitSkillExp, MaxHp: unitData.MaxHp, FavoriteFlag: unitData.FavoriteFlag, DisplayRank: unitData.DisplayRank, UnitRemovableSkillCapacity: unitData.UnitRemovableSkillCapacity, MaxRemovableSkillCapacity: unitData.UnitRemovableSkillCapacity, Attribute: unitData.Attribute, Smile: unitData.Smile, Cute: unitData.Cute, Cool: unitData.Cool, IsRankMax: unitData.IsRankMax, IsLoveMax: unitData.IsLoveMax, IsLevelMax: unitData.IsLevelMax, IsSigned: unitData.IsSigned, IsSkillLevelMax: unitData.IsSkillLevelMax, IsRemovableSkillCapacityMax: unitData.IsRemovableSkillCapacityMax, IsSupportMember: isSupportMember, NewUnitFlag: false, UnitRarityID: unitData.Rarity, IsHit: unitData.Rarity == rarityUR, RemovableSkillIDs: []int{}, InsertDate: insertDate, TotalSmile: unitData.Smile, TotalCute: unitData.Cute, TotalCool: unitData.Cool, TotalHp: unitData.MaxHp, } }