Distributed and decentralized pi calculation

Compare changes

Choose any two refs to compare.

Changed files
+145 -43
.github
workflows
src
client
server
website
+17
.github/workflows/tngl.yml
··· 1 + name: Mirroring 2 + 3 + on: [push, delete] 4 + 5 + jobs: 6 + to_tangled: 7 + runs-on: ubuntu-latest 8 + steps: # <-- must use actions/checkout before mirroring! 9 + - uses: actions/checkout@v3 10 + with: 11 + fetch-depth: 0 12 + - uses: pixta-dev/repository-mirroring-action@v1 13 + with: 14 + target_repo_url: 15 + git@tangled.sh:wish.freakybob.site/pistributed 16 + ssh_private_key: # <-- use 'secrets' to pass credential information. 17 + ${{ secrets.TANGLED_SSH }}
+4 -1
.gitignore
··· 161 161 162 162 # Server 163 163 picalc/ 164 - ver.txt 164 + ver.txt 165 + 166 + # Client 167 + pi.txt
+10 -3
README.md
··· 1 - # pistributed 2 - distributed pi calculation 1 + # Pistributed 2 + > [!NOTE] 3 + > Python 3.14 has released! 🥳 Pistributed is untested on 3.14 at the moment (ironically). <3 4 + 5 + Distributed and decentralized pi calculation 6 + 7 + Tangled users; get Pistributed's client/server from GitHub here: https://github.com/wish13yt/pistributed/releases 8 + 9 + Website: https://wish13yt.github.io/pistributed/ 3 10 # Guide 4 - Download the server from the latest release. 11 + Download the server from the [latest release](https://github.com/wish13yt/pistributed/releases/latest). 5 12 6 13 Then, make sure you have flask & python-dotenv installed. 7 14
+42 -27
src/client/client.py
··· 3 3 import time 4 4 import threading 5 5 import requests 6 + import sys 7 + import urllib.request 6 8 7 9 print("Pistributed, an app to calculate Pi with distributed power.") 8 10 print("Do not run on systems owned by another entity, entities, person, or people, without explicit permission from them.") ··· 18 20 server = input("What is the server URL that you'd like to connect to? (ex: https://example.com, http://localhost:5000) ") 19 21 print("Alright! Thanks. Let the calculating begin :D (to exit, run ctrl+c or close terminal)") 20 22 print("-------------------") 23 + 21 24 global pi_val 22 25 pi_val = None 23 - def calc(n, prec): 24 - getcontext().prec = prec 25 - t = Decimal(0) 26 - pi = Decimal(0) 27 - deno = Decimal(0) 28 - for k in range(n): 29 - t = ((-1)**k) * (factorial(6*k)) * (13591409 + 545140134*k) 30 - deno = factorial(3*k) * (factorial(k)**3) * (640320**(3*k)) 31 - pi += Decimal(t) / Decimal(deno) 32 - pi = pi * Decimal(12) / Decimal(640320**Decimal(1.5)) 33 - pi = 1/pi 34 - return pi 26 + 27 + for line in urllib.request.urlopen(server + "/api/getmultiplier"): 28 + multiplier = int(line.decode('utf-8')) 29 + print("Multiplier from server is " + str(multiplier)) 30 + 31 + try: 32 + def calc(n, prec): 33 + getcontext().prec = prec 34 + t = Decimal(0) 35 + pi = Decimal(0) 36 + deno = Decimal(0) 37 + for k in range(n): 38 + t = ((-1)**k) * (factorial(6*k)) * (13591409 + 545140134*k) 39 + deno = factorial(3*k) * (factorial(k)**3) * (640320**(3*k)) 40 + pi += Decimal(t) / Decimal(deno) 41 + pi = pi * Decimal(12) / Decimal(640320**Decimal(1.5)) 42 + pi = 1/pi * multiplier 43 + return pi 35 44 36 - def upload(): 37 - while True: 38 - if str(pi_val).startswith("3.14") == True: 45 + def upload(): 46 + time.sleep(1) 47 + while True: 39 48 print(">> checking and uploading latest calculation") 40 49 response = requests.get(server + "/api/getpi") 41 50 print(response.text) ··· 46 55 data = {'pi': str(pi_val)} 47 56 print(data) 48 57 response = requests.post(server + "/api/postpi", data=data) 58 + print(response.text) 49 59 else: 50 60 if replen > pilen: 51 61 print("server pi length is greater than local pi length! not uploading") ··· 53 63 print("local pi length longer than server pi length! uploading") 54 64 data = {'pi': str(pi_val)} 55 65 response = requests.post(server + "/api/postpi", data=data) 56 - else: 57 - print("pi_val not yet defined!") 58 - time.sleep(60) 66 + print(response.text) 67 + time.sleep(60) 59 68 60 - threading.Thread(target=upload, daemon=True).start() 69 + threading.Thread(target=upload, daemon=True).start() 61 70 62 - calculation = 1 63 - precision = 10 71 + calculation = 1 72 + precision = 10 64 73 65 - while True: 66 - pi_val = calc(calculation, precision) 67 - print(pi_val) 68 - calculation += 1 69 - precision += 5 70 - time.sleep(5) 74 + while True: 75 + pi_val = calc(calculation, precision) 76 + print(pi_val) 77 + calculation += 1 78 + precision += 5 79 + time.sleep(5) 80 + except: 81 + print("\n") 82 + print("Saving your latest Pi to Pi.txt and exiting...") 83 + with open("pi.txt", "w") as f: 84 + f.write(str(pi_val)) 85 + sys.exit()
+64 -8
src/server/app.py
··· 2 2 from flask import render_template 3 3 from dotenv import load_dotenv 4 4 import os 5 - 5 + global pilen 6 + global pilength 6 7 app = Flask(__name__) 7 8 load_dotenv() 8 9 name = os.getenv("NAME") 9 10 email = os.getenv("EMAIL") 10 - 11 + multi = int(os.getenv("MULTI")) 12 + atEmail = email.replace("@", " at ") 13 + safeEmail = atEmail.replace(".", " dot ") 11 14 @app.route('/api/getpi') 12 15 def getpi(): 13 16 if request.method == 'GET': ··· 21 24 22 25 @app.route('/api/postpi', methods=['POST', 'GET']) 23 26 def postpi(): 27 + f = open("picalc/pi.txt", "r") 28 + checkCorrectly = 3.14 * multi 24 29 if request.form['pi']: 25 - if request.form['pi'].startswith("3.14") == True: 26 - with open("picalc/pi.txt", "w") as f: 27 - f.write(request.form['pi']) 30 + if f.read() == "No clients have connected yet. Become one of the first!": 31 + if request.form['pi'].startswith(str(checkCorrectly)) == True: 32 + with open("picalc/pi.txt", "w") as f: 33 + f.write(request.form['pi']) 34 + else: 35 + return "Invalid string!" 28 36 else: 29 - return "Invalid string!" 37 + if request.form['pi'].startswith(f.read()) == True: 38 + with open("picalc/pi.txt", "w") as f: 39 + f.write(request.form['pi']) 40 + else: 41 + return "Invalid string!" 42 + else: 43 + return "Request not found!" 30 44 31 45 @app.route('/') 32 46 def lander(): ··· 36 50 if piresult == "No clients have connected yet. Become one of the first!": 37 51 piresult = "No clients have connected. Become one of the first!" 38 52 else: 53 + try: 54 + pilength = len(str(piresult)) 55 + print(pilength) 56 + pilen = "Current Pi length is " + str(pilength) + " digits!" 57 + except: 58 + pilen = "Current Pi length couldn't be calculated!" 39 59 piresult = "Current Pi count is " + piresult 40 60 except: 41 - piresult = "picalc/pi.txt wasn't found on this web server. Sorry!" 61 + piresult = "picalc/pi.txt wasn't found on this server! It will be created now to fix this issue." 62 + try: 63 + with open("picalc/pi.txt", "w") as f: 64 + f.write("No clients have connected yet. Become one of the first!") 65 + except: 66 + piresult = f"Couldn't create pi.txt! Please contact {name} at {safeEmail} to fix this!" 42 67 if request.method == 'GET': 43 68 ver = open("ver.txt", "r") 44 69 version = ver.read() 45 - return render_template('index.html', pi=piresult, name=name, email=email, version=version) 70 + return render_template('index.html', pi=piresult, name=name, email=safeEmail, version=version, pilen="Current Pi length is " + str(pilength), multi=str(multi)) 46 71 else: 47 72 return "Please use GET to access this page." 73 + 74 + @app.route('/api/getlen') 75 + def getlen(): 76 + f = open("picalc/pi.txt", "r") 77 + piresult = f.read() 78 + if not piresult == "No clients have connected yet. Become one of the first!": 79 + pilength = len(str(piresult)) 80 + return str(pilength) 81 + else: 82 + return "Length cannot be calculated due to Pi not being calculated yet." 83 + 84 + @app.route('/api/getver') 85 + def getver(): 86 + try: 87 + f = open("ver.txt", "r") 88 + version = f.read() 89 + return version 90 + except: 91 + return "ver.txt not found on server" 92 + 93 + @app.route('/api/getname') 94 + def getname(): 95 + return name 96 + 97 + @app.route('/api/getemail') 98 + def getemail(): 99 + return safeEmail 100 + 101 + @app.route('/api/getmultiplier') 102 + def getMultiply(): 103 + return str(multi) 48 104 49 105 @app.errorhandler(404) 50 106 def page_not_found(error):
+3 -2
src/server/setup.py
··· 12 12 input("I agree, and would like to continue. (to continue, press enter)") 13 13 email = input("What email would you like to display for server support? THIS WILL BE MADE PUBLIC ") 14 14 called = input("What would you like to be called? (ex: Wish) THIS WILL BE MADE PUBLIC ") 15 + multi = input("What would you like Pi to be multiplied by? (number ONLY, default is 1)") or 1 15 16 print("Thank you! Creating a .env file... Make sure to run server.py when you are ready!") 16 17 with open(".env", "w") as file: 17 - file.write("EMAIL=" + email + "\nNAME=" + called) 18 + file.write("EMAIL=" + email + "\nNAME=" + called + "\nMULTI=" + multi) 18 19 isExist = os.path.exists("picalc") 19 20 if not isExist: 20 21 os.makedirs("picalc") ··· 23 24 pifile.write("No clients have connected yet. Become one of the first!") 24 25 print("Created picalc/pi.txt successfully. Do NOT edit this file!") 25 26 with open("ver.txt", "w") as versionfile: 26 - versionfile.write("1.1") 27 + versionfile.write("1.7") 27 28 print("Created version file. Server will not work without this!!!")
+2
src/server/templates/index.html
··· 24 24 <body> 25 25 <h1>Pistrubuted {{ version }}</h1> 26 26 <p>Pistrubuted is an open-source server & client to calculate Pi with distrubuted machines. Get started by downloading the client and connecting to this server.</p> 27 + <p>Pi is multiplied by {{ multi }}</p> 27 28 <p>{{ pi }}</p> 29 + <p>{{ pilen }}</p> 28 30 <hr> 29 31 <footer> 30 32 <p>This server is run by {{ name }}. Contact them at {{ email }} for support.</p>
+3 -2
website/index.html
··· 26 26 </head> 27 27 <body> 28 28 <h1>Pistributed</h1> 29 - <p>Pistrubuted is an open-source server & client to calculate Pi with distrubuted machines. Get started by downloading the client and connecting to a server.</p> 29 + <p>Pistrubuted is an open-source server & client to calculate Pi with distrubuted machines. Get started by <a href="https://github.com/wish13yt/pistributed/releases/latest">downloading the client</a> and connecting to a server.</p> 30 30 <p>No Pistributed servers are hosted by me except for the test server I use (which isn't public).</p> 31 31 <p>Make sure you trust the server you are connecting to! I am not responsible for what servers host.</p> 32 + <hr> 32 33 <footer> 33 34 <p>Pistributed made with Flask, Python, and love ❤️</p> 34 - <p>Client, server, and website is made available via GPL-3.0. Learn more at <a href="https://github.com/wish13yt/pistributed">https://github.com/wish13yt/pistributed</a>.</p> 35 + <p>Client, server, and website is made available via GPL-3.0. Learn more on <a href="https://github.com/wish13yt/pistributed">GitHub</a>.</p> 35 36 </footer> 36 37 </body> 37 38 </html>