package pricing import ( "errors" "fmt" "strconv" "time" ) type BuyingStrategy int const ( UNLIMITED BuyingStrategy = iota SUBSCRIPTION PAY_PER_USE ) type Strategy interface { GetStrategy() string GetStrategyValue() int } type TimePricingStrategy int const ( ONCE TimePricingStrategy = iota PER_SECOND PER_MINUTE PER_HOUR PER_DAY PER_WEEK PER_MONTH ) func (t TimePricingStrategy) GetStrategy() string { return [...]string{"ONCE", "PER_SECOND", "PER_MINUTE", "PER_HOUR", "PER_DAY", "PER_WEEK", "PER_MONTH"}[t] } func (t TimePricingStrategy) GetStrategyValue() int { return int(t) } func getAverageTimeInSecond(averageTimeInSecond float64, start time.Time, end *time.Time) float64 { now := time.Now() after := now.Add(time.Duration(averageTimeInSecond) * time.Second) fromAverageDuration := after.Sub(now).Seconds() var tEnd time.Time if end == nil { tEnd = start.Add(1 * time.Hour) } else { tEnd = *end } fromDateDuration := tEnd.Sub(start).Seconds() if fromAverageDuration > fromDateDuration { return fromAverageDuration } return fromDateDuration } func BookingEstimation(t TimePricingStrategy, price float64, locationDurationInSecond float64, start time.Time, end *time.Time) (float64, error) { locationDurationInSecond = getAverageTimeInSecond(locationDurationInSecond, start, end) priceStr := fmt.Sprintf("%v", price) p, err := strconv.ParseFloat(priceStr, 64) if err != nil { return 0, err } switch t { case ONCE: return p, nil case PER_HOUR: return p * float64(locationDurationInSecond/3600), nil case PER_MINUTE: return p * float64(locationDurationInSecond/60), nil case PER_SECOND: return p * locationDurationInSecond, nil case PER_DAY: return p * float64(locationDurationInSecond/86400), nil case PER_WEEK: return p * float64(locationDurationInSecond/604800), nil case PER_MONTH: return p * float64(locationDurationInSecond/2592000), nil } return 0, errors.New("Pricing strategy not found") } // hmmmm type PricingStrategy[T Strategy] struct { Price float64 `json:"Price" bson:"Price" default:"0"` // Price is the Price of the pricing BuyingStrategy BuyingStrategy `json:"buying_strategy" bson:"buying_strategy" default:"0"` // BuyingStrategy is the buying strategy of the pricing TimePricingStrategy TimePricingStrategy `json:"time_pricing_strategy" bson:"time_pricing_strategy" default:"0"` // TimePricingStrategy is the time pricing strategy of the pricing OverrideStrategy T `json:"override_strategy" bson:"override_strategy" default:"-1"` // Modulation is the modulation of the pricing } func (p PricingStrategy[T]) SetStrategy(Price float64, BuyingStrategy BuyingStrategy, TimePricingStrategy TimePricingStrategy) error { if TimePricingStrategy == ONCE && (BuyingStrategy != UNLIMITED || BuyingStrategy != PAY_PER_USE) { return errors.New("time pricing strategy can only be set to ONCE if buying strategy is UNLIMITED or PAY_PER_USE") } else if BuyingStrategy == SUBSCRIPTION && (TimePricingStrategy == ONCE) { return errors.New("subscription duration in second must be set if buying strategy is SUBSCRIPTION") } p.Price = Price p.BuyingStrategy = BuyingStrategy p.TimePricingStrategy = TimePricingStrategy return nil } func (p PricingStrategy[T]) SetSpecificPerUseStrategy(strategy T) error { if p.BuyingStrategy == UNLIMITED { return errors.New("UNLIMITED buying strategy can't have a specific strategy, Price is set on buying") } p.OverrideStrategy = strategy return nil } // QUANTITY can be how many of gb core per example func (p PricingStrategy[T]) GetPrice(amountOfData float64, bookingTimeDuration float64, start time.Time, end *time.Time) (float64, error) { if p.BuyingStrategy == SUBSCRIPTION { return BookingEstimation(p.GetTimePricingStrategy(), p.Price*float64(amountOfData), bookingTimeDuration, start, end) } else if p.BuyingStrategy == UNLIMITED { return p.Price, nil } return p.Price * float64(amountOfData), nil } func (p PricingStrategy[T]) GetBuyingStrategy() BuyingStrategy { return p.BuyingStrategy } func (p PricingStrategy[T]) GetTimePricingStrategy() TimePricingStrategy { return p.TimePricingStrategy } func (p PricingStrategy[T]) GetOverrideStrategy() T { return p.OverrideStrategy }