2023-09-10, 16:02
  #205
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av Mysadname
Funkar det för dig ?

För mig stannar det på samma ställe som det gjort förut:
Testa denna modifierad kod, som nu inkluderar möjlighet att köra med eller utan parallella processer.
Nu kan du förhoppningsvis få en felkod, så vi ser var skon klämmer.

Kod:
import requests
import re
import json
import itertools
import os
import time

from concurrent.futures import ProcessPoolExecutor

# konstanter och definitioner

maxcoupons = 10000 # högsta antal rader (100000 är Sv.Spels gränd)
max_num_of_workers = 8 # ändras för olika antal parallella processer
outfiles = ["", "tips.txt", "tips.csv"] # ändras för andra filnamn
urls = ["", "https://spela.svenskaspel.se/stryktipset" , "https://spela.svenskaspel.se/europatipset", "https://spela.svenskaspel.se/fulltraff"]
multi_process = False # ändra till True för att köra flera processer samtidigt

fallback_omg = "50" 
fallback_url = f"https://api.spela.svenskaspel.se/multifetch?urls=/draw/1/fulltraff/draws/{fallback_omg}" 

def fetchFallbackGames(furl):
	
	try: 
		response = requests.get(furl)
		html_content = response.text
	
	except:
		print(f"Kan inte komma hämta data från: {furl}. Avbryter.")
		quit()
	
	try:
		json_obj = json.loads(html_content)
		gd = json_obj["responses"][0]["draw"]["drawEvents"]

	except:
		print(f"Kunde inte extrahera data, från:")
		print (json_obj)
		quit()
	
	return gd
	

def process_chunk(start, end, rowlist, pmin, pmax):
	 
	try:
		sub_gen = itertools.islice(itertools.product(*[enumerate(row) for row in rowlist]), start, end)
	except:
		print(f"Itertools failed at {start} - {end}")
		quit() 
	valid_combinations = []
	tss = 0
	for comb in sub_gen:
		tss += 1
		try:
			indices, values = zip(*comb)
		except:
			print("zip failed, with comb of:",len(comb))
			quit()
		s = sum(values)
		if pmin <= s <= pmax:
			valid_combinations.append(indices + (s,))
	return valid_combinations, tss

def main():
	

	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()

	
	url = urls[gamemode]
	
	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 = []
	fallback_mode = False

	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]
			omg=draws[drawsKey]["drawNumber"] # hämta omgångsnr
		except IndexError:
			print("Inte möjligt att hämta Fullträff-omgång.")
			jn = input("Tryck J för att hämta historiska data för testberäkning: ").lower()
			if not "j" == jn:
				quit()
			omg = fallback_omg
			fallback_mode = True
			gameDict = fetchFallbackGames(fallback_url)
			gameKeys = list(range(0,13))			
			
		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
	
		if fallback_mode == False:
			game = gameDict[gameKey]["odds"]["current"]["value"]  # hämtar odds-värden från Fullträff-sidan
		else:
			game = gameDict[gameKey]
		
		gamesum = 0.0
		
		floats = []
		fgame = []
		
		for i in range(0,numAlts):
			if fallback_mode == False:
				t = game[i]
			else:
				t = game["betMetrics"]["values"][i]["odds"]["odds"].replace(",",".")
			if t == None:
				print ("None-error",gameDict[gameKey])
				quit()
			#print(t)
			f = 100.0/float(t) # konvertera oddset 100/o
			floats.append(f)
		
		gamesum = sum(floats)
	
		for ix,o in enumerate(floats):
			newo = 100.0 * o / gamesum  # normalfördela fullträff-oddsen så att summan blir 100.0
			if ix<numAlts:
				fgame.append(newo)

		if gamemode==3:
			rowlist.append(fgame)
		
		else:
			for ix,perc in enumerate(fgame):
				signlists[ix].append(perc)

	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:
	
		cn = 0
		tsts = 0
		valid_combinations = []
		
		default_workers = os.cpu_count()
		print(f"Default number of workers: {default_workers}")

		chunk_size = 500000  # 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)]
	
		print ("Length of chunks:",len(chunks))
		
		start_time = time.time()
	
		if multi_process:
			
			with ProcessPoolExecutor(max_workers=max_num_of_workers) as executor:
				print(f"Executor is using {executor._max_workers} workers")
			
				for chunk_result, chunk_tsts in executor.map(process_chunk, [start for start, end in chunks], [end for start, end in chunks], itertools.repeat(rowlist), itertools.repeat(pmin), itertools.repeat(pmax)):
   
					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
	
		else:
			
			for start, end in chunks:
				chunk_result, chunk_tsts = process_chunk(start, end, rowlist, pmin, pmax)
				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
			
		end_time = time.time()
		taken_time = round(end_time - start_time,2)
		ave_time = round(taken_time/(tsts/1000000),4)
		print(f"Time taken: {taken_time} seconds")
		print(f"Avg. time: {ave_time} sec/million iterations")
		
		
		with open(outfile, 'w') as f:
		
			f.write(f"Fulltraff,Omg={omg}\n") # första raden 
		
			for ix,comb in enumerate(valid_combinations):
			
				if mde == 1 and ix<maxcoupons: # 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 and ix<maxcoupons: # CSV-läge
					f.write(','.join(str(nm) for nm in comb)+"\n")

	cn=min(cn,maxcoupons)
	
	print(f"{outfile} skapad med {cn} rader!")

