func (s *rankStrategy) NextAd(client *models.Client) (*models.Ad, log.ServerError) { isNew := s.isNewRand.Float32() < s.dbConfig.NewTrafficPercentage() ad, _ := s.getNewAd(isNew, client.Info) if ad != nil { return ad, nil } adIDs, ad, err := s.getAdIDs(isNew, client.Info) if ad != nil { return ad, nil } else if err != nil { return nil, log.New(http.StatusNotFound, notFoundDesc, err) } if adIDs == nil { return nil, log.NewError(http.StatusNotFound, notFoundDesc) } viewsPerAd, conversionsPerAd := s.getStatistics(adIDs) rankPerAd, totalRank := calculateRanks(viewsPerAd, conversionsPerAd) adID := s.chooseAd(adIDs, rankPerAd, totalRank) ad, err = s.db.Ads().GetAdByID(&adID) if err != nil { return nil, log.New(http.StatusNotFound, notFoundDesc, err) } return ad, nil }
func getStatistic(id string, c statistic.StatisticsCollection) (*statistic.Statistic, log.ServerError) { if id == "" { return nil, log.NewError(http.StatusBadRequest, "id is not specified") } return c.GetById(&id) }
func parseRequiredInfo(query url.Values) (*ClientInfo, log.ServerError) { os := query.Get("os") if os == "" { return nil, log.NewError(http.StatusBadRequest, "os is not specified") } osVersion := query.Get("osVersion") if osVersion == "" { return nil, log.NewError(http.StatusBadRequest, "os version is not specified") } deviceModel := query.Get("deviceModel") if deviceModel == "" { return nil, log.NewError(http.StatusBadRequest, "device model is not specified") } return &ClientInfo{ OS: os, OSVersion: osVersion, DeviceModel: deviceModel, }, nil }
func (c *statisticsCollection) GetById(id *string) (*Statistic, log.ServerError) { if !bson.IsObjectIdHex(*id) { return nil, log.NewError(http.StatusBadRequest, "provided value is not valid object id") } var result Statistic err := c.FindId(bson.ObjectIdHex(*id)).One(&result) if err != nil { return nil, log.NewInternalError(err) } return &result, nil }
func (c *appsCollection) GetApp(r *http.Request) (*App, log.ServerError) { token := r.URL.Query().Get("appToken") if token == "" { return nil, log.NewError(http.StatusBadRequest, "App token is not specified") } var app App err := c.Find(&bson.M{"appToken": token}).One(&app) if err != nil { return nil, log.New(http.StatusForbidden, fmt.Sprintf("app token %v is not found", token), err) } return &app, nil }
func (c *controller) View(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Header().Set("Content-Type", "application/json; charset=utf-8") database := c.app.Database() apps := database.Apps() t := getAdType(r) if t == "" { c.writeError(w, log.NewError(http.StatusBadRequest, "type of request ad is not specified")) return } devApp, err := apps.GetApp(r) if err != nil { c.writeError(w, err) return } client, err := models.GetClient(c.app.GeoIP(), r) if err != nil { c.writeError(w, err) return } ad, err := c.strategy.NextAd(client) if err != nil { c.writeError(w, err) return } viewId := database.Views().SaveStatistic(ad.ID, devApp.ID, client) adInfo := getInfo(t, viewId, ad, r) jsonAd, e := json.Marshal(adInfo) if e != nil { c.writeError(w, log.NewInternalError(e)) return } w.Write(jsonAd) }