Преглед на файлове

epic: free = element price.discountPrice==0 (offer discountSetting unreliable); deals from fmtPrice

Paul Klumpp преди 3 дни
родител
ревизия
c27926d0b9
променени са 1 файла, в които са добавени 25 реда и са изтрити 15 реда
  1. 25 15
      internal/epic/client.go

+ 25 - 15
internal/epic/client.go

@@ -75,8 +75,11 @@ type element struct {
 	} `json:"seller"`
 	Price struct {
 		TotalPrice struct {
-			FmtPrice struct {
+			DiscountPrice int `json:"discountPrice"` // current price in cents; 0 = free
+			OriginalPrice int `json:"originalPrice"` // list price in cents
+			FmtPrice      struct {
 				OriginalPrice string `json:"originalPrice"`
+				DiscountPrice string `json:"discountPrice"` // formatted current price
 			} `json:"fmtPrice"`
 		} `json:"totalPrice"`
 	} `json:"price"`
@@ -150,13 +153,17 @@ func buildGames(el element, kind string, windows []offer, keep func(offer) bool,
 		slug = el.CatalogNs.Mappings[0].PageSlug
 	}
 	for _, o := range windows {
-		if !keep(o) {
-			continue
-		}
-		if freeOnly && (o.Discount.DiscountPrice != 0 || o.Discount.DiscountPercentage != 100) {
-			// DiscountPrice alone is not enough: some offers omit the price
-			// field (null → 0) while discountPercentage reveals them as
-			// partial discounts (e.g. Castlevania, Oct 2026).
+		// Semantics verified against the live API (Oct 2026): the ONLY
+		// reliable free indicator is el.price.totalPrice.discountPrice == 0
+		// (the element's current price). The offer's discountSetting fields
+		// are unreliable: discountPrice is null (=0 in Go) even for
+		// non-free offers, and discountPercentage carries inconsistent
+		// values (e.g. Castlevania 40 while the store shows −60 %).
+		//   - freeOnly:  element current price must be 0.
+		//   - deals:     current price > 0; discount display from
+		//                fmtPrice (original → current).
+		currentlyFree := el.Price.TotalPrice.DiscountPrice == 0
+		if freeOnly != currentlyFree {
 			continue
 		}
 		g := game.Game{
@@ -172,13 +179,16 @@ func buildGames(el element, kind string, windows []offer, keep func(offer) bool,
 			EndDate:     o.EndDate,
 			PriceFmt:    el.Price.TotalPrice.FmtPrice.OriginalPrice,
 		}
-		if o.Discount.DiscountPercentage > 0 && o.Discount.DiscountPercentage < 100 {
-			g.DiscountPct = o.Discount.DiscountPercentage
-			// discountPercentage here is the *discount* (e.g. 40 = −40 %),
-			// not the remaining share. discountPrice (cents) may be absent
-			// (null → 0) on such offers; then show percent only.
-			if o.Discount.DiscountPrice > 0 {
-				g.FinalPriceFmt = fmt.Sprintf("%d.%02d €", o.Discount.DiscountPrice/100, o.Discount.DiscountPrice%100)
+		if !currentlyFree {
+			g.Kind = "deal"
+			g.FinalPriceFmt = el.Price.TotalPrice.FmtPrice.DiscountPrice
+			if orig := el.Price.TotalPrice.FmtPrice.OriginalPrice; orig != "" {
+				g.PriceFmt = orig
+			}
+			// Compute the discount percent from the prices (cents).
+			if cur := el.Price.TotalPrice.DiscountPrice; cur > 0 && cur < el.Price.TotalPrice.OriginalPrice {
+				orig := el.Price.TotalPrice.OriginalPrice
+				g.DiscountPct = (orig - cur) * 100 / orig
 			}
 		}
 		if i := indexOfID(games, g.ID); i >= 0 {