if __name__ == '__main__':
    main()
Citera
2023-09-10, 17:11
  #206
Medlem
Citat:
Ursprungligen postat av Enterprise
Testa denna modifierad kod, som nu inkluderar möjlighet att köra med eller utan parallella processer.
Nu kan du förhoppningsvis få en felkod, så vi ser var skon klämmer.

Kod:
import requests
import re
import json
import itertools
import os
import time

from concurrent.futures import ProcessPoolExecutor

# konstanter och definitioner

maxcoupons = 10000 # högsta antal rader (100000 är Sv.Spels gränd)
max_num_of_workers = 8 # ändras för olika antal parallella processer
outfiles = ["", "tips.txt", "tips.csv"] # ändras för andra filnamn
urls = ["", "https://spela.svenskaspel.se/stryktipset" , "https://spela.svenskaspel.se/europatipset", "https://spela.svenskaspel.se/fulltraff"]
multi_process = False # ändra till True för att köra flera processer samtidigt

fallback_omg = "50" 
fallback_url = f"https://api.spela.svenskaspel.se/multifetch?urls=/draw/1/fulltraff/draws/{fallback_omg}" 

def fetchFallbackGames(furl):
	
	try: 
		response = requests.get(furl)
		html_content = response.text
	
	except:
		print(f"Kan inte komma hämta data från: {furl}. Avbryter.")
		quit()
	
	try:
		json_obj = json.loads(html_content)
		gd = json_obj["responses"][0]["draw"]["drawEvents"]

	except:
		print(f"Kunde inte extrahera data, från:")
		print (json_obj)
		quit()
	
	return gd
	

def process_chunk(start, end, rowlist, pmin, pmax):
	 
	try:
		sub_gen = itertools.islice(itertools.product(*[enumerate(row) for row in rowlist]), start, end)
	except:
		print(f"Itertools failed at {start} - {end}")
		quit() 
	valid_combinations = []
	tss = 0
	for comb in sub_gen:
		tss += 1
		try:
			indices, values = zip(*comb)
		except:
			print("zip failed, with comb of:",len(comb))
			quit()
		s = sum(values)
		if pmin <= s <= pmax:
			valid_combinations.append(indices + (s,))
	return valid_combinations, tss

def main():
	

	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()

	
	url = urls[gamemode]
	
	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 = []
	fallback_mode = False

	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]
			omg=draws[drawsKey]["drawNumber"] # hämta omgångsnr
		except IndexError:
			print("Inte möjligt att hämta Fullträff-omgång.")
			jn = input("Tryck J för att hämta historiska data för testberäkning: ").lower()
			if not "j" == jn:
				quit()
			omg = fallback_omg
			fallback_mode = True
			gameDict = fetchFallbackGames(fallback_url)
			gameKeys = list(range(0,13))			
			
		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
	
		if fallback_mode == False:
			game = gameDict[gameKey]["odds"]["current"]["value"]  # hämtar odds-värden från Fullträff-sidan
		else:
			game = gameDict[gameKey]
		
		gamesum = 0.0
		
		floats = []
		fgame = []
		
		for i in range(0,numAlts):
			if fallback_mode == False:
				t = game[i]
			else:
				t = game["betMetrics"]["values"][i]["odds"]["odds"].replace(",",".")
			if t == None:
				print ("None-error",gameDict[gameKey])
				quit()
			#print(t)
			f = 100.0/float(t) # konvertera oddset 100/o
			floats.append(f)
		
		gamesum = sum(floats)
	
		for ix,o in enumerate(floats):
			newo = 100.0 * o / gamesum  # normalfördela fullträff-oddsen så att summan blir 100.0
			if ix<numAlts:
				fgame.append(newo)

		if gamemode==3:
			rowlist.append(fgame)
		
		else:
			for ix,perc in enumerate(fgame):
				signlists[ix].append(perc)

	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:
	
		cn = 0
		tsts = 0
		valid_combinations = []
		
		default_workers = os.cpu_count()
		print(f"Default number of workers: {default_workers}")

		chunk_size = 500000  # 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)]
	
		print ("Length of chunks:",len(chunks))
		
		start_time = time.time()
	
		if multi_process:
			
			with ProcessPoolExecutor(max_workers=max_num_of_workers) as executor:
				print(f"Executor is using {executor._max_workers} workers")
			
				for chunk_result, chunk_tsts in executor.map(process_chunk, [start for start, end in chunks], [end for start, end in chunks], itertools.repeat(rowlist), itertools.repeat(pmin), itertools.repeat(pmax)):
   
					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
	
		else:
			
			for start, end in chunks:
				chunk_result, chunk_tsts = process_chunk(start, end, rowlist, pmin, pmax)
				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
			
		end_time = time.time()
		taken_time = round(end_time - start_time,2)
		ave_time = round(taken_time/(tsts/1000000),4)
		print(f"Time taken: {taken_time} seconds")
		print(f"Avg. time: {ave_time} sec/million iterations")
		
		
		with open(outfile, 'w') as f:
		
			f.write(f"Fulltraff,Omg={omg}\n") # första raden 
		
			for ix,comb in enumerate(valid_combinations):
			
				if mde == 1 and ix<maxcoupons: # 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 and ix<maxcoupons: # CSV-läge
					f.write(','.join(str(nm) for nm in comb)+"\n")

	cn=min(cn,maxcoupons)
	
	print(f"{outfile} skapad med {cn} rader!")

