@@ -2,6 +2,7 @@ package misc
import (
"math"
"reflect"
"sync"
"time"
@@ -24,8 +25,9 @@ const (
AveragePickupTimeNormalTime = 10.0 //分钟
BadCommentOrderNormalRatio = 0.2
UnfinishOrderNormalRatio = 1.0
StoreRangeGoodRadius = 200 0 //米
StoreRangeBadRadius = 100 0 //米
StoreRangeGoodRadius = 2. 0 //千 米
StoreRangeBadRadius = 1. 0 //千 米
SaleSkuPriceRatio = 90 //百分比
)
var (
@@ -46,28 +48,32 @@ type StoreScoreDataWrapper struct {
locker sync . RWMutex
}
func ( s * StoreScoreDataWrapper ) AppendData ( data * model . StoreScore ) {
s . locker . Lock ( )
defer s . locker . Unlock ( )
s . storeScoreData [ data . StoreID ] = data
}
func ( s * StoreScoreDataWrapper ) GetData ( storeID int ) * model . StoreScore {
s . locker . RLock ( )
defer s . locker . RUnlock ( )
return s . storeScoreData [ storeID ]
}
func ( s * StoreScoreDataWrapper ) InitData ( ) {
s . storeScoreData = make ( map [ int ] * model . StoreScore )
}
func ( s * StoreScoreDataWrapper ) SetData ( storeID int , valueName string , value int ) {
s . locker . Lock ( )
defer s . locker . Unlock ( )
data := s . storeScoreData [ storeID ]
if data == nil {
data = & model . StoreScore { }
data . StoreID = storeID
s . storeScoreData [ storeID ] = data
}
valueInfo := reflect . ValueOf ( data ) . Elem ( )
valueInfo . FieldByName ( valueName ) . SetInt ( int64 ( value ) )
}
func GetOpenTime ( opTimeList [ ] int16 ) ( opTime float64 ) {
opTime = 0
for index , _ := range opTimeList {
if index % 2 == 1 {
diff := opTimeList [ index ] - opTimeList [ index - 1 ]
op Time + = float64 ( diff ) / 100
endTime := opTimeList [ index ]
start Time : = opTimeList [ index - 1 ]
diffHour := float64 ( endTime / 100 - startTime / 100 )
diffMin := float64 ( endTime % 100 - startTime % 100 ) / 60
opTime += diffHour + diffMin
}
}
return opTime
@@ -79,27 +85,23 @@ func ScoreStoreOpenTime(storeList []*cms.StoreExt) {
storeID := storeInfo . ID
storeStatus := storeInfo . Status
isStoreOpen := storeStatus == model . StoreStatusOpened
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
storeScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
}
for _ , storeMap := range storeInfo . StoreMaps {
vendorStoreStatus := int ( utils . MustInterface2Int64 ( storeMap [ "status" ] ) )
isVendorStoreOpen := vendorStoreStatus == model . StoreStatusOpened
opTimeList := storeInfo . GetOpTimeList ( )
if len ( opTimeList ) > 0 && isStoreOpen && isVendorStoreOpen {
finalScore := 0
opTime := GetOpenTime ( opTimeList )
if opTime >= StoreOpenTimeNormalTime {
storeScoreData . StoreOpenTim e = ItemScore
finalScor e = ItemScore
} else {
decScore := int ( math . Round ( StoreOpenTimeNormalTime - opTime ) )
storeScoreData . StoreOpenTim e = ItemScore - decScore
if storeScoreData . StoreOpenTim e < 0 {
storeScoreData . StoreOpenTim e = 0
finalScor e = ItemScore - decScore
if finalScor e < 0 {
finalScor e = 0
}
}
storeScoreDataWrapper . SetData ( storeID , "StoreOpenTime" , finalScore )
}
}
}
@@ -109,25 +111,23 @@ func ScoreStoreOpenTime(storeList []*cms.StoreExt) {
func ScoreSaleSkuCount ( ctx * jxcontext . Context , storeList [ ] * cms . StoreExt ) {
for _ , storeInfo := range storeList {
storeID := storeInfo . ID
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
store ScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . Append Data( storeScoreData )
}
jxSkuInfoData , _ := cms . GetStoreSkus ( ctx , storeID , [ ] int { } , true , "" , true , map [ string ] interface { } { } , 0 , - 1 )
saleSkuCount : = 0
for _ , value := range jxSkuInfoData . SkuNames {
for _ , skuInfo := range value . Skus2 {
saleStatus := jxutils . MergeSkuStatus ( skuInfo . SkuStatus , skuInfo . StoreSkuStatus )
if saleStatus == model . SkuStatusNormal {
saleSkuCount ++
jxSkuInfoData , err := cms . GetStoreSkus ( ctx , storeID , [ ] int { } , true , "" , true , map [ string ] interface { } { } , 0 , - 1 )
if err == nil && len ( jxSkuInfoData . SkuNames ) > 0 {
final Score : = 0
saleSkuCount : = 0
for _ , value := range jxSkuInfo Data. SkuNames {
for _ , skuInfo := range value . Skus2 {
saleStatus := jxutils . MergeSkuStatus ( skuInfo . SkuStatus , skuInfo . StoreSkuStatus )
if saleStatus = = model . SkuStatusNormal {
saleSkuCount ++
}
}
}
}
storeScoreData . SaleSkuCount = int ( math . Round ( float64 ( saleSkuCount ) * SaleSkuScorePerUnit ) )
if storeScoreData . SaleSkuCount > ItemScore {
storeScoreData . SaleSkuCount = ItemScore
finalScore = int ( math . Round ( float64 ( saleSkuCount ) * SaleSkuScorePerUnit ) )
if finalScore > ItemScore {
finalScore = ItemScore
}
storeScoreDataWrapper . SetData ( storeID , "SaleSkuCount" , finalScore )
}
}
}
@@ -136,15 +136,10 @@ func ScoreSaleSkuCount(ctx *jxcontext.Context, storeList []*cms.StoreExt) {
func ScoreAveragePickupTime ( storeList [ ] * cms . StoreExt ) {
for _ , storeInfo := range storeList {
storeID := storeInfo . ID
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
storeScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
}
db := dao . GetDB ( )
orderList , err := dao . GetDailyFinishOrderList ( db , storeID )
if err = = nil {
orderListCount : = len ( orderList )
if err == nil && orderListCount > 0 {
totalScore := 0
for _ , value := range orderList {
statusTime := value . StatusTime . Unix ( )
@@ -160,7 +155,8 @@ func ScoreAveragePickupTime(storeList []*cms.StoreExt) {
totalScore += tempScore
}
}
storeScoreData . AveragePickupTim e = totalScore / len ( orderList)
finalScor e : = totalScore / orderListCount
storeScoreDataWrapper . SetData ( storeID , "AveragePickupTime" , finalScore )
}
}
}
@@ -169,24 +165,22 @@ func ScoreAveragePickupTime(storeList []*cms.StoreExt) {
func ScoreBadCommentOrder ( storeList [ ] * cms . StoreExt ) {
for _ , storeInfo := range storeList {
storeID := storeInfo . ID
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
storeScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
}
db := dao . GetDB ( )
badCommentOrderCount , _ := dao . GetDailyBadCommentOrderCount ( db , storeID )
finishOrderCount , _ := dao . GetDailyFinishOrderCount ( db , storeID )
badCommentOrderRatio := float64 ( badComment OrderCount) * 10 0 / float64 ( finishOrderCount )
if badCommentOrderRatio < = BadCommentOrderNormalRatio {
storeScoreData . B adCommentOrder = ItemScore
} else {
dec Score : = int ( math . Round ( ( badCommentOrderRatio - BadCommentOrderNormalRatio ) / 0.1 ) )
storeScoreData . BadCommentOrder = ItemScore - decScore
if storeScoreData . BadCommentOrder < 0 {
storeScoreData . BadCommentOrder = 0
if finish OrderCount > 0 {
finalScore : = 0
badCommentOrderRatio := float64 ( b adCommentOrderCount ) * 100 / float64 ( finishOrderCount )
if badCommentOrderRatio <= BadCommentOrderNormalRatio {
final Score = ItemScore
} else {
decScore := int ( math . Round ( ( badCommentOrderRatio - BadCommentOrderNormalRatio ) / 0.1 ) )
finalScore = ItemScore - decScore
if finalScore < 0 {
finalScore = 0
}
}
storeScoreDataWrapper . SetData ( storeID , "BadCommentOrder" , finalScore )
}
}
}
@@ -195,24 +189,22 @@ func ScoreBadCommentOrder(storeList []*cms.StoreExt) {
func ScoreUnfinishOrder ( storeList [ ] * cms . StoreExt ) {
for _ , storeInfo := range storeList {
storeID := storeInfo . ID
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
storeScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
}
db := dao . GetDB ( )
unFinishOrderCount , _ := dao . GetDailyUnFinishOrderCount ( db , storeID )
finishOrderCount , _ := dao . GetDailyFinishOrderCount ( db , storeID )
unfinishOrderRatio := float64 ( unF inishOrderCount) * 10 0 / float64 ( finishOrderCount )
if unfinishOrderRatio < = UnfinishOrderNormalRatio {
storeScoreData . Unf inishOrder = ItemScore
} else {
dec Score : = int ( math . Round ( ( unfinishOrderRatio - UnfinishOrderNormalRatio ) / 5 ) )
storeScoreData . UnfinishOrder = ItemScore - decScore
if storeScoreData . UnfinishOrder < 0 {
storeScoreData . UnfinishOrder = 0
if f inishOrderCount > 0 {
finalScore : = 0
unfinishOrderRatio := float64 ( unF inishOrderCount ) * 100 / float64 ( finishOrderCount )
if unfinishOrderRatio <= UnfinishOrderNormalRatio {
final Score = ItemScore
} else {
decScore := int ( math . Round ( ( unfinishOrderRatio - UnfinishOrderNormalRatio ) / 5 ) )
finalScore = ItemScore - decScore
if finalScore < 0 {
finalScore = 0
}
}
storeScoreDataWrapper . SetData ( storeID , "UnfinishOrder" , finalScore )
}
}
}
@@ -226,17 +218,12 @@ func ScoreAbsentGoodsOrder(storeList []*cms.StoreExt) {
func ScorePromotionSku ( storeList [ ] * cms . StoreExt ) {
for _ , storeInfo := range storeList {
storeID := storeInfo . ID
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
storeScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
}
db := dao . GetDB ( )
beginTime := time . Now ( )
endTime := time . Now ( )
actStoreSkuList , err := dao . GetEffectiveActStoreSkuInfo ( db , - 1 , [ ] int { } , [ ] int { storeID } , [ ] int { } , beginTime , endTime )
if err == nil {
if err == nil && len ( actStoreSkuList ) > 0 {
finalScore := 0
actStoreSkuMap := make ( map [ int ] int )
for _ , value := range actStoreSkuList {
if value . Type != model . ActSkuFake {
@@ -245,14 +232,15 @@ func ScorePromotionSku(storeList []*cms.StoreExt) {
}
promotionSkuCount := len ( actStoreSkuMap )
if promotionSkuCount >= PromotionSkuNormalCount {
storeScoreData . PromotionSku = ItemScore
finalScore = ItemScore
} else {
decScore := ( PromotionSkuNormalCount - promotionSkuCount ) / 2
storeScoreData . PromotionSku = ItemScore - decScore
if storeScoreData . PromotionSku < 0 {
storeScoreData . PromotionSku = 0
finalScore = ItemScore - decScore
if finalScore < 0 {
finalScore = 0
}
}
storeScoreDataWrapper . SetData ( storeID , "PromotionSku" , finalScore )
}
}
}
@@ -261,15 +249,10 @@ func ScorePromotionSku(storeList []*cms.StoreExt) {
func ScoreFullVendor ( storeList [ ] * cms . StoreExt ) {
fullVendorCount := len ( fullVendorList )
for _ , storeInfo := range storeList {
finalScore := 0
storeID := storeInfo . ID
storeStatus := storeInfo . Status
isStoreOpen := storeStatus == model . StoreStatusOpened
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
storeScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
}
count := 0
for _ , storeMap := range storeInfo . StoreMaps {
vendorStoreStatus := int ( utils . MustInterface2Int64 ( storeMap [ "status" ] ) )
@@ -280,11 +263,12 @@ func ScoreFullVendor(storeList []*cms.StoreExt) {
}
}
if count == fullVendorCount {
storeScoreData . FullVendor = ItemScore
finalScore = ItemScore
} else {
decScore := ( fullVendorCount - count ) * 2
storeScoreData . FullVendor = ItemScore - decScore
finalScore = ItemScore - decScore
}
storeScoreDataWrapper . SetData ( storeID , "FullVendor" , finalScore )
}
}
@@ -302,42 +286,39 @@ func CalcPolygonArea(points [][2]float64) (area float64) {
//经营范围面积大于半径2km的圆得满分10分, 低于1km得分0
func ScoreStoreRange ( storeList [ ] * cms . StoreExt ) {
for _ , storeInfo := range storeList {
finalScore := 0
storeID := storeInfo . ID
storeScoreData := storeScoreDataWrapper . GetData ( storeID )
if storeScoreData == nil {
storeScoreData = & model . StoreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
}
if storeInfo . DeliveryRangeType == model . DeliveryRangeTypePolygon {
points := jxutils . CoordinateStr2Points ( storeInfo . DeliveryRange )
area := CalcPolygonArea ( points )
goodArea := math . Pi * StoreRangeGoodRadius * StoreRangeGoodRadius
badArea := math . Pi * StoreRangeBadRadius * StoreRangeBadRadius
if area >= goodArea {
storeScoreData . StoreRang e = ItemScore
finalScor e = ItemScore
} else if area <= badArea {
storeScoreData . StoreRang e = 0
finalScor e = 0
} else {
diff := float64 ( goodArea - area )
diff := goodArea - area
ratio := float64 ( ItemScore ) / ( goodArea - badArea )
storeScoreData . StoreRang e = ItemScore - int ( math . Round ( diff * ratio ) )
finalScor e = ItemScore - int ( math . Round ( diff * ratio ) )
}
} else if storeInfo . DeliveryRangeType == model . DeliveryRangeTypeRadius {
deliveryRadius := utils . Str2In t64WithDefault ( storeInfo . DeliveryRange , 0 )
deliveryRadius := utils . Str2Floa t64WithDefault ( storeInfo . DeliveryRange , 0 )
if deliveryRadius >= StoreRangeGoodRadius {
storeScoreData . StoreRang e = ItemScore
finalScor e = ItemScore
} else if deliveryRadius <= StoreRangeBadRadius {
storeScoreData . StoreRang e = 0
finalScor e = 0
} else {
diff := float64 ( StoreRangeGoodRadius - deliveryRadius )
diff := StoreRangeGoodRadius - deliveryRadius
ratio := float64 ( ItemScore ) / ( StoreRangeGoodRadius - StoreRangeBadRadius )
storeScoreData . StoreRang e = ItemScore - int ( math . Round ( diff * ratio ) )
finalScor e = ItemScore - int ( math . Round ( diff * ratio ) )
}
}
storeScoreDataWrapper . SetData ( storeID , "StoreRange" , finalScore )
}
}
//得到距离某个门店多少KM内的所有门店信息
func GetRangeStoreList ( storeID int , lng , lat , checkDist float64 , storeList [ ] * cms . StoreExt ) ( outStoreList [ ] * cms . StoreExt ) {
for _ , storeInfo := range storeList {
if storeInfo . ID == storeID {
@@ -353,6 +334,7 @@ func GetRangeStoreList(storeID int, lng, lat, checkDist float64, storeList []*cm
return outStoreList
}
//得到所有门店的商品
func GetAllStoreSkus ( ctx * jxcontext . Context , storeList [ ] * cms . StoreExt ) {
allStoreSkus = make ( map [ int ] map [ int ] * cms . StoreSkuNameExt )
for _ , storeInfo := range storeList {
@@ -375,21 +357,64 @@ func ClearAllStoreSkus() {
allStoreSkus = nil
}
//得到所有门店的商品, map[int]*cms.StoreSkuNamesInfo
//得到距离某个门店5KM内的所有门店信息
//得到给定门店列表里的同一SkuID商品的平均价格
func GetStoreSkusAveragePrice ( storeList [ ] * cms . StoreExt ) map [ int ] int {
skusTotalPrice := make ( map [ int ] int )
skusCount := make ( map [ int ] int )
skusAveragePrice := make ( map [ int ] int )
for _ , storeInfo := range storeList {
storeID := storeInfo . ID
for _ , value := range allStoreSkus [ storeID ] {
skuID := value . Skus2 [ 0 ] . SkuID
skuPrice := value . Skus2 [ 0 ] . BindPrice
skusTotalPrice [ skuID ] += skuPrice
skusCount [ skuID ] ++
}
}
for id , totalPrice := range skusTotalPrice {
skusAveragePrice [ id ] = int ( math . Round ( float64 ( totalPrice ) / float64 ( skusCount [ id ] ) ) )
}
return skusAveragePrice
}
func GetSkusCountLessEqualAvgPrice ( storeID int , skusAveragePrice map [ int ] int ) ( count int ) {
for _ , value := range allStoreSkus [ storeID ] {
skuID := value . Skus2 [ 0 ] . SkuID
skuPrice := value . Skus2 [ 0 ] . BindPrice
skuAvgPrice := skusAveragePrice [ skuID ]
if skuPrice <= skuAvgPrice {
count ++
}
}
return count
}
//可售商品价格在附近5km内门店比较, 价格低于等于平均值的商品数占90%以上满分10分, 比例每降低10%减1分, 100%超标得0分
func ScoreSaleSkuPrice ( ctx * jxcontext . Context , storeList [ ] * cms . StoreExt ) {
GetAllStoreSkus ( ctx , storeList )
for _ , storeInfo := range storeList {
finalScore := 0
storeID := storeInfo . ID
s toreScoreData := storeScoreDataWrapper . GetData ( storeID )
if s toreScoreData == nil {
stor eSc oreData = & model . S toreScore { }
storeScoreData . StoreID = storeID
storeScoreDataWrapper . AppendData ( storeScoreData )
totalCount := len ( allStoreSkus [ storeID ] )
if totalCount > 0 {
rang eSt oreList : = GetRangeStoreList ( storeID , s toreInfo . FloatLng , storeInfo . FloatLat , 5 , storeList )
skusAveragePrice : = GetStoreSkusAveragePrice ( rangeStoreList )
count := GetSkusCountLessEqualAvgPrice ( storeID , skusAveragePrice )
ratio := int ( math . Round ( float64 ( count ) * 100 / float64 ( totalCount ) ) )
if ratio >= SaleSkuPriceRatio {
finalScore = ItemScore
} else {
decScore := ( SaleSkuPriceRatio - ratio ) / 10
finalScore = ItemScore - decScore
if finalScore < 0 {
finalScore = 0
}
}
storeScoreDataWrapper . SetData ( storeID , "SaleSkuPrice" , finalScore )
}
//rangeStoreList := GetRangeStoreList(storeID, storeInfo.FloatLng, storeInfo.FloatLat, 5, storeList)
}
ClearAllStoreSkus ( )
}
func GetFilterStoreListEx ( storeList [ ] * cms . StoreExt , storeIDMap map [ int ] int ) ( outStoreList [ ] * cms . StoreExt ) {