AdInf Dev Journals #3: Pyscript!
Games Mentioned
- RPS
Sites Mentioned
- WAMO
Over this weekend I worked on two of my projects: RPS (Rock Paper Scissors) and WAMO.
On Friday I hit a blocker attempting to host RPS via Python Flask framework (I was trying to figure out how to take user input via browser and send it to the function that was connected via the Flask backend… and failed to make it work). I also spent some time debugging issues with the GUI for the app. Eventually, after hours of trial and error, I decided to split my RPS project into two entities: the .py local runnable file which utilizes a SimpleDialog Tkinter GUI and a browser accessible version using html embedded with PyScript – an option I had never encountered before taking on this project!
PyScript, which was only released earlier in 2022 and is still in active development, allows developers to use Python functionality within HTML files, basically allowing Python code to be executed on any webpage. This solution seemed perfect for RPS because:
- It allows for browser embedding (which was a primary goal of the project)
- RPS’s functions are relatively simple, allowing for more reliable usage via PyScript
- I didn’t need to translate the RPS function to JavaScript like I was beginning to fear!
- The “seriousness” of this project allows for this to be a good test of PyScript
In my limited experience, PyScript is unable to emulate some of the functions of Python on the browser, specifically commands that directly talk to the machine. My Tkinter GUI was unaccessable and a sys.exit() functionality that I had did not work with Pyscript.
With assistance from various tutorials and resources – specifically on the issue of getting HTML form input to properly connect to the Python functions – I was able to create the first working PyScript version of the game, linked here (currently temporarily housed on my other site!)
Action Item Checklist:
Key: Completed In-progress/Pending
- Created a python script that:
- Accepts user input and returns Win/Tie/Loss result on submit
- Displays a scoreboard of results in your session
- Has a desktop version utilizing a SimpleDialogue Tkinter GUI
- Implementing:
- RPS: GUI for user to input and see the output
- RPS: Code revisions for dealing with invalid options and resetting
RPS: Flask set up
- WAMO: Finish Getting into College
- Later:
- RPS: Allow user to send a code to play against their friend!
- RPS: Matplotlib the scoreboard info?
- RPS: Graphic design
- WAMO: NFT upload newest batches of Hmm icons
Here’s what I have so far:
https://github.com/jaqkk/Rock-Paper-Scissors
<html>
<head>
<title>
Rock Paper Scissors!
</title>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<style>
input[type=text], select {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=submit] {
width: 100%;
background-color: #4c4faf;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type=submit]:hover {
background-color: #45a049;
}
p {
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
</style>
<body>
<form onsubmit="return false">
<label for="name">Rock (r), paper (p), scissors (s)! --- random (Enter) reset (q): </label><br>
<input type="text" id="name" name="name" value=""><br>
<input pys-onClick="sub" type="submit" id="btn-form" value="submit">
</form>
<p>Output:</p>
<p id = 'output'></p>
<br>
<p>Scoreboard</p>
<p id = 'scoreboard'></p>
<py-script>
tie_count= 0
win_count=0
lose_count=0
def reset(self):
global tie_count
tie_count = 0
def RPS(userchoice):
import random
import sys
from argparse import FileType
FileType = ".py"
#allowed character list and initializing counts
rps = ["r", "p", "s" , "R", "P", "S" , " ", "q" , "%"]
global tie_count
global win_count
global lose_count
if userchoice != "":
c = True
else:
c = False
#Rock Paper Scissors runtime loop, first input asks for r p s (with random and quit options as well)
while c == True:
if userchoice not in rps:
return "Error! Only letters r, p, s allowed"
continue
elif len(userchoice) > 1:
return "Error! Only 1 character max allowed"
continue
if userchoice == " ":
userchoice = rps[random.randint(0, 2)]
UC = str(userchoice).lower()
cpu = rps[random.randint(0, 2)]
#matchups
if userchoice == "%":
return win_count, tie_count, lose_count
if UC == "q":
return "rulebreaker!"
if UC == cpu:
tie_count+=1
val = "Tie! - Your input was: ", UC ,". "
cpuval = "CPU choice was: ", cpu ,". "
endval = "".join(val+cpuval)
return endval
elif UC == "r" and cpu == "s" or UC == "s" and cpu == "p" or UC== "p" and cpu == "r":
win_count+=1
val = "Winner! - Your input was: ", UC ,". "
cpuval = "CPU choice was: ", cpu ,". "
endval = "".join(val+cpuval)
return endval
elif UC == "r" and cpu == "p" or UC == "s" and cpu == "r" or UC== "p" and cpu == "s":
lose_count+=1
val = "Loser! - Your input was: ", UC ,". "
cpuval = "CPU choice was: ", cpu ,". "
endval = "".join(val+cpuval)
return endval
def sub(*args,**kwargs):
result_place = Element('output')
result_place2 = Element('scoreboard')
input = Element('name').value
print(input)
out = RPS(input)
result_place.write(str(out))
score = RPS("%")
result_place2.write(str(score))
</py-script>
</body>
</html>
That’s all for the weekend, gonna take some time to rest, get caught up on WAMO work, and customizing the CSS on RPS!