Initial commit: web_hghl_server
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
package moreser
|
||||
|
||||
// NormalizePage 规范化分页参数,限制单次请求数量避免大分页拖垮 MongoDB。
|
||||
func NormalizePage(pageNum, pageSize, defaultPageSize, maxPageSize int64) (int64, int64) {
|
||||
if pageNum <= 0 {
|
||||
pageNum = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = defaultPageSize
|
||||
}
|
||||
if pageSize > maxPageSize {
|
||||
pageSize = maxPageSize
|
||||
}
|
||||
return pageNum, pageSize
|
||||
}
|
||||
|
||||
// InsertedAdsCount 计算实际可穿插的广告数量,每 interval 条内容后插入 1 条广告。
|
||||
func InsertedAdsCount(contentTotal, adsTotal, interval int64) int64 {
|
||||
if contentTotal <= 0 || adsTotal <= 0 || interval <= 0 {
|
||||
return 0
|
||||
}
|
||||
insertSlots := contentTotal / interval
|
||||
if insertSlots > adsTotal {
|
||||
return adsTotal
|
||||
}
|
||||
return insertSlots
|
||||
}
|
||||
|
||||
// ContentPosition 计算内容原始下标在混排列表中的全局位置。
|
||||
func ContentPosition(contentIndex, adsTotal, interval int64) int64 {
|
||||
if interval <= 0 {
|
||||
return contentIndex
|
||||
}
|
||||
adsBefore := contentIndex / interval
|
||||
if adsBefore > adsTotal {
|
||||
adsBefore = adsTotal
|
||||
}
|
||||
return contentIndex + adsBefore
|
||||
}
|
||||
|
||||
// FirstContentIndexAtOrAfter 找到指定混排位置之后第一条内容下标。
|
||||
func FirstContentIndexAtOrAfter(pos, contentTotal, adsTotal, interval int64) int64 {
|
||||
left, right := int64(0), contentTotal
|
||||
for left < right {
|
||||
mid := left + (right-left)/2
|
||||
if ContentPosition(mid, adsTotal, interval) < pos {
|
||||
left = mid + 1
|
||||
continue
|
||||
}
|
||||
right = mid
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
||||
// ContentRange 计算当前混排分页需要读取的内容下标范围。
|
||||
func ContentRange(start, end, contentTotal, adsTotal, interval int64) (int64, int64) {
|
||||
contentStart := FirstContentIndexAtOrAfter(start, contentTotal, adsTotal, interval)
|
||||
contentEnd := FirstContentIndexAtOrAfter(end, contentTotal, adsTotal, interval)
|
||||
if contentStart >= contentEnd {
|
||||
return 0, 0
|
||||
}
|
||||
return contentStart, contentEnd - contentStart
|
||||
}
|
||||
|
||||
// ContentRangeWithoutTotal 计算当前混排分页需要读取的内容范围,不依赖内容总数。
|
||||
// 适用于列表接口不返回 totalCount 的场景;广告位仍按“每 interval 条内容后插入 1 条广告”计算。
|
||||
func ContentRangeWithoutTotal(start, end, adsTotal, interval int64) (int64, int64) {
|
||||
if start < 0 || end <= start {
|
||||
return 0, 0
|
||||
}
|
||||
contentStart := contentIndexAtMixedPosition(start, adsTotal, interval)
|
||||
contentEnd := contentIndexAtMixedPosition(end, adsTotal, interval)
|
||||
if contentStart >= contentEnd {
|
||||
return 0, 0
|
||||
}
|
||||
return contentStart, contentEnd - contentStart
|
||||
}
|
||||
|
||||
// ContentIndexAtPositionWithoutTotal 计算混排位置对应的内容下标,不判断该位置是否为广告。
|
||||
func ContentIndexAtPositionWithoutTotal(pos, adsTotal, interval int64) int64 {
|
||||
return contentIndexAtMixedPosition(pos, adsTotal, interval)
|
||||
}
|
||||
|
||||
// AdIndexAtPositionWithoutTotal 计算混排位置对应的广告下标,返回 -1 表示该位置不是广告。
|
||||
func AdIndexAtPositionWithoutTotal(pos, adsTotal, interval int64) int64 {
|
||||
if adsTotal <= 0 || interval <= 0 || pos < 0 {
|
||||
return -1
|
||||
}
|
||||
cycle := interval + 1
|
||||
if pos >= adsTotal*cycle {
|
||||
return -1
|
||||
}
|
||||
if pos%cycle != interval {
|
||||
return -1
|
||||
}
|
||||
return pos / cycle
|
||||
}
|
||||
|
||||
// contentIndexAtMixedPosition 返回混排位置之前已经出现的内容数量。
|
||||
func contentIndexAtMixedPosition(pos, adsTotal, interval int64) int64 {
|
||||
if pos <= 0 {
|
||||
return 0
|
||||
}
|
||||
if adsTotal <= 0 || interval <= 0 {
|
||||
return pos
|
||||
}
|
||||
adCycle := interval + 1
|
||||
adAreaSize := adsTotal * adCycle
|
||||
if pos >= adAreaSize {
|
||||
return pos - adsTotal
|
||||
}
|
||||
fullCycles := pos / adCycle
|
||||
remain := pos % adCycle
|
||||
return fullCycles*interval + minInt64(remain, interval)
|
||||
}
|
||||
|
||||
func minInt64(a, b int64) int64 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// AdIndexAtPosition 计算混排位置对应的广告下标,返回 -1 表示该位置不是广告。
|
||||
func AdIndexAtPosition(pos, contentTotal, adsTotal, interval int64) int64 {
|
||||
if interval <= 0 {
|
||||
return -1
|
||||
}
|
||||
nextContent := FirstContentIndexAtOrAfter(pos+1, contentTotal, adsTotal, interval)
|
||||
prevContent := nextContent - 1
|
||||
if prevContent >= 0 && (prevContent+1)%interval == 0 && (prevContent+1)/interval-1 < adsTotal {
|
||||
if ContentPosition(prevContent, adsTotal, interval)+1 == pos {
|
||||
return (prevContent+1)/interval - 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
Reference in New Issue
Block a user