+17
.github/workflows/tngl.yml
+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
+4
-1
.gitignore
+10
-3
README.md
+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
+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
+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
+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
+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
+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>