if __name__ == '__main__':
    main()

Nu gick den igång, ingen felkod:

Time taken: 21.39 seconds
Avg. time: 0.6385 sec/million iterations
tips.txt skapad med 10000 rader!
Citera
2023-09-10, 17:13
  #207
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av Mysadname
Nu gick den igång, ingen felkod:

Time taken: 21.39 seconds
Avg. time: 0.6385 sec/million iterations
tips.txt skapad med 10000 rader!
OK, då får nog lov att köra single-process ändå. 0.635 sek/miljon är OK tid även om det är tre gånger långsammare än på min Windows-burk med 8 eller 16 processer.
Citera
2023-09-10, 17:14
  #208
Medlem
Citat:
Ursprungligen postat av Enterprise
OK, då får nog lov att köra single-process ändå. 0.635 sek/miljon är OK tid även om det är tre gånger långsammare än på min Windows-burk med 8 eller 16 processer.

Oj, var det så stor skillnad
Citera
2023-09-10, 17:25
  #209
Medlem
Citat:
Ursprungligen postat av Enterprise
OK, då får nog lov att köra single-process ändå. 0.635 sek/miljon är OK tid även om det är tre gånger långsammare än på min Windows-burk med 8 eller 16 processer.

Var tvungen att testa på min 32Gb burk och där gick det ännu långsammare

Time taken: 44.31 seconds
Avg. time: 1.3227 sec/million iterations
tips.txt skapad med 10000 rader!
Citera
2023-09-10, 17:48
  #210
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av Mysadname
Var tvungen att testa på min 32Gb burk och där gick det ännu långsammare

Time taken: 44.31 seconds
Avg. time: 1.3227 sec/million iterations
tips.txt skapad med 10000 rader!
Ja det är enbart CPU frekvens som gäller när man kör single thread. Det stora minnet gör det inte snabbare.
Citera
2023-09-10, 17:52
  #211
Medlem
Enterprises avatar
Som en referens tar min MacBook Air (M1) 0.6 sek per miljon med 8 processer och 1.38 sek per miljon med single thread.
Citera
2023-09-10, 18:45
  #212
Medlem
Citat:
Ursprungligen postat av Enterprise
Som en referens tar min MacBook Air (M1) 0.6 sek per miljon med 8 processer och 1.38 sek per miljon med single thread.

Ok, så hur får man datorn att använda den kraft den har istället för det som den tycker duger ?
__________________
Senast redigerad av Mysadname 2023-09-10 kl. 18:58.
Citera
2023-09-10, 19:04
  #213
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av Mysadname
Ok, så hur får man datorn att använda den kraft den har istället för det som den tycker duger ?
Om du ändrar multi_process till True och fortfarande inte får några felmeddelanden så kommer vi inte längre.
Citera
2023-09-10, 19:13
  #214
Medlem
Citat:
Ursprungligen postat av Enterprise
Om du ändrar multi_process till True och fortfarande inte får några felmeddelanden så kommer vi inte längre.

Men vad det ska vara besvärligt, jag ändrade på ett ställe men får såklart felmeddelande:

Traceback (most recent call last):

Cell In[3], line 16
multi_process = true # ändra till True för att köra flera processer samtidigt

NameError: name 'true' is not defined

Tycker ju att om den har max fart på 5.0 Ghz så kan den väl nyttja det ?
__________________
Senast redigerad av Mysadname 2023-09-10 kl. 19:16.
Citera
2023-09-10, 19:15
  #215
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av Mysadname
Men vad det ska vara besvärligt, jag ändrade på ett ställe men får såklart felmeddelande:

Traceback (most recent call last):

Cell In[3], line 16
multi_process = true # ändra till True för att köra flera processer samtidigt

NameError: name 'true' is not defined
testa True med stor bokstav
Citera
2023-09-10, 19:17
  #216
Medlem
Citat:
Ursprungligen postat av Enterprise
testa True med stor bokstav

Ja, den får väl stå på en stund, stannar på samma ställe som förut:

Default number of workers: 16
Length of chunks: 26122
Executor is using 8 workers
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in