Citat:
För vad det är värt så testa detta. Eftersom vissar matcher på Fullträff inte alltid har odds tydligen (antar att detta kommer så småningom) så gjorde jag en "fall back" där skriptet, när det inte finns odds på webben, istället använder spelarnas streckfördelning som guidance. Tanken är också att det ska gå rejält snabbare, men jag sitter på en lite för slö dator för att kunna avgöra någon stor skillnad.
Kod:
import requests
import re
import json
import itertools
from concurrent.futures import ProcessPoolExecutor
from pprint import pprint
gamemode = int(input("Spelform? 1= Stryktipset 2= Europatipset 3= Fullträff "))
if not gamemode in [1,2,3]:
print("Endast 1-2 möjliga val. Avbryter.")
quit()
pgoal = float(input("Önskad summa (t.ex. 200.0) ? "))
pdev = float(input("Tolerabel +/- avvikelse decimaltal (t.ex. 0.05)? "))
pmin = pgoal - pdev
pmax = pgoal + pdev
mde = int(input("Tryck 1 för text-fil och 2 för CSV-fil: "))
if not mde in [1,2]:
print("Endast 1 eller 2 möjliga val. Avbryter.")
quit()
urls = ["", "https://spela.svenskaspel.se/stryktipset" , "https://spela.svenskaspel.se/europatipset", "https://spela.svenskaspel.se/fulltraff"]
url = urls[gamemode]
outfiles = ["", "tips.txt", "tips.csv"]
outfile = outfiles[mde]
try:
response = requests.get(url)
html_content = response.text
except:
print(f"Kan inte komma hämta data från: {url}. Avbryter.")
quit()
pattern = r'_svs\.tipsen\.data\.preloadedState\s*=\s*(\{.*\});'
try:
match = re.search(pattern, html_content)
json_str = match.group(1)
json_obj = json.loads(json_str)
gameDict = json_obj["EventTypeStatistic"]
gameKeys = list(dict.keys(gameDict))
except:
print(f"Kunde inte extrahera data")
quit()
signlists = []
rowlist = []
def process_chunk(start, end):
sub_gen = itertools.islice(itertools.product(*[enumerate(row) for row in rowlist]), start, end)
valid_combinations = []
tss = 0
for comb in sub_gen:
tss += 1
indices, values = zip(*comb)
s = sum(values)
if pmin <= s <= pmax:
valid_combinations.append(indices + (s,))
return valid_combinations, tss
if gamemode == 3: # om fullträff, sätt upp lista utifrån 13 rader
draws=json_obj["Draws"]["entities"]
try:
drawsKey = list(dict.keys(draws))[0]
except IndexError:
print("Inte möjligt att hämta Fullträff-omgång. Avbryter.")
quit()
omg=draws[drawsKey]["drawNumber"] # hämta omgångsnr
print(f"Fullträff omgång {omg}:")
else: # annars sätt upp lista utifrån 3 tecken
for _ in range(0,3):
signlists.append([])
for gameKey in gameKeys: # iterera över alla 13 matcher
numAlts=3
if gamemode==3: # Fullträff
numAlts=6
game = gameDict[gameKey]["odds"]["current"]["value"] # hämtar odds-värden från Fullträff-sidan
reserve = False
if game[0] == None:
reserve = True
game = gameDict[gameKey]["distributions"]["38"]["Global"]["current"]["value"] #Fall-back till distributions om inte odds finns
gamesum = 0.0
floats = []
fgame = []
for i in range(0,numAlts):
if game[i] == None:
print ("None-error",gameDict[gameKey])
quit()
if reserve == False:
f = 100.0/float(game[i]) # konvertera oddset 100/o
else:
f = float(game[i])
floats.append(f)
gamesum = sum(floats)
for ix,o in enumerate(floats):
if reserve == False:
newo = 100.0 * o / gamesum # normalfördela fullträff-oddsen så att summan blir 100.0
else:
newo = o # om fallback (distribution så behövs ingen normalfördelning)
if ix<numAlts:
fgame.append(newo)
if gamemode==3:
rowlist.append(fgame)
else:
for ix,perc in enumerate(fgame):
signlists[ix].append(perc)
#game = gameDict[gameKey]["distributions"][str(gamemode)]["Global"]["current"]["value"] # Hämta streckfördelning
if gamemode<3:
P = { "1": signlists[0], "X": signlists[1], "2": signlists[2] }
rows = itertools.product(*(['1X2'] * 13))
cn = 0
with open(outfile, 'w') as f:
for row in rows:
percentage = sum(P[result][n] for (n, result) in enumerate(row))
if pmin <= percentage <= pmax:
cn += 1
if mde==1:
f.write("E,"+','.join(row)+"\n")
if mde==2:
f.write(','.join(row + (str(percentage),))+"\n")
else:
maxcoupons = 10000
cn = 0
tsts = 0
valid_combinations = []
chunk_size = 100000 # You can adjust the chunk size
total_size = 6 ** 13 # 6^13 combinations
chunks = [(i, min(i + chunk_size, total_size)) for i in range(0, total_size, chunk_size)]
with ProcessPoolExecutor() as executor:
for chunk_result, chunk_tsts in executor.map(process_chunk, [start for start, end in chunks], [end for start, end in chunks]):
tsts += chunk_tsts
valid_combinations.extend(chunk_result)
cn += len(chunk_result)
if tsts % 1000000 == 0:
print(int(tsts / 1000000), "million iterations,", cn, "rows found")
if cn >= maxcoupons:
break
with open(outfile, 'w') as f:
f.write(f"Fulltraff,Omg={omg}\n") # första raden
for comb in valid_combinations:
if mde == 1: # TXT-läge
comb=list(comb)
comb.pop() # ta bort summa som inte används i TXT-läge
f.write("E,"+','.join(str(nm) for nm in comb)+"\n")
elif mde == 2: # CSV-läge
f.write(','.join(str(nm) for nm in comb)+"\n")
print(f"{outfile} skapad med {cn} rader!")
Intressant, dock fick jag felmeddelande direkt när jag skulle köra det:
Traceback (most recent call last):
Cell In[2], line 161
for chunk_result, chunk_tsts in executor.map(process_chunk, [start for start, end in chunks], [end for start, end in chunks]):
File ~\anaconda3\Lib\concurrent\futures\process.py:816 in map
results = super().map(partial(_process_chunk, fn),
File ~\anaconda3\Lib\concurrent\futures\_base.py:608 in map
fs = [self.submit(fn, *args) for args in zip(*iterables)]
File ~\anaconda3\Lib\concurrent\futures\_base.py:608 in <listcomp>
fs = [self.submit(fn, *args) for args in zip(*iterables)]
File ~\anaconda3\Lib\concurrent\futures\process.py:770 in submit
raise BrokenProcessPool(self._broken)
BrokenProcessPool: A child process terminated abruptly, the process pool is not usable anymore
