Last active
April 4, 2018 02:27
-
-
Save DarkKor/866d2e44937209eb07a0ffb3e780de70 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MARK: - Soldout bets | |
private extension InGameBetsPresenter { | |
// Здесь везде сумма выкупа или ненулевое число, или 0 если выкупить нельзя, или -1, если локально посчитать сумму выкупа нельзя. | |
// В случае с -1 мы должны в UI отобразить знак вопроса и дать возможность узнать сумму выкупа у сервера. Но это не тема этого гиста. | |
// Так как lineId нам недоступно в этом случае, искать линию, соответствующую данной ставке, мы будем довольно утино. Другого варианта нет( | |
func findLine(forBet: BetLine, event: Event) -> Line? { | |
return event.lines.values.first(where: { $0.koefStr == forBet.koefAdditional && $0.favorite == forBet.favorite && Int32($0.type) == forBet.type }) | |
} | |
// MARK: Ordinar | |
func soldoutValue(ordinar: BetHistory) -> Double { | |
let betLine = ordinar.lines[0] | |
guard let event = DataStore.shared.events[betLine.eventId] else { | |
return 0 | |
} | |
let line = findLine(forBet: betLine, event: event) | |
if let currentLine = line { | |
let index = Int(betLine.xOfVx) - 1 | |
let currentKoef = Double(currentLine.vx[index]) / 100.0 | |
if currentKoef > 1 { | |
let betKoef = Double(betLine.koef) | |
let betValue = ordinar.betValue | |
let saleAmount = (betValue * betKoef - | |
(betKoef * betValue / (1.0 / (1.05 - 1.0 / currentKoef))) - betValue * 0.025) | |
var saleAmount2: Double = -1.0 | |
if currentKoef >= betKoef { | |
saleAmount2 = (betValue * betKoef / currentKoef - betValue * 0.125); | |
} else { | |
saleAmount2 = (betValue * betKoef / currentKoef - betValue * betKoef / currentKoef * 0.125) | |
} | |
if (saleAmount >= saleAmount2) { | |
if (saleAmount2 < 0) { | |
return 0.0 | |
} else { | |
return saleAmount2 | |
} | |
} else { | |
if saleAmount > 0 { | |
return saleAmount | |
} | |
} | |
} | |
} else { | |
if [1111116666, 1111116667, 283].contains(Int(betLine.type)) { | |
return -1.0 | |
} else { | |
let marketType = Int(DataStore.shared.markets[betLine.type]!.type) | |
if (event.inLive != 0 || event.inLive == 0 && [1, 2, 3, 4, 5, 6, 7, 8, 15].contains(marketType)) { | |
return 0.0 | |
} else { | |
return -1.0 | |
} | |
} | |
} | |
return 0.0 | |
} | |
// MARK: Express | |
// Это обычный кортеж, он нам нужен для накопления информации по мере прохода по массиву ставок экспресса | |
// Как мы помним, расчет экспресса основан на умножении коэффициентов входящих в него ставок. | |
// Точно так же и тут, ничего нового. Разве что информации, необходимой для расчета суммы выкупа, немного больше | |
// Поле flag в данном кортеже означает, что мы не смогли рассчитать сумму выкупа, и следует вообще говоря запрашивать ее у сервера | |
// Если не смогли, но выкупить можно, то дальше считать сумму экспресса нет смысла. | |
typealias LineParams = (winKoefs: Double, noWinKoefs: Double, betsKoefs: Double, linesKoefs: Double, countWin: Int, flag: Int) | |
func soldoutValue(express: BetHistory) -> Double { | |
var lineParams = LineParams(winKoefs: 1, noWinKoefs: 1, betsKoefs: 1, linesKoefs: 1, countWin: 0, flag: 0) | |
for i in 0..<express.lines.count { | |
let line = express.lines[i]; | |
let params = setLineParam(line, lineParams); | |
if params == nil { | |
return 0.0 | |
} | |
else if params!.flag != 0 { | |
return -1.0 | |
} | |
else { | |
lineParams = params! | |
} | |
} | |
return getSaleAmount(express.lines, lineParams, express.betValue) | |
} | |
func setLineParam(_ line: BetLine, _ lineParams: LineParams) -> LineParams? { | |
guard let event = DataStore.shared.events[line.eventId] else { | |
return nil | |
} | |
var currentKoef: Double = 0.0 | |
if line.state == 1 { | |
currentKoef = line.koefWin; | |
} else { | |
var currentLine = findLine(forBet: line, event: event) | |
if currentLine == nil { | |
if [1111116666, 1111116667, 283].contains(Int(line.type)) { | |
var params = lineParams | |
params.flag = 1 | |
return params | |
} else { | |
let marketType = Int(DataStore.shared.markets[line.type]!.type) | |
if (event.inLive != 0 || event.inLive == 0 && [1, 2, 3, 4, 5, 6, 7, 8, 15].contains(marketType)) { | |
return nil | |
} else { | |
var params = lineParams | |
params.flag = 1 | |
return params | |
} | |
} | |
} | |
let index = Int(line.xOfVx) - 1 | |
currentKoef = Double(currentLine!.vx[index]) / 100.0 | |
} | |
if currentKoef <= 1 { | |
var params = lineParams | |
params.flag = 1 | |
return params | |
} | |
var params = lineParams | |
params.betsKoefs = lineParams.betsKoefs * line.koef; | |
switch (line.state) { | |
case 0: | |
params.linesKoefs = lineParams.linesKoefs * currentKoef | |
params.noWinKoefs = lineParams.noWinKoefs * line.koef | |
case 1: | |
params.winKoefs = lineParams.winKoefs * line.koef | |
params.countWin = lineParams.countWin + 1 | |
default: | |
break | |
} | |
return params | |
} | |
func getSaleAmount(_ lines: [BetLine], _ lineParams: LineParams, _ betTotal: Double) -> Double { | |
var saleAmount: Double = 0, saleAmount2: Double = 0 | |
if lineParams.betsKoefs >= 1000 || lineParams.linesKoefs >= 1000 { | |
return 0.0 | |
} | |
if lineParams.countWin == lines.count { | |
saleAmount = betTotal * lineParams.winKoefs * 0.125 | |
return saleAmount | |
} | |
if lineParams.countWin + 1 == lines.count { | |
saleAmount = betTotal * lineParams.winKoefs * lineParams.noWinKoefs - (lineParams.noWinKoefs * betTotal * | |
lineParams.winKoefs / (1.0 / (1.05 - 1.0 / lineParams.linesKoefs))) - 0.025 * betTotal * lineParams.winKoefs | |
if lineParams.linesKoefs >= lineParams.noWinKoefs { | |
saleAmount2 = betTotal * lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs - betTotal * | |
lineParams.winKoefs * 0.125 | |
} else { | |
saleAmount2 = betTotal * lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs - betTotal * | |
lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs * 0.125 | |
} | |
if saleAmount >= saleAmount2 { | |
if saleAmount2 < 0 { | |
return 0.0 | |
} else { | |
return saleAmount2 | |
} | |
} else { | |
if saleAmount > 0 { | |
return saleAmount | |
} | |
} | |
} | |
if lines.count - lineParams.countWin <= 3 { | |
if lineParams.linesKoefs >= lineParams.noWinKoefs { | |
saleAmount2 = betTotal * lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs - betTotal * | |
lineParams.winKoefs * 0.4 | |
} else { | |
saleAmount2 = betTotal * lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs - betTotal * | |
lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs * 0.25 | |
} | |
return saleAmount2 < 0 ? 0 : saleAmount2 | |
} | |
if lineParams.linesKoefs >= lineParams.noWinKoefs { | |
saleAmount2 = betTotal * lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs - betTotal * | |
lineParams.winKoefs * 0.6 | |
} else { | |
saleAmount2 = betTotal * lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs - betTotal * | |
lineParams.winKoefs * lineParams.noWinKoefs / lineParams.linesKoefs * 0.5 | |
} | |
return saleAmount2 < 0 ? 0 : saleAmount2 | |
} | |
// MARK: System | |
// Расчет суммы выкупа для системы основывается на предыдущих методах расчета экспресса, только нужно выудить все комбинации ставок | |
func soldoutValue(system: BetHistory) -> Double { | |
let num = Int(system.eventsCountInSystem) | |
let systemVariants = combosOfLength(n: system.lines.count, m: num).count | |
let expressTotal = system.betValue / Double(systemVariants) | |
var exit: Bool = false | |
var saleAmount: Double = 0 | |
let bets = comboBets(bet: system, num: num, total: system.lines.count) | |
bets.forEach { (lines) in | |
if exit { | |
return | |
} | |
var lineParams = LineParams(winKoefs: 1, noWinKoefs: 1, betsKoefs: 1, linesKoefs: 1, countWin: 0, flag: 0) | |
lines.forEach({ (line) in | |
let params = setLineParam(line, lineParams) | |
if params == nil { | |
exit = true | |
return | |
} | |
else if params!.flag != 0 { | |
exit = true | |
return | |
} | |
else { | |
lineParams = params! | |
} | |
}) | |
saleAmount += getSaleAmount(lines, lineParams, expressTotal) | |
} | |
if exit { | |
return -1 | |
} | |
return saleAmount | |
} | |
// Получение всех возможных сочетаний в выбранной системе | |
// (например, рассматриваем систему 2 из 3, получим здесь массив следующих ставок - [1,2], [2,3], [1,3]) | |
// В java-коде эти методы будут иметь реализацию отличную от приведенной здесь | |
func comboBets(bet: BetHistory, num: Int, total: Int) -> [[BetLine]] { | |
let combinedIndices = combosOfLength(n: total, m: num) | |
var bets = [[BetLine]]() | |
combinedIndices.forEach { (indices) in | |
bets.append(indices.map({ (index) -> BetLine in | |
return bet.lines[index] | |
})) | |
} | |
return bets | |
} | |
func addCombo(prevCombo: [Int], pivotList: [Int]) -> [([Int], [Int])] { | |
var pivotList = pivotList | |
return (0..<pivotList.count) | |
.map { | |
_ -> ([Int], [Int]) in | |
(prevCombo + [pivotList.remove(at: 0)], pivotList) | |
} | |
} | |
func combosOfLength(n: Int, m: Int) -> [[Int]] { | |
return [Int](1...m) | |
.reduce([([Int](), [Int](0..<n))]) { | |
(accum, _) in | |
accum.flatMap(addCombo) | |
}.map { | |
$0.0 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment