func awakeningsTableHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "<html><head><title>All Awakenings</title></head><body>\n") io.WriteString(w, "<table><thead><tr><th>From Card</th><th>To Card</th><th>Chance</th><th>Orb</th><th>Large</th><th>Medium</th><th>Small</th></tr></thead><tbody>\n") for _, value := range VcData.Awakenings { baseCard := vc.CardScan(value.BaseCardId, VcData.Cards) resultCard := vc.CardScan(value.ResultCardId, VcData.Cards) fmt.Fprintf(w, "<tr><td><img src=\"/images/cardthumb/%s\"/><br /><a href=\"/cards/detail/%d\">%s</a></td><td><img src=\"/images/cardthumb/%s\"/><br /><a href=\"/cards/detail/%d\">%s</a></td><td>%d%%</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td></tr>", baseCard.Image(), baseCard.Id, baseCard.Name, resultCard.Image(), resultCard.Id, resultCard.Name, value.Percent, value.Material1Count, value.Material2Count, value.Material3Count, value.Material4Count, ) } io.WriteString(w, "</tbody></table>\n") io.WriteString(w, "</body></html>") }
func awakeningsCsvHandler(w http.ResponseWriter, r *http.Request) { // File header w.Header().Set("Content-Disposition", "attachment; filename=vcData-awaken-"+strconv.Itoa(VcData.Version)+"_"+VcData.Common.UnixTime.Format(time.RFC3339)+".csv") w.Header().Set("Content-Type", "text/csv") cw := csv.NewWriter(w) cw.Write([]string{ "Id", "Name", "BaseCardId", "ResultCardId", "Percent", "Material1Item ", "Material1Count", "Material2Item ", "Material2Count", "Material3Item ", "Material3Count", "Material4Item ", "Material4Count", "Order", "IsClosed", }) for _, value := range VcData.Awakenings { baseCard := vc.CardScan(value.BaseCardId, VcData.Cards) cw.Write([]string{ strconv.Itoa(value.Id), baseCard.Name, strconv.Itoa(value.BaseCardId), strconv.Itoa(value.ResultCardId), strconv.Itoa(value.Percent), strconv.Itoa(value.Material1Item), strconv.Itoa(value.Material1Count), strconv.Itoa(value.Material2Item), strconv.Itoa(value.Material2Count), strconv.Itoa(value.Material3Item), strconv.Itoa(value.Material3Count), strconv.Itoa(value.Material4Item), strconv.Itoa(value.Material4Count), strconv.Itoa(value.Order), strconv.Itoa(value.IsClosed), }) } cw.Flush() }
func getWikiReward(reward vc.RankRewardSheet, newline bool) string { rlist := "%s x%d" if newline { rlist = "<br />" + rlist } var r string if reward.CardId > 0 { card := vc.CardScan(reward.CardId, VcData.Cards) if card == nil { r = "{{Card Icon|Unknown Card Id}}" } else { r = fmt.Sprintf("{{Card Icon|%s}}", card.Name) } } else if reward.ItemId > 0 { item := vc.ItemScan(reward.ItemId, VcData.Items) if item == nil { r = fmt.Sprintf("__UNKNOWN_ITEM_ID:%d__", reward.ItemId) } else if item.GroupId == 17 { // tickets r = fmt.Sprintf("{{Ticket|%s}}", cleanTicketName(item.NameEng)) } else if item.GroupId == 30 || (item.GroupId >= 10 && item.GroupId <= 16) { // Arcana r = fmt.Sprintf("{{Arcana|%s}}", cleanArcanaName(item.NameEng)) } else if (item.GroupId >= 5 && item.GroupId <= 7) || item.GroupId == 31 || item.GroupId == 22 { // sword, shoe, key, rod, potion r = fmt.Sprintf("{{Valkyrie|%s}}", cleanItemName(item.NameEng)) } else if item.GroupId == 18 { // exchange items r = fmt.Sprintf("[[File:%[1]s.png|28px|link=Items#%[1]s]] [[Items#%[1]s|%[1]s]]", item.NameEng) } else { r = fmt.Sprintf("__UNKNOWN_GROUP:_%d_%s__", item.GroupId, item.NameEng) } } else { r = "Unknown Reward Type" } return fmt.Sprintf(rlist, r, reward.Num) }
func eventDetailHandler(w http.ResponseWriter, r *http.Request) { path := r.URL.Path var pathLen int if path[len(path)-1] == '/' { pathLen = len(path) - 1 } else { pathLen = len(path) } pathParts := strings.Split(path[1:pathLen], "/") // "events/detail/id" if len(pathParts) < 3 { http.Error(w, "Invalid event id ", http.StatusNotFound) return } eventId, err := strconv.Atoi(pathParts[2]) if err != nil || eventId < 1 { http.Error(w, "Invalid event id "+pathParts[2], http.StatusNotFound) return } event := vc.EventScan(eventId, VcData.Events) var prevEvent, nextEvent *vc.Event = nil, nil for i := event.Id - 1; i > 0; i-- { tmp := vc.EventScan(i, VcData.Events) if tmp != nil && tmp.EventTypeId == event.EventTypeId { prevEvent = tmp break } } prevEventName := "" if prevEvent != nil { prevEventName = strings.Replace(prevEvent.Name, "【New Event】", "", -1) } for i := event.Id + 1; i <= vc.MaxEventId(VcData.Events); i++ { tmp := vc.EventScan(i, VcData.Events) if tmp != nil && tmp.EventTypeId == event.EventTypeId { nextEvent = tmp break } } nextEventName := "" if nextEvent != nil { nextEventName = strings.Replace(nextEvent.Name, "【New Event】", "", -1) } fmt.Fprintf(w, "<html><head><title>%s</title></head><body><h1>%[1]s</h1>\n", event.Name) if event.BannerId > 0 { fmt.Fprintf(w, `<a href="/images/event/largeimage/%[1]d/event_image_en?filename=Banner_%[2]s.png"><img src="/images/event/largeimage/%[1]d/event_image_en" alt="Banner"/></a><br />`, event.BannerId, url.QueryEscape(event.Name)) } if event.TexIdImage > 0 { fmt.Fprintf(w, `<a href="/images/event/largeimage/%[1]d/event_image_en?filename=Banner_%[2]s.png"><img src="/images/event/largeimage/%[1]d/event_image_en" alt="Texture Image" /></a>br />`, event.TexIdImage, url.QueryEscape(event.Name)) } if event.TexIdImage2 > 0 { fmt.Fprintf(w, `<a href="/images/event/largeimage/%[1]d/event_image_en?filename=Banner_%[2]s.png"><img src="/images/event/largeimage/%[1]d/event_image_en" alt="Texture Image 2" /></a><br />`, event.TexIdImage2, url.QueryEscape(event.Name)) } if prevEventName != "" { fmt.Fprintf(w, "<div style=\"float:left\"><a href=\"%d\">%s</a>\n</div>", prevEvent.Id, prevEventName) } if nextEventName != "" { fmt.Fprintf(w, "<div style=\"float:right\"><a href=\"%d\">%s</a>\n</div>", nextEvent.Id, nextEventName) } fmt.Fprintf(w, "<div style=\"clear:both;float:left\">Edit on the <a href=\"https://valkyriecrusade.wikia.com/wiki/%s?action=edit\">wikia</a>\n<br />", strings.Replace(event.Name, "【New Event】", "", -1)) if event.MapId > 0 { fmt.Fprintf(w, "<a href=\"/maps/%d\">Map Information</a>\n<br />", event.MapId) } io.WriteString(w, "<textarea style=\"width:800px;height:760px\">") switch event.EventTypeId { case 1: // archwitch event rtrend := genWikiRankTrend(event) var legendary string var faws string var aws string for _, aw := range event.Archwitches(VcData) { cardMaster := vc.CardScan(aw.CardMasterId, VcData.Cards) if aw.IsLAW() { legendary = cardMaster.Name } else if aw.IsFAW() { faws += "|" + cardMaster.Name + "|Fantasy Archwitch\n" } else { aws += "|" + cardMaster.Name + "|Archwitch\n" } } eventMap := event.Map(VcData) var eHallStart string if eventMap == nil || eventMap.ElementalhallStart.IsZero() || event.EndDatetime.Before(eventMap.ElementalhallStart.Time) { eHallStart = "" } else { eHallStart = eventMap.ElementalhallStart.Format(wikiFmt) } midrewards := "" finalrewards := "" rankReward := "" rr := event.RankRewards(VcData) if rr != nil { mid := rr.MidRewards(VcData) if mid != nil { midCaption := fmt.Sprintf("Mid Rankings<br /><small> Cutoff@ %s (JST)</small>", rr.MidBonusDistributionDate.Format(wikiFmt), ) midrewards = genWikiRewards(mid, midCaption) } finalRewardList := rr.FinalRewards(VcData) finalrewards = genWikiRewards(finalRewardList, "Final Rankings") for _, fr := range finalRewardList { if fr.CardId > 0 { rrCard := vc.CardScan(fr.CardId, VcData.Cards) rankReward = rrCard.Name break } } } fmt.Fprintf(w, getEventTemplate(event.EventTypeId), event.StartDatetime.Format(wikiFmt), // start event.EndDatetime.Format(wikiFmt), // end eHallStart, // E-Hall opening "1", // E-Hall rotation rankReward, // rank reward legendary, // legendary archwitch faws, // Fantasy Archwitch aws, // Regular Archwitch html.EscapeString(strings.Replace(event.Description, "\n", "\n\n", -1)), (midrewards + finalrewards), //rewards rtrend, // Rank trend "", // sub event (Alliance Battle) prevEventName, //Previous event name nextEventName, // next event name ) case 16: // alliance bingo battle fallthrough case 11: // special campaign (Abyssal AW and others) // may just do the THOR event seprately and leave this as just news fallthrough case 13: //Alliance Ultimate Battle fallthrough case 12: // Alliance Duel fallthrough case 10: //Alliance Battle fallthrough default: io.WriteString(w, html.EscapeString(strings.Replace(event.Description, "\n", "\n\n", -1))) } io.WriteString(w, "</textarea></div>") io.WriteString(w, "</body></html>") }
func cardDetailHandler(w http.ResponseWriter, r *http.Request) { path := r.URL.Path var pathLen int if path[len(path)-1] == '/' { pathLen = len(path) - 1 } else { pathLen = len(path) } pathParts := strings.Split(path[1:pathLen], "/") // "cards/detail/id" if len(pathParts) < 3 { http.Error(w, "Invalid card id ", http.StatusNotFound) return } cardId, err := strconv.Atoi(pathParts[2]) if err != nil || cardId < 1 || cardId > len(VcData.Cards) { http.Error(w, "Invalid card id "+pathParts[2], http.StatusNotFound) return } card := vc.CardScan(cardId, VcData.Cards) evolutions := getEvolutions(card) amalgamations := getAmalgamations(evolutions) lastEvo, ok := evolutions["H"] if ok { delete(evolutions, "H") } firstEvo, ok := evolutions["F"] if ok { delete(evolutions, "F") } else { firstEvo, ok = evolutions["0"] if !ok { firstEvo = evolutions["1"] } } var turnOverTo, turnOverFrom *vc.Card if firstEvo.Id > 0 { if firstEvo.TransCardId > 0 { turnOverTo = firstEvo.EvoAccident(VcData.Cards) } else { turnOverFrom = firstEvo.EvoAccidentOf(VcData.Cards) } } var avail string for _, av := range amalgamations { // check to see if this card is the result of an amalgamation resultAmalgFound := false if !resultAmalgFound { for _, ev := range evolutions { if ev.Id == av.FusionCardId { if !strings.Contains(avail, "[[Amalgamation]]") { avail += " [[Amalgamation]]" } resultAmalgFound = true break } } } // look for a self amalgamation if _, ok := evolutions["A"]; !ok { var materialFuseId int for _, ev := range evolutions { switch ev.Id { case av.Material1, av.Material2, av.Material3, av.Material4: materialFuseId = av.FusionCardId } } if materialFuseId > 0 { fuseCard := vc.CardScan(materialFuseId, VcData.Cards) if fuseCard.Name == card.Name { evolutions["A"] = *fuseCard if !strings.Contains(avail, "[[Amalgamation]]") { avail += " [[Amalgamation]]" } } } } if _, ok := evolutions["A"]; ok && resultAmalgFound { break } } skipFirstEvo := false if gevo, ok := evolutions["G"]; ok { skipFirstEvo = gevo.Id == firstEvo.Id } //skipFirstEvo = skipFirstEvo || (firstEvo.Id == lastEvo.Id && firstEvo.Rarity() != "X") //fmt.Fprintf(os.Stdout, "Skip First Evo: %v\n", skipFirstEvo) cardName := card.Name if len(cardName) == 0 { cardName = firstEvo.Image() } fmt.Fprintf(w, "<html><head><title>%s</title></head><body><h1>%[1]s</h1>\n", cardName) fmt.Fprintf(w, "<div>Edit on the <a href=\"https://valkyriecrusade.wikia.com/wiki/%s?action=edit\">wikia</a>\n<br />", cardName) io.WriteString(w, "<textarea readonly=\"readonly\" style=\"width:100%;height:450px\">") if card.IsClosed != 0 { io.WriteString(w, "{{Unreleased}}") } fmt.Fprintf(w, "{{Card\n|element = %s\n", card.Element()) if firstEvo.Id > 0 { skillEvoMod := "" if firstEvo.Rarity()[0:1] == "G" { skillEvoMod = "g" } fmt.Fprintf(w, "|rarity = %s\n", fixRarity(firstEvo.Rarity())) if !skipFirstEvo { io.WriteString(w, printWikiSkill(firstEvo.Skill1(VcData), nil, "")) } skill2 := firstEvo.Skill2(VcData) if skill2 != nil { io.WriteString(w, printWikiSkill(skill2, lastEvo.Skill2(VcData), skillEvoMod+"2")) // print skill 3 if it exists io.WriteString(w, printWikiSkill(firstEvo.Skill3(VcData), nil, skillEvoMod+"3")) } else if lastEvo.Id > 0 { io.WriteString(w, printWikiSkill(lastEvo.Skill2(VcData), nil, skillEvoMod+"2")) // print skill 3 if it exists io.WriteString(w, printWikiSkill(lastEvo.Skill3(VcData), nil, skillEvoMod+"3")) } io.WriteString(w, printWikiSkill(lastEvo.ThorSkill1(VcData), nil, skillEvoMod+"t")) } else { io.WriteString(w, "|rarity = \n|skill = \n|skill lv1 = \n|skill lv10 = \n|procs = \n") } if evo, ok := evolutions["A"]; ok { aSkillName := evo.Skill1Name(VcData) if aSkillName != firstEvo.Skill1Name(VcData) { io.WriteString(w, printWikiSkill(evo.Skill1(VcData), nil, "a")) } if _, ok := evolutions["GA"]; ok { io.WriteString(w, printWikiSkill(evo.Skill1(VcData), nil, "ga")) } } if evo, ok := evolutions["G"]; ok { io.WriteString(w, printWikiSkill(evo.Skill1(VcData), nil, "g")) io.WriteString(w, printWikiSkill(evo.Skill2(VcData), nil, "g2")) io.WriteString(w, printWikiSkill(evo.Skill3(VcData), nil, "g3")) io.WriteString(w, printWikiSkill(evo.ThorSkill1(VcData), nil, "gt")) } //traverse evolutions in order var evokeys []string for k := range evolutions { evokeys = append(evokeys, k) } sort.Strings(evokeys) for i, k := range evokeys { evo := evolutions[k] if i == 0 && skipFirstEvo { continue } fmt.Fprintf(w, "|cost %[1]s = %[2]d\n|atk %[1]s = %[3]d / %s\n|def %[1]s = %[5]d / %s\n|soldiers %[1]s = %[7]d / %s\n", strings.ToLower(k), evo.DeckCost, evo.DefaultOffense, maxStatAtk(evo, len(evolutions)), evo.DefaultDefense, maxStatDef(evo, len(evolutions)), evo.DefaultFollower, maxStatFollower(evo, len(evolutions))) } fmt.Fprintf(w, "|description = %s\n|friendship = %s\n", html.EscapeString(card.Description(VcData)), html.EscapeString(strings.Replace(card.Friendship(VcData), "\n", "<br />", -1))) login := card.Login(VcData) if len(strings.TrimSpace(login)) > 0 { fmt.Fprintf(w, "|login = %s\n", html.EscapeString(strings.Replace(login, "\n", "<br />", -1))) } fmt.Fprintf(w, "|meet = %s\n|battle start = %s\n|battle end = %s\n|friendship max = %s\n|friendship event = %s\n", html.EscapeString(strings.Replace(card.Meet(VcData), "\n", "<br />", -1)), html.EscapeString(strings.Replace(card.BattleStart(VcData), "\n", "<br />", -1)), html.EscapeString(strings.Replace(card.BattleEnd(VcData), "\n", "<br />", -1)), html.EscapeString(strings.Replace(card.FriendshipMax(VcData), "\n", "<br />", -1)), html.EscapeString(strings.Replace(card.FriendshipEvent(VcData), "\n", "<br />", -1))) var awakenInfo *vc.CardAwaken for _, val := range VcData.Awakenings { if lastEvo.Id == val.BaseCardId { awakenInfo = &val break } } if awakenInfo != nil { fmt.Fprintf(w, "|awaken chance = %d\n|awaken orb = %d\n|awaken l = %d\n|awaken m = %d\n|awaken s = %d\n", awakenInfo.Percent, awakenInfo.Material1Count, awakenInfo.Material2Count, awakenInfo.Material3Count, awakenInfo.Material4Count, ) } var aw *vc.Archwitch for _, evo := range evolutions { if nil != evo.Archwitch(VcData) { aw = evo.Archwitch(VcData) break } } if aw != nil { for _, like := range aw.Likeability(VcData) { fmt.Fprintf(w, "|likeability %d = %s\n", like.Friendship, html.EscapeString(strings.Replace(like.Likability, "\n", "<br />", -1)), ) } } if turnOverFrom != nil { fmt.Fprintf(w, "|turnoverfrom = %s\n", turnOverFrom.Name) } else if turnOverTo != nil { fmt.Fprintf(w, "|turnoverto = %s\n", turnOverTo.Name) fmt.Fprintf(w, "|availability = %s\n", avail) } else { fmt.Fprintf(w, "|availability = %s\n", avail) } io.WriteString(w, "}}") //Write out amalgamations here if len(amalgamations) > 0 { io.WriteString(w, "\n==''[[Amalgamation]]''==\n") for _, v := range amalgamations { mats := v.Materials(VcData) l := len(mats) fmt.Fprintf(w, "{{Amalgamation|matcount = %d\n|name 1 = %s|rarity 1 = %s\n|name 2 = %s|rarity 2 = %s\n|name 3 = %s|rarity 3 = %s\n", l-1, mats[0].Name, mats[0].Rarity(), mats[1].Name, mats[1].Rarity(), mats[2].Name, mats[2].Rarity()) if l > 3 { fmt.Fprintf(w, "|name 4 = %s|rarity 4 = %s\n", mats[3].Name, mats[3].Rarity()) } if l > 4 { fmt.Fprintf(w, "|name 5 = %s|rarity 5 = %s\n", mats[4].Name, mats[4].Rarity()) } io.WriteString(w, "}}\n") } } io.WriteString(w, "</textarea></div>") // show images here io.WriteString(w, "<div style=\"float:left\">") for _, k := range evokeys { evo := evolutions[k] fmt.Fprintf(w, `<div style="float: left; margin: 3px"><a href="/images/cardthumb/%s"><img src="/images/cardthumb/%[1]s"/></a><br />%s : %s☆</div>`, evo.Image(), evo.Name, k, ) } io.WriteString(w, "<div style=\"clear: both\">") for _, k := range evokeys { evo := evolutions[k] if _, err := os.Stat(vcfilepath + "/card/hd/" + evo.Image()); err == nil { fmt.Fprintf(w, `<div style="float: left; margin: 3px"><a href="/images/cardHD/%s.png"><img src="/images/cardHD/%[1]s.png"/></a><br />%s : %s☆</div>`, evo.Image(), evo.Name, k) } else if _, err := os.Stat(vcfilepath + "/card/md/" + evo.Image()); err == nil { fmt.Fprintf(w, `<div style="float: left; margin: 3px"><a href="/images/card/%s.png"><img src="/images/card/%[1]s.png"/></a><br />%s : %s☆</div>`, evo.Image(), evo.Name, k) } else { fmt.Fprintf(w, `<div style="float: left; margin: 3px"><a href="/images/cardSD/%s.png"><img src="/images/cardSD/%[1]s.png"/></a><br />%s : %s☆</div>`, evo.Image(), evo.Name, k) } } io.WriteString(w, "</div>") io.WriteString(w, "</body></html>") }
func getEvolutions(card *vc.Card) map[string]vc.Card { ret := make(map[string]vc.Card) // handle cards like Chimrey and Time Traveler (enemy) if card.CardCharaId < 1 { ret["0"] = *card ret["F"] = *card ret["H"] = *card return ret } getAmalBaseCard := func(card *vc.Card) map[string]vc.Card { if card.IsAmalgamation(VcData.Amalgamations) { // check for a base amalgamation with the same name // if there is one, use that for the base card for _, amal := range card.Amalgamations(VcData) { if card.Id == amal.FusionCardId { // material 1 ac := vc.CardScan(amal.Material1, VcData.Cards) if ac.Id != card.Id && ac.Name == card.Name { return getEvolutions(ac) } // material 2 ac = vc.CardScan(amal.Material2, VcData.Cards) if ac.Id != card.Id && ac.Name == card.Name { return getEvolutions(ac) } // material 3 ac = vc.CardScan(amal.Material3, VcData.Cards) if ac != nil && ac.Id != card.Id && ac.Name == card.Name { return getEvolutions(ac) } // material 4 ac = vc.CardScan(amal.Material4, VcData.Cards) if ac != nil && ac.Id != card.Id && ac.Name == card.Name { return getEvolutions(ac) } } } } return nil } // find the lowest evolution and work from there. if card.Rarity()[0] == 'G' { bc := card.AwakensFrom(VcData) if bc != nil { // look for self amalgamation (like sulis) amalBaseCard := getAmalBaseCard(bc) if amalBaseCard != nil { return amalBaseCard } return getEvolutions(bc) } } else if card.EvolutionRank != 0 { // check for a previous evolution for _, c := range VcData.Cards { if c.EvolutionCardId == card.Id { return getEvolutions(&c) } } } else { // check for self amalgamation (like sulis) amalBaseCard := getAmalBaseCard(card) if amalBaseCard != nil { return amalBaseCard } } // get the actual evolution list ret[strconv.Itoa(card.EvolutionRank)] = *card ret["F"] = *card nextId := card.EvolutionCardId lastEvo := card for nextId > 1 { nextCard := vc.CardScan(nextId, VcData.Cards) // verify that we haven't switched characters like Terra -> Rhea if card.CardCharaId == nextCard.CardCharaId { nextEvo := strconv.Itoa(nextCard.EvolutionRank) ret[nextEvo] = *nextCard lastEvo = nextCard } nextId = nextCard.EvolutionCardId } ret["H"] = *lastEvo // check if the card has a known awakening: cardg := lastEvo.AwakensTo(VcData) // this doesn't mean that the card has an awakening, it just makes it easier to find if cardg != nil { ret["G"] = *cardg } else { // look for the awakening the hard way now, based on the character id gs := 0 for _, val := range VcData.Cards { if card.CardCharaId == val.CardCharaId && val.Rarity()[0] == 'G' { if gs == 0 { ret["G"] = val } else { ret["G"+strconv.Itoa(gs)] = val } gs++ } } } return ret }