Sheek, the sheep game with a knockout twist. - Neowise - 24-06-2023
Hi,
Inspired by another posts in the sign-up thread, I have decide to try out a new flavour of sheep, this one called sheek.
As I have no idea how this game will play, I'll run its inaugural game small, and see how it plays out, well, that's the plan as of writing this.
As with the game sheep, you are looking for the most popular answer.
The twist is, if you ace, you are knocked out.
Here are some questions. There are no wrong answers in Sheek.
1) Name one of the colours a snooker ball can be.
2) Name a County in Northern Ireland
3) Name a Spice Girl.
4) Name one of the directions that the arrows point on a standard keyboard.
5) Name a primary colour of light.
6) Name one of the countries on the Korean Peninsula.
Enjoy.
Feel free to use Google, brothers, sister, uncles, friends, children or AI for assistance.
RE: Sheek, the sheep game with a knockout twist. - jp liz v1 - 25-06-2023
Sheeky
RE: Sheek, the sheep game with a knockout twist. - Leg End Reject - 25-06-2023
I'll get answers in later today for this Arabian twist on sheep.
RE: Sheek, the sheep game with a knockout twist. - Neowise - 25-06-2023
16 players:
aaronjennings
davetherave
Declan A Walsh
Edser
Homer J. Fong
Irish Aris
Jluv
jp liz v1
Leg End Reject
lorcand1990
Mam of 4
Necro
nothing
Sephiroth_Dude
ShaneU
Spears
RE: Sheek, the sheep game with a knockout twist. - Leg End Reject - 25-06-2023
@jp liz v1
@E.N.
@Necro
@thomil
@Spears
@ari101
@ShaneU
@Trigger
@Barna77
@Sawduck
@nothing
@DejaBoo
@Mam of 4
@Barney92
@BuileBeag
@lorcand1990
@Irish Aris
@RSOAPS
@Homer J. Fong
@aaronjennings
@Sephiroth_Dude
@Declan A Walsh
@Hello 2D Person Below
@
RE: Sheek, the sheep game with a knockout twist. - jp liz v1 - 25-06-2023
Sheek Spoon Entry In
RE: Sheek, the sheep game with a knockout twist. - Declan A Walsh - 26-06-2023
@Leg End Reject Entry already submitted, but thanks for remembering me!
A few more callouts:
@Wichita Lineman
@NNAHere
@Cj maxx
@davetherave
@Tauriel
@Zaph
@Kol
RE: Sheek, the sheep game with a knockout twist. - lorcand1990 - 26-06-2023
RE: Sheek, the sheep game with a knockout twist. - BuileBeag - 26-06-2023
I too, am in.
RE: Sheek, the sheep game with a knockout twist. - nothing - 26-06-2023
And me!
RE: Sheek, the sheep game with a knockout twist. - Mam of 4 - 26-06-2023
In too !
RE: Sheek, the sheep game with a knockout twist. - Spears - 26-06-2023
Thanks for the shoutout @Leg End Reject 😊
..I'll get an entry in tomorrow evening @Neowise 🙃
RE: Sheek, the sheep game with a knockout twist. - Leg End Reject - 27-06-2023
@Butty Brennan too in case he logs in.
RE: Sheek, the sheep game with a knockout twist. - lorcand1990 - 27-06-2023
(25-06-2023, 10:49 PM)Leg End Reject Wrote: @jp liz v1
@E.N.
@Necro
@thomil
@Spears
@ari101
@ShaneU
@Trigger
@Barna77
@Sawduck
@nothing
@DejaBoo
@Mam of 4
@Barney92
@BuileBeag
@lorcand1990
@Irish Aris
@RSOAPS
@Homer J. Fong
@aaronjennings
@Sephiroth_Dude
@Declan A Walsh
@Hello 2D Person Below
@
RE: Sheek, the sheep game with a knockout twist. - Spears - 27-06-2023
Inski 😊
RE: Sheek, the sheep game with a knockout twist. - davetherave - 29-06-2023
Answers in. Thanks Neo
RE: Sheek, the sheep game with a knockout twist. - Neowise - 29-06-2023
16 players is awesome, and way more than I thought I'd get in this new idea for a game.
I'll fire off the reveal some time tonight. wasn't planing anything fancy, but as we got 16 players in I might just spend a few minutes looking for a few pictures to go along with the reveal.
In other news, I'm remaking the sheep scorer from scratch in python.
before whoever has the chrome book asks, yes, it is way more portable than c# (with my experience of c# anyway) and i should be able to fire out a chromebook version after i have it working.
RE: Sheek, the sheep game with a knockout twist. - E.N. - 29-06-2023
Make that 17, if I haven't missed the boat
RE: Sheek, the sheep game with a knockout twist. - Sephiroth_Dude - 30-06-2023
(29-06-2023, 06:46 PM)Neowise Wrote: 16 players is awesome, and way more than I thought I'd get in this new idea for a game.
I'll fire off the reveal some time tonight. wasn't planing anything fancy, but as we got 16 players in I might just spend a few minutes looking for a few pictures to go along with the reveal.
In other news, I'm remaking the sheep scorer from scratch in python.
before whoever has the chrome book asks, yes, it is way more portable than c# (with my experience of c# anyway) and i should be able to fire out a chromebook version after i have it working.
18, don't forget Builebeag.
RE: Sheek, the sheep game with a knockout twist. - Neowise - 30-06-2023
(30-06-2023, 12:04 AM)Sephiroth_Dude Wrote: (29-06-2023, 06:46 PM)Neowise Wrote: 16 players is awesome, and way more than I thought I'd get in this new idea for a game.
I'll fire off the reveal some time tonight. wasn't planing anything fancy, but as we got 16 players in I might just spend a few minutes looking for a few pictures to go along with the reveal.
In other news, I'm remaking the sheep scorer from scratch in python.
before whoever has the chrome book asks, yes, it is way more portable than c# (with my experience of c# anyway) and i should be able to fire out a chromebook version after i have it working.
18, don't forget Builebeag.
Oh, i must investigate the missing bb
RE: Sheek, the sheep game with a knockout twist. - Neowise - 30-06-2023
thanks seph, will double check whole list again.
18 players:
aaronjennings
BuileBeag
davetherave
Declan A Walsh
E.N.
Edser
Homer J. Fong
Irish Aris
Jluv
jp liz v1
Leg End Reject
lorcand1990
Mam of 4
Necro
nothing
Sephiroth_Dude
ShaneU
Spears
RE: Sheek, the sheep game with a knockout twist. - Sephiroth_Dude - 30-06-2023
(29-06-2023, 06:46 PM)Neowise Wrote: In other news, I'm remaking the sheep scorer from scratch in python.
Are you using tkinter ?
RE: Sheek, the sheep game with a knockout twist. - Neowise - 30-06-2023
(30-06-2023, 01:00 PM)Sephiroth_Dude Wrote: (29-06-2023, 06:46 PM)Neowise Wrote: In other news, I'm remaking the sheep scorer from scratch in python.
Are you using tkinter ?
yes, want me to share what i have done up to now?
RE: Sheek, the sheep game with a knockout twist. - Sephiroth_Dude - 30-06-2023
(30-06-2023, 01:13 PM)Neowise Wrote: (30-06-2023, 01:00 PM)Sephiroth_Dude Wrote: Are you using tkinter ?
yes, want me to share what i have done up to now?
Sure that would be great!
RE: Sheek, the sheep game with a knockout twist. - Neowise - 30-06-2023
main.pyShow Content
from tkinter import *
from tkinter import filedialog, messagebox, ttk
import xml.etree.ElementTree as ET
gt= {'Sheep':1,'PeehsDM':2, 'PeehsFB':3, 'PeehsHybrid':4, 'Heep':5, 'Heep15':6, 'Heep2':7, 'Kangaroo':8, 'Manual':9}
gtl=['filler','Sheep','PeehsDM','PeehsFB','PeehsHybrid','Heep','Heep15','Heep2','Kangaroo','Manual']
rt= {'None':0,'Up':1,'Down':2,'Nearest':3}
rtl=['None','Up','Down','Nearest']
def resetProgram():
global myTextbox1, myLabel2, myQuestions, myAnswers, myPlayers, curQ
myQuestions = []
myAnswers = []
myPlayers = []
curQ = 1
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
myLabel2.grid_forget()
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0, column=4)
return
def edQL(edQText):
edQL.filename = filedialog.askopenfilename(title="Load Questions from File", filetypes=[("txt files", "*.txt")] )
#print(edQL.filename) #debug code
file1 = open(edQL.filename, 'r')
strvar=file1.read()
edQText.delete(1.0,END)
edQText.insert(INSERT, strvar)
return(edQText)
def edSave(edQW,edQText):
global myQuestions
global myLabel2
global curQ
myQuestions = edQText.get("1.0",END).splitlines()
window.deiconify()
if curQ==0:curQ=1
if curQ>len(myQuestions): curQ=len(myQuestions)
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ - 1])
myLabel2.grid(row=0, column=4)
edQW.destroy()
def edPCancel(edAW,object):
edAW.deiconify()
object.destroy()
def newPlayer(edAW):
global myPlayers
edAW.withdraw()
newPW = Toplevel(edAW)
newPW.title("New Player")
newPLabel = Label(newPW, text="Enter new player name:").grid(row=0,column=0)
newPEntry = Entry(newPW).grid(row=1,column=0)
newPOK = Button(newPW, text='OK').grid(row=2,column=3)
newPCancel = Button(newPW,text='Cancel', command=lambda:edPCancel(edAW,newPW)).grid(row=2,column=4)
def edAnswers(window):
window.withdraw()
myfile="\n".join(item for item in myAnswers)
edAW = Toplevel(window)
edAW.title("Edit Entries")
edALabel = Label(edAW, text="Player:")
edALabel.grid(row=0,column=0)
combo = ttk.Combobox(edAW,state="readonly",values=["Python", "C", "C++", "Java"])
combo.grid(row=0,column=1)
spacer=Label(edAW).grid(row=0,column=2)
edALabel = Label(edAW, text="Starting Score:", padx=10)
edALabel.grid(row=1,column=0)
edAText = Text(edAW)
edAText.insert(INSERT, 'Click Load... to load players and answers\nfrom a PM text file, or click New Player\nto add players manually.')
edAText.grid(column=0,columnspan=3, rowspan=10, padx=5, pady=5)
edALoad = Button(edAW,text="Load", padx=20, command=lambda:edQL(edAText)).grid(row=0, column=3, padx=10,pady=5)
edANP = Button(edAW, text="New Player", padx=4,command=lambda:newPlayer(edAW)).grid(row=1, column=3, padx=10,pady=5)
edACN = Button(edAW, text="Change Name", padx=0).grid(row=2 ,column=3, padx=10,pady=5)
edADP = Button(edAW, text="Delete Player", padx=0).grid(row=3, column=3, padx=10,pady=5)
edASave = Button(edAW,text="Save Changes",command=lambda:edSave(edAW,edAText)).grid(row=9, column=3,padx=10, pady=5)
edACancel = Button(edAW,text="Cancel", padx=20,command=lambda:edCancel(edAW)).grid(row=10, column=3, padx=10, pady=5)
edAW.rowconfigure(4, weight=1)
edAW.columnconfigure(2, weight=1)
return
def edQuestions(window):
window.withdraw()
myfile="\n".join(item for item in myQuestions)
edQW = Toplevel(window)
edQW.title("Edit Questions")
edQLabel = Label(edQW, text="Click Load... to load the questions from a text file, or just type them in here one per line")
edQLabel.grid(row=0,columnspan=2)
edQText = Text(edQW)
edQText.insert(INSERT,myfile)
edQText.grid(column=0, rowspan=10, padx=5, pady=5)
edQLoad = Button(edQW,text="Load", padx=20, command=lambda:edQL(edQText)).grid(row=1, column=1)
edQSave = Button(edQW,text="Save Changes",command=lambda:edSave(edQW,edQText)).grid(row=9, column=1)
edQCancel = Button(edQW,text="Cancel", padx=20,command=lambda:edCancel(edQW)).grid(row=10, column=1)
return
def validate_entry(text):
return text.isdecimal()
myQuestions = []
myAnswers = []
myPlayers = []
curQ=1
window = Tk()
window.geometry("680x450")
window.title("Sheep Score Foggies Edition")
Outputtype = IntVar()
Outputtype.set(1)
Gametype = IntVar()
Gametype.set(1)
Roundtype = IntVar()
Roundtype.set(0)
menubar = Menu(window)
window.config(menu=menubar)
fileMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="File",menu=fileMenu)
def dothis():
global myQuestions
print(myQuestions)
print(myAnswers)
print(myPlayers)
print(gtl[Gametype.get()])
print(rtl[Roundtype.get()])
def loadReveal():
global myQuestions, myLabel2, myPlayers, Gametype, Roundtype
filename = filedialog.askopenfilename(title="Load Sheep Scoring File", filetypes=[("Sheep Score 2017 File", "*.sheep17")])
tree = ET.parse(filename)
root = tree.getroot()
print(root.tag)
if root.tag == "SheepScore2012Game":
myQuestions = []
for child in root:
if child.tag == "Question":
myQuestions.append(child.text)
elif child.tag == "Player":
myPlayers.append([child.text,child.attrib['StartScore']])
elif child.tag == "ScoringMethod":
Gametype.set(gt[child.text])
elif child.tag == "Rounding":
Roundtype.set(rt[child.text])
elif child.tag == "Group":
pass # To do
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ - 1])
myLabel2.grid(row=0, column=4)
else:
qdown()
else:
messagebox.showinfo(title="Greetings", message="This is not a recognized sheep file!")
fileMenu.add_command(label="New Reveal", command=resetProgram)
fileMenu.add_command(label="Load Reveal...", command=loadReveal)
fileMenu.add_command(label="Save Reveal...")
fileMenu.add_command(label="Debug", command=dothis)
fileMenu.add_separator()
fileMenu.add_command(label="Exit",command=quit)
sheepMenu = Menu(menubar,tearoff=0)
menubar.add_cascade(label="Sheep",menu=sheepMenu)
sheepMenu.add_command(label="Edit Questions...", command=lambda:edQuestions(window))
sheepMenu.add_command(label="Edit Entries...", command=lambda:edAnswers(window))
scoringMenu=Menu(menubar,tearoff=0)
sheepMenu.add_cascade(label="Scoring",menu=scoringMenu)
scoringMenu.add_radiobutton(label="Sheep",value=1, variable=Gametype)
peehsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Peehs",menu=peehsMenu)
peehsMenu.add_radiobutton(label="DM Scoring",value=2, variable=Gametype)
peehsMenu.add_radiobutton(label="FB Scoring",value=3, variable=Gametype)
peehsMenu.add_radiobutton(label="Hybrid",value=4, variable=Gametype)
heepsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Heeps",menu=heepsMenu)
heepsMenu.add_radiobutton(label="2x Heep Bonus",value=7, variable=Gametype)
heepsMenu.add_radiobutton(label="1.5x Heep Bonus",value=6, variable=Gametype)
heepsMenu.add_radiobutton(label="No Heep Bonus",value=5, variable=Gametype)
scoringMenu.add_radiobutton(label="Kangaroo",value=8, variable=Gametype)
scoringMenu.add_radiobutton(label="Manual",value=9, variable=Gametype)
scoringMenu.add_separator()
roundingMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Rounding",menu=roundingMenu)
roundingMenu.add_radiobutton(label="No Rounding",value=0, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Up",value=1, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Down",value=2, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Nearest",value=3, variable=Roundtype)
outputMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="Output",menu=outputMenu)
outputMenu.add_command(label="Copy answers for this question")
outputMenu.add_command(label="Copy total scores up to this question")
outputMenu.add_command(label="Copy score table up to this question")
outputMenu.add_command(label="Copy Player list")
outputMenu.add_separator()
styleMenu=Menu(menubar,tearoff=0)
outputMenu.add_cascade(label="Output Style",menu=styleMenu)
styleMenu.add_radiobutton(label="Forum Table",value=1, variable=Outputtype)
styleMenu.add_radiobutton(label="Forum Formatted Text",value=2, variable=Outputtype)
styleMenu.add_radiobutton(label="Unformatted Text",value=3, variable=Outputtype)
def qdown():
global curQ
global myLabel2
if curQ>len(myQuestions): curQ = len(myQuestions)
if curQ>1:
curQ=curQ-1
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ-1])
myLabel2.grid(row=0, column=4)
def qup():
global curQ
global myLabel2
if curQ > len(myQuestions): curQ = len(myQuestions)
if curQ < len(myQuestions):
curQ = curQ + 1
else:
curQ == 1
myTextbox1.delete(0,END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ-1])
myLabel2.grid(row=0, column=4)
qButton1 = Button(window, text="<",command=qdown).grid(row=0,column=1)
qButton2 = Button(window, text=">",command=qup).grid(row=0,column=3)
myLabel1 = Label(window, text="Q #", padx=5).grid(row=0,column=0)
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0,column=4)
myTextbox1 = Entry(window,width=4 ,validate="key",
validatecommand=(window.register(validate_entry), "%S"))
myTextbox1.insert(INSERT,curQ)
myTextbox1.grid(row=0,column=2)
myTextbox2 = Text(window,state=DISABLED,padx=10,pady=5)
myTextbox2.grid(row=1,column=0,columnspan=5)
window.columnconfigure(4, weight=1)
window.mainloop()
RE: Sheek, the sheep game with a knockout twist. - Sephiroth_Dude - 30-06-2023
(30-06-2023, 01:18 PM)Neowise Wrote:
main.pyShow Content
from tkinter import *
from tkinter import filedialog, messagebox, ttk
import xml.etree.ElementTree as ET
gt= {'Sheep':1,'PeehsDM':2, 'PeehsFB':3, 'PeehsHybrid':4, 'Heep':5, 'Heep15':6, 'Heep2':7, 'Kangaroo':8, 'Manual':9}
gtl=['filler','Sheep','PeehsDM','PeehsFB','PeehsHybrid','Heep','Heep15','Heep2','Kangaroo','Manual']
rt= {'None':0,'Up':1,'Down':2,'Nearest':3}
rtl=['None','Up','Down','Nearest']
def resetProgram():
global myTextbox1, myLabel2, myQuestions, myAnswers, myPlayers, curQ
myQuestions = []
myAnswers = []
myPlayers = []
curQ = 1
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
myLabel2.grid_forget()
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0, column=4)
return
def edQL(edQText):
edQL.filename = filedialog.askopenfilename(title="Load Questions from File", filetypes=[("txt files", "*.txt")] )
#print(edQL.filename) #debug code
file1 = open(edQL.filename, 'r')
strvar=file1.read()
edQText.delete(1.0,END)
edQText.insert(INSERT, strvar)
return(edQText)
def edSave(edQW,edQText):
global myQuestions
global myLabel2
global curQ
myQuestions = edQText.get("1.0",END).splitlines()
window.deiconify()
if curQ==0:curQ=1
if curQ>len(myQuestions): curQ=len(myQuestions)
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ - 1])
myLabel2.grid(row=0, column=4)
edQW.destroy()
def edPCancel(edAW,object):
edAW.deiconify()
object.destroy()
def newPlayer(edAW):
global myPlayers
edAW.withdraw()
newPW = Toplevel(edAW)
newPW.title("New Player")
newPLabel = Label(newPW, text="Enter new player name:").grid(row=0,column=0)
newPEntry = Entry(newPW).grid(row=1,column=0)
newPOK = Button(newPW, text='OK').grid(row=2,column=3)
newPCancel = Button(newPW,text='Cancel', command=lambda:edPCancel(edAW,newPW)).grid(row=2,column=4)
def edAnswers(window):
window.withdraw()
myfile="\n".join(item for item in myAnswers)
edAW = Toplevel(window)
edAW.title("Edit Entries")
edALabel = Label(edAW, text="Player:")
edALabel.grid(row=0,column=0)
combo = ttk.Combobox(edAW,state="readonly",values=["Python", "C", "C++", "Java"])
combo.grid(row=0,column=1)
spacer=Label(edAW).grid(row=0,column=2)
edALabel = Label(edAW, text="Starting Score:", padx=10)
edALabel.grid(row=1,column=0)
edAText = Text(edAW)
edAText.insert(INSERT, 'Click Load... to load players and answers\nfrom a PM text file, or click New Player\nto add players manually.')
edAText.grid(column=0,columnspan=3, rowspan=10, padx=5, pady=5)
edALoad = Button(edAW,text="Load", padx=20, command=lambda:edQL(edAText)).grid(row=0, column=3, padx=10,pady=5)
edANP = Button(edAW, text="New Player", padx=4,command=lambda:newPlayer(edAW)).grid(row=1, column=3, padx=10,pady=5)
edACN = Button(edAW, text="Change Name", padx=0).grid(row=2 ,column=3, padx=10,pady=5)
edADP = Button(edAW, text="Delete Player", padx=0).grid(row=3, column=3, padx=10,pady=5)
edASave = Button(edAW,text="Save Changes",command=lambda:edSave(edAW,edAText)).grid(row=9, column=3,padx=10, pady=5)
edACancel = Button(edAW,text="Cancel", padx=20,command=lambda:edCancel(edAW)).grid(row=10, column=3, padx=10, pady=5)
edAW.rowconfigure(4, weight=1)
edAW.columnconfigure(2, weight=1)
return
def edQuestions(window):
window.withdraw()
myfile="\n".join(item for item in myQuestions)
edQW = Toplevel(window)
edQW.title("Edit Questions")
edQLabel = Label(edQW, text="Click Load... to load the questions from a text file, or just type them in here one per line")
edQLabel.grid(row=0,columnspan=2)
edQText = Text(edQW)
edQText.insert(INSERT,myfile)
edQText.grid(column=0, rowspan=10, padx=5, pady=5)
edQLoad = Button(edQW,text="Load", padx=20, command=lambda:edQL(edQText)).grid(row=1, column=1)
edQSave = Button(edQW,text="Save Changes",command=lambda:edSave(edQW,edQText)).grid(row=9, column=1)
edQCancel = Button(edQW,text="Cancel", padx=20,command=lambda:edCancel(edQW)).grid(row=10, column=1)
return
def validate_entry(text):
return text.isdecimal()
myQuestions = []
myAnswers = []
myPlayers = []
curQ=1
window = Tk()
window.geometry("680x450")
window.title("Sheep Score Foggies Edition")
Outputtype = IntVar()
Outputtype.set(1)
Gametype = IntVar()
Gametype.set(1)
Roundtype = IntVar()
Roundtype.set(0)
menubar = Menu(window)
window.config(menu=menubar)
fileMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="File",menu=fileMenu)
def dothis():
global myQuestions
print(myQuestions)
print(myAnswers)
print(myPlayers)
print(gtl[Gametype.get()])
print(rtl[Roundtype.get()])
def loadReveal():
global myQuestions, myLabel2, myPlayers, Gametype, Roundtype
filename = filedialog.askopenfilename(title="Load Sheep Scoring File", filetypes=[("Sheep Score 2017 File", "*.sheep17")])
tree = ET.parse(filename)
root = tree.getroot()
print(root.tag)
if root.tag == "SheepScore2012Game":
myQuestions = []
for child in root:
if child.tag == "Question":
myQuestions.append(child.text)
elif child.tag == "Player":
myPlayers.append([child.text,child.attrib['StartScore']])
elif child.tag == "ScoringMethod":
Gametype.set(gt[child.text])
elif child.tag == "Rounding":
Roundtype.set(rt[child.text])
elif child.tag == "Group":
pass # To do
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ - 1])
myLabel2.grid(row=0, column=4)
else:
qdown()
else:
messagebox.showinfo(title="Greetings", message="This is not a recognized sheep file!")
fileMenu.add_command(label="New Reveal", command=resetProgram)
fileMenu.add_command(label="Load Reveal...", command=loadReveal)
fileMenu.add_command(label="Save Reveal...")
fileMenu.add_command(label="Debug", command=dothis)
fileMenu.add_separator()
fileMenu.add_command(label="Exit",command=quit)
sheepMenu = Menu(menubar,tearoff=0)
menubar.add_cascade(label="Sheep",menu=sheepMenu)
sheepMenu.add_command(label="Edit Questions...", command=lambda:edQuestions(window))
sheepMenu.add_command(label="Edit Entries...", command=lambda:edAnswers(window))
scoringMenu=Menu(menubar,tearoff=0)
sheepMenu.add_cascade(label="Scoring",menu=scoringMenu)
scoringMenu.add_radiobutton(label="Sheep",value=1, variable=Gametype)
peehsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Peehs",menu=peehsMenu)
peehsMenu.add_radiobutton(label="DM Scoring",value=2, variable=Gametype)
peehsMenu.add_radiobutton(label="FB Scoring",value=3, variable=Gametype)
peehsMenu.add_radiobutton(label="Hybrid",value=4, variable=Gametype)
heepsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Heeps",menu=heepsMenu)
heepsMenu.add_radiobutton(label="2x Heep Bonus",value=7, variable=Gametype)
heepsMenu.add_radiobutton(label="1.5x Heep Bonus",value=6, variable=Gametype)
heepsMenu.add_radiobutton(label="No Heep Bonus",value=5, variable=Gametype)
scoringMenu.add_radiobutton(label="Kangaroo",value=8, variable=Gametype)
scoringMenu.add_radiobutton(label="Manual",value=9, variable=Gametype)
scoringMenu.add_separator()
roundingMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Rounding",menu=roundingMenu)
roundingMenu.add_radiobutton(label="No Rounding",value=0, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Up",value=1, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Down",value=2, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Nearest",value=3, variable=Roundtype)
outputMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="Output",menu=outputMenu)
outputMenu.add_command(label="Copy answers for this question")
outputMenu.add_command(label="Copy total scores up to this question")
outputMenu.add_command(label="Copy score table up to this question")
outputMenu.add_command(label="Copy Player list")
outputMenu.add_separator()
styleMenu=Menu(menubar,tearoff=0)
outputMenu.add_cascade(label="Output Style",menu=styleMenu)
styleMenu.add_radiobutton(label="Forum Table",value=1, variable=Outputtype)
styleMenu.add_radiobutton(label="Forum Formatted Text",value=2, variable=Outputtype)
styleMenu.add_radiobutton(label="Unformatted Text",value=3, variable=Outputtype)
def qdown():
global curQ
global myLabel2
if curQ>len(myQuestions): curQ = len(myQuestions)
if curQ>1:
curQ=curQ-1
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ-1])
myLabel2.grid(row=0, column=4)
def qup():
global curQ
global myLabel2
if curQ > len(myQuestions): curQ = len(myQuestions)
if curQ < len(myQuestions):
curQ = curQ + 1
else:
curQ == 1
myTextbox1.delete(0,END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(myQuestions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=myQuestions[curQ-1])
myLabel2.grid(row=0, column=4)
qButton1 = Button(window, text="<",command=qdown).grid(row=0,column=1)
qButton2 = Button(window, text=">",command=qup).grid(row=0,column=3)
myLabel1 = Label(window, text="Q #", padx=5).grid(row=0,column=0)
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0,column=4)
myTextbox1 = Entry(window,width=4 ,validate="key",
validatecommand=(window.register(validate_entry), "%S"))
myTextbox1.insert(INSERT,curQ)
myTextbox1.grid(row=0,column=2)
myTextbox2 = Text(window,state=DISABLED,padx=10,pady=5)
myTextbox2.grid(row=1,column=0,columnspan=5)
window.columnconfigure(4, weight=1)
window.mainloop()
Nice, I was looking at pygame recently, looks like a handy enough library.
RE: Sheek, the sheep game with a knockout twist. - Neowise - 06-07-2023
Update for @Sephiroth_Dude
Getting closer.
File load fully implemented.
New Reveal implemented.
Edit Questions fully implemented.
Edit entries. Mostly Done.
Now I getting into the world of groups.
I've been pushing them out for long enough.
I thought the save changes in the edit answers was going to be hard to update, but it was a 5 second job, I have done most of the work required in the change combo box selection code.
RE: Sheek, the sheep game with a knockout twist. - Neowise - 06-07-2023
Spoiler tag loses the indentations. wtf
Code: from tkinter import *
from tkinter import filedialog, messagebox, ttk
import xml.etree.ElementTree as ET
from enum import Enum
class EdPlayer:
def __init__(self):
self.Name = ""
self.Answers = ""
self.OriginalPosition = -1
self.StartScore = 0
self.NewPlayerOriginalPosition = -1
self.EdIndex = 0
self.NeedsRegrouping = False
def __init__(self, newName, newAnswers, start_score=0, origPos=-1):
self.Name = newName
self.Answers = newAnswers
self.OriginalPosition = origPos
self.StartScore = start_score
self.NewPlayerOriginalPosition = -1
self.EdIndex = 0
self.NeedsRegrouping = False
class ShGame:
class ShQuestion:
def __init__(self, ref_game, new_text):
self.Text = new_text
self.Groups= []
self._Game = ref_game
@property
def GameIndex(self):
return self._Game.Questions.index(self)
@property
def Game(self):
return self._Game
def StartNewGroup(self, new_text):
newGrp = ShGroup(self, new_text)
self.Groups.append(newGrp)
return newGrp
def SyncGroups(self):
self.Groups = [shg for shg in self.Groups if shg.Answers]
def GetAllAnswers(self):
all_answers = []
for grp in self.Groups:
all_answers.extend(grp.Answers)
return all_answers
# returns list of scores for this question
# SCORING METHODS
# Sheep: each player gets total answers in his group as his score
# Peehs1: incorrects = 1.5 * highest correct score
# Peehs2: incorrects = highest correct score + 0.5 * number of distinct
# correct answers
# Heep: highest score gets 0, 2nd highest get doubled
# Kangaroo: must be incorrect; correct answers get 0
def Scores(include_bonus):
curScore = {}
for plr in _Game.Players:
curScore[plr] = 0
if len(_Game.Players) == 0 or len(_Game.Questions) == 0:
return curScore
highest_score = 0
second_highest_score = 0
num_distinct_correct = 0
for grp in self.Groups:
for ans in grp.Answers:
if ans.Player not in curScore:
continue
curScore[ans.Player] = len(grp.Answers)
return curScore
# for peehs/heep
if grp.Correct:
num_distinct_correct += 1
if len(grp.Answers) > highest_score:
second_highest_score = highest_score
highest_score = len(grp.Answers)
elif len(grp.Answers) > second_highest_score and len(grp.Answers) < highest_score:
second_highest_score = len(grp.Answers)
# apply special scores depending on scoring method
for grp in self.Groups:
for ans in grp.Answers:
if ans.Player not in curScore:
continue
if self._Game.Method == ShMethod.Sheep:
if not grp.Correct:
curScore[ans.Player] = 0
# incorrect means invalid for sheep
elif self._Game.Method == ShMethod.PeehsDM:
# incorrect -> 1.5*sheep
if not grp.Correct:
curScore[ans.Player] = 1.5 * highest_score
elif self._Game.Method == ShMethod.PeehsFB:
# incorrect -> sheep + 0.5*distinct
if not grp.Correct:
curScore[ans.Player] = highest_score + 0.5 * num_distinct_correct
elif self._Game.Method == ShMethod.PeehsHybrid:
# incorrect -> sheep + 0.5*distinct
if not grp.Correct:
curScore[ans.Player] = 1.25 * highest_score + 0.25 * num_distinct_correct
elif _Game.Method == ShMethod.Heep or _Game.Method == ShMethod.Heep15 or _Game.Method == ShMethod.Heep2:
if curScore[ans.Player] == highest_score or not grp.Correct:
curScore[ans.Player] = 0
elif curScore[ans.Player] == second_highest_score:
if _Game.Method == ShMethod.Heep15:
curScore[ans.Player] *= 1.5
elif _Game.Method == ShMethod.Heep2:
curScore[ans.Player] *= 2
elif _Game.Method == ShMethod.Kangaroo:
if grp.Correct:
curScore[ans.Player] = 0
elif _Game.Method == ShMethod.Manual:
curScore[ans.Player] = 0
# apply rounding
if _Game.Rounding == ShRoundingType.Up:
curScore[ans.Player] = math.ceil(curScore[ans.Player])
elif _Game.Rounding == ShRoundingType.Down:
curScore[ans.Player] = math.floor(curScore[ans.Player])
elif _Game.Rounding == ShRoundingType.Nearest:
curScore[ans.Player] = round(curScore[ans.Player])
# apply player & group bonuses
if include_bonus:
temp_score = cur_score[ans.Player]
if grp.BonusType == ShBonusType.Override:
temp_score = grp.GroupBonus
elif grp.BonusType == ShBonusType.Add:
temp_score += grp.GroupBonus
if ans.BonusType == ShBonusType.Override:
temp_score = ans.AnswerBonus
elif ans.BonusType == ShBonusType.Add:
temp_score += ans.AnswerBonus
cur_score[ans.Player] = temp_score
def score_up_to(include_bonus):
cur_score = {}
next_score = {}
for plr in _Game.Players:
cur_score[plr] = 0
for que in _Game.Questions:
if que.GameIndex <= self.GameIndex:
next_score = que.scores(include_bonus)
for k, v in next_score.items():
if k in cur_score:
cur_score[k] += v
return cur_score
class ShPlayer:
counter = 0
def __init__(self, ref_game, player_name, start_score=0):
self._Game = ref_game
self.Name = player_name
self.Answers = []
self.StartScore = start_score
ShGame.ShPlayer.counter += 1
@property
def Count(self):
return self.counter
@property
def GameIndex(self):
return self._Game.Players.index(self)
@property
def Game(self):
return self._Game
def __del__(self):
for ans in self.Answers:
self.counter -= 1
ans.Group.Answers.remove(ans)
class ShGroup:
def __init__(self, ref_question, new_text):
self.Text = new_text
self.Correct = True
self.GroupBonus = 0
self.BonusType = NONE
self.Answers = [] # actual answers
self._Question = ref_question # reference to question
# constructor
# declares with an empty list for Answers
#self.Answers = [ShAnswer() for _ in range(len(ref_question.Game.Players))]
#self.Answers = [ShGame.ShAnswer(len(ref_question.Game.Players)) for _ in range(len(ref_question.Game.Players))]
@property
def Question(self):
return self._Question
# moves all answers to ref_group and deletes itself
def MergeToGroup(self, ref_group):
if ref_group == self:
# throw new Exception("Trying to merge a group to itself")
return
while len(self.Answers) != 0:
self.Answers[0].ChangeGroup(ref_group)
self._Question.Groups.remove(self)
def GetScore(self, include_bonus):
if len(self.Answers) == 0:
return 0
else:
try:
baseScore = _Question.Scores(False)[self.Answers[0].Player]
if include_bonus:
if self.BonusType == ShBonusType.Override:
return self.GroupBonus
elif self.BonusType == ShBonusType.Add:
return self.GroupBonus + baseScore
else:
return baseScore
else:
return baseScore
except:
return 0
def __del__(self):
for ans in self.Answers:
ans.Player.Answers.remove(ans)
class ShAnswer:
def __init__(self, ref_group, ref_player, new_text):
self.Text = new_text
self.AnswerBonus = 0
self._Group = ref_group
self._Player = ref_player
@property
def Group(self):
return self._Group
@property
def Player(self):
return self._Player
def ChangeGroup(self, ref_group):
if ref_group == self._Group:
return
if self._Group.Question != ref_group.Question:
raise Exception("Moving an answer to a group in a different question.")
oldGroup = self._Group
self._Group = ref_group
ref_group.Answers.append(self)
oldGroup.Answers.remove(self)
if len(oldGroup.Answers) == 0:
oldGroup.Question.Groups.remove(oldGroup)
def StartNewGroup(self):
oldGroup = self._Group
newGroup = ShGroup(_Group.Question, self.Text)
oldGroup.Question.Groups.append(newGroup)
self._Group = newGroup
newGroup.Answers.append(self)
oldGroup.Answers.remove(self)
if len(oldGroup.Answers) == 0:
oldGroup.Question.Groups.remove(oldGroup)
class ShMethod(Enum):
Sheep = 1
PeehsDM = 2
PeehsFB = 3
PeehsHybrid = 4
Heep = 5
Heep15 = 6
Heep2 = 7
Kangaroo = 8
Manual = 9
class ShBonusType(Enum):
NONE = 0
Add = 1
Override = 2
class ShRoundingType(Enum):
NONE = 0
Up = 1
Down = 2
Nearest = 3
def __init__(self,*args):
if len(args)==0:
self.Questions = []
self.Players = []
self.Method = self.ShMethod.Sheep
self.Rounding = self.ShRoundingType.NONE
elif len(args)==3:
new_questions=args[0]
new_players=args[1]
new_answers=args[2]
if len(new_answers) != len(new_questions) or len(new_answers[0]) != len(new_players):
raise Exception("Answer list must be size [num questions, num players]")
self.Questions = [ShQuestion(self, txt) for txt in new_questions]
self.Players = [ShPlayer(self, txt) for txt in new_players]
for iques in range(len(new_questions)):
for iplayer in range(len(new_players)):
new_group = ShGroup(self.Questions[iques], new_answers[iques][iplayer])
self.Questions[iques].Groups.append(new_group)
new_answer = ShAnswer(new_group, self.Players[iplayer], new_answers[iques][iplayer])
new_group.Answers.append(new_answer)
self.Players[iplayer].Answers.append(new_answer)
def __str__(self):
return 'This is a Game'
def loadReveal(self):
resetProgram()
#print (sg.__dict__)
global myLabel2, Roundtype
#filename = "C:/Users/keith/Desktop/sheep/80s2023.sheep17"
filename = filedialog.askopenfilename(title="Load Sheep Scoring File", filetypes=[("Sheep Score 2017 File", "*.sheep17")])
tree = ET.parse(filename)
root = tree.getroot()
#print(root.tag)
if root.tag == "SheepScore2012Game":
for child in root:
if child.tag == "ScoringMethod":
self.Method = self.ShMethod[child.text]
#Gametype.set(gt[child.text])
elif child.tag == "Rounding":
if child.text =="None":
child.text = "NONE"
self.Rounding = self.ShRoundingType[child.text]
#Roundtype.set(rt[child.text])
elif child.tag == "Question":
#print(child.attrib['GameIndex'], child.text)
qindex = int(child.attrib['GameIndex'])
while len(self.Questions) < qindex + 1:
self.Questions.append(self.ShQuestion(self, "(blank)"))
self.Questions[qindex].Text = child.text
elif child.tag == "Player":
pindex = int(child.attrib['GameIndex'])
start_score = child.attrib['StartScore']
while len(self.Players) < pindex + 1:
self.Players.append(self.ShPlayer(self, "(blank)", start_score))
self.Players[pindex].Name = child.text
elif child.tag == "Group":
group_q_index = int(child.attrib['QuestionIndex'])
tempcorrect = child.attrib['Correct']
tempgroupbonus = child.attrib['GroupBonus']
tempgroupbonustype = child.attrib['BonusType']
newGroup = self.ShGroup(self.Questions[group_q_index], "")
newGroup.Correct = tempcorrect
newGroup.GroupBonus = tempgroupbonus
newGroup.BonusType = tempgroupbonustype
self.Questions[group_q_index].Groups.append(newGroup)
#print(child.tag, child.text)
for item in child:
if item.tag == "Text":
newGroup.Text = item.text
elif item.tag == "Answer":
ans_p_index = int(item.attrib['PlayerIndex'])
tempansbonus = int(item.attrib["AnswerBonus"])
tempansbonustype = item.attrib['BonusType']
anstext = item.text
newAns = ShGame.ShAnswer(newGroup, self.Players[ans_p_index], anstext)
newGroup.Answers.append(newAns)
self.Players[ans_p_index].Answers.append(newAns)
if len(self.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=self.Questions[curQ - 1].Text)
myLabel2.grid(row=0, column=4)
else:
qdown()
else:
messagebox.showinfo(title="Greetings", message="This is not a recognized sheep file!")
def qdown():
global curQ
global myLabel2
if curQ>len(sg.Questions): curQ = len(sg.Questions)
if curQ>1:
curQ=curQ-1
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ-1].Text)
myLabel2.grid(row=0, column=4)
def qup():
global curQ
global myLabel2
if curQ > len(sg.Questions): curQ = len(sg.Questions)
if curQ < len(sg.Questions):
curQ = curQ + 1
else:
curQ == 1
myTextbox1.delete(0,END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ-1].Text)
myLabel2.grid(row=0, column=4)
def resetProgram():
global myTextbox1, myLabel2, players, curQ, current_var
sg.Questions = []
sg.Players = []
players=[]
curQ = 1
current_var.set("")
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
myLabel2.grid_forget()
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0, column=4)
return
def edQL(edQText):
edQL.filename = filedialog.askopenfilename(title="Load Questions from File", filetypes=[("txt files", "*.txt")] )
#print(edQL.filename) #debug code
file1 = open(edQL.filename, 'r')
strvar=file1.read()
edQText.delete(1.0,END)
edQText.insert(INSERT, strvar)
return(edQText)
def edSave(edQW,edQText):
global myLabel2
global curQ
sg.Questions = []
questions = edQText.get("1.0",END).splitlines()
qindex=0
for item in questions:
sg.Questions.append(ShGame.ShQuestion(qindex,questions[qindex]))
qindex+=1
window.deiconify()
if curQ==0:curQ=1
if curQ>len(sg.Questions): curQ=len(sg.Questions)
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ - 1].Text)
myLabel2.grid(row=0, column=4)
edQW.destroy()
def edPSave(edAW,edAText):
global players, score, myPlayers
if len(players)>0:
answers = edAText.get(1.0, END).splitlines()
if answers[-1].lstrip() == '':
del answers[-1]
index = 0
if len(answers) >= len(players[curP].Answers):
while index < len(players[curP].Answers):
if answers[index] != players[curP].Answers[index].Text:
players[curP].Answers[index].Text = answers[index]
index += 1
while index < len(answers):
players[curP].Answers.append(ShGame.ShAnswer(ShGame.ShGroup(index, ""), players[curP], answers[index]))
index += 1
if len(answers) < len(players[curP].Answers):
while index < len(answers):
if answers[index] != players[curP].Answers[index].Text:
players[curP].Answers[index].Text = answers[index]
index += 1
while index < len(players[curP].Answers):
del players[curP].Answers[index]
sg.Players=[]
x=0
for item in players:
sg.Players.append(item)
x=x+1
window.deiconify()
edAW.destroy()
def edPCancel(parent,child):
parent.deiconify()
child.destroy()
def edCancel(child):
window.deiconify()
child.destroy()
def edPOK(edAText,combo, edAW, newPW, newplayer, x=''):
global players, score, curP
players.append(ShGame.ShPlayer(sg,newplayer,0))
combo['values'] = [item.Name for item in players]
curP+=1
combo.current(curP)
PAnswers = []
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers = answers + item + "\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
edAW.deiconify()
newPW.destroy()
def newPlayer(edAText,combo, edAW):
edAW.withdraw()
newPW = Toplevel(edAW)
newPW.bind('<Return>', lambda x: edPOK(edAText,combo, edAW, newPW, newPEntry.get()))
newPW.title("New Player")
newPLabel = Label(newPW, text="Enter new player name:", padx=10, font=20).grid(row=0, column=0)
newPEntry = Entry(newPW, font=20)
newPEntry.grid(row=1, column=0)
newPOK = Button(newPW, text='OK', command=lambda: edPOK(edAText,combo, edAW, newPW, newPEntry.get())).grid(row=2,column=3)
newPCancel = Button(newPW, text='Cancel', command=lambda: edPCancel(edAW, newPW)).grid(row=2,column=4)
def TextBoxUpdate(edAText,combo):
global curP, current_var, players
#Get current answers
answers=edAText.get(1.0, END).splitlines()
if answers[-1].lstrip()=='':
del answers[-1]
index=0
if len (answers) >= len (players[curP].Answers):
while index < len(players[curP].Answers):
if answers[index]!=players[curP].Answers[index].Text:
players[curP].Answers[index].Text=answers[index]
index+=1
while index < len(answers):
players[curP].Answers.append(ShGame.ShAnswer(ShGame.ShGroup(index,""),players[curP],answers[index]))
index+=1
if len(answers) < len(players[curP].Answers):
while index < len(answers):
if answers[index]!=players[curP].Answers[index].Text:
players[curP].Answers[index].Text=answers[index]
index+=1
while index < len(players[curP].Answers):
del players[curP].Answers[index]
current_value = current_var.get()
index=0
for item in players:
if item.Name==current_value:
curP=index
else: index+=1
if len(players) != 0:
combo.current(curP)
PAnswers=[]
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers=answers+item+"\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
def edAnswers(window):
global players, curP, current_var
players = []
for item in sg.Players:
players.append(item)
curP = len(players)-1
window.withdraw()
edAW = Toplevel(window)
edAW.bind("<<ComboboxSelected>>", lambda x: TextBoxUpdate(edAText,combo))
edAW.title("Edit Entries")
edALabel = Label(edAW, text="Player:")
edALabel.grid(row=0, column=0)
combo = ttk.Combobox(edAW,textvariable=current_var, state="readonly", values=[item.Name for item in players])
if len(players) != 0:
combo.current(curP)
PAnswers=[]
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers=answers+item+"\n"
combo.grid(row=0, column=1)
spacer = Label(edAW).grid(row=0, column=2)
edALabel = Label(edAW, text="Starting Score:", padx=10)
edALabel.grid(row=1, column=0)
edAText = Text(edAW)
if len(players)==0:
edAText.insert(INSERT,'Click Load... to load players and answers\nfrom a PM text file, or click New Player\nto add players manually.')
else:
edAText.insert(INSERT,answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
edALoad = Button(edAW, text="Load", padx=20, command=lambda: edQL(edAText)).grid(row=0,column=3,padx=10,pady=5)
edANP = Button(edAW, text="New Player", padx=4, command=lambda: newPlayer(edAText,combo, edAW)).grid(row=1,column=3,padx=10,pady=5)
edACN = Button(edAW, text="Change Name", padx=0).grid(row=2, column=3, padx=10, pady=5)
edADP = Button(edAW, text="Delete Player", padx=0).grid(row=3, column=3, padx=10, pady=5)
edASave = Button(edAW, text="Save Changes", command=lambda: edPSave(edAW, edAText)).grid(row=9, column=3,padx=10, pady=5)
edACancel = Button(edAW, text="Cancel", padx=20, command=lambda: edCancel(edAW)).grid(row=10, column=3,padx=10, pady=5)
edAW.rowconfigure(4, weight=1)
edAW.columnconfigure(2, weight=1)
return
def edQuestions(window):
window.withdraw()
myfile = "\n".join(item.Text.lstrip() for item in sg.Questions)
edQW = Toplevel(window)
edQW.title("Edit Questions")
edQLabel = Label(edQW,text="Click Load... to load the questions from a text file, or just type them in here one per line")
edQLabel.grid(row=0, columnspan=2)
edQText = Text(edQW)
edQText.insert(INSERT, myfile)
edQText.grid(column=0, rowspan=10, padx=5, pady=5)
edQLoad = Button(edQW, text="Load", padx=20, command=lambda: edQL(edQText)).grid(row=1, column=1)
edQSave = Button(edQW, text="Save Changes", command=lambda: edSave(edQW, edQText)).grid(row=9, column=1)
edQCancel = Button(edQW, text="Cancel", padx=20, command=lambda: edCancel(edQW)).grid(row=10, column=1)
return
def validate_entry(text):
return text.isdecimal()
def outPlayerscore():
print("[", end="")
for i in myPlayers:
if i != myPlayers[-1]:
print(i.score, end=",")
else:
print(i.score, end="")
print("]")
def dothis():
print(sg)
print(sg.__dict__)
print(sg.Questions[0].__dict__)
gt= {'Sheep':1,'PeehsDM':2, 'PeehsFB':3, 'PeehsHybrid':4, 'Heep':5, 'Heep15':6, 'Heep2':7, 'Kangaroo':8, 'Manual':9}
gtl=['filler','Sheep','PeehsDM','PeehsFB','PeehsHybrid','Heep','Heep15','Heep2','Kangaroo','Manual']
rt= {'None':0,'Up':1,'Down':2,'Nearest':3}
rtl=['None','Up','Down','Nearest']
bt= {'None':1, 'Add':2, 'Override':3}
btl=['filler','None', 'Add', 'Override']
sg = ShGame()
players=[]
score=[]
curQ=1
curP=1
window = Tk()
window.geometry("680x450")
window.title("Sheep Score Foggies Edition")
Outputtype = IntVar()
Outputtype.set(1)
Gametype = IntVar()
Gametype.set(1)
Roundtype = IntVar()
Roundtype.set(0)
current_var = StringVar()
menubar = Menu(window)
window.config(menu=menubar)
fileMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="File",menu=fileMenu)
fileMenu.add_command(label="New Reveal", command=resetProgram)
fileMenu.add_command(label="Load Reveal...", command=sg.loadReveal)
fileMenu.add_command(label="Save Reveal...")
fileMenu.add_command(label="Debug", command=dothis)
fileMenu.add_separator()
fileMenu.add_command(label="Exit",command=quit)
sheepMenu = Menu(menubar,tearoff=0)
menubar.add_cascade(label="Sheep",menu=sheepMenu)
sheepMenu.add_command(label="Edit Questions...", command=lambda:edQuestions(window))
sheepMenu.add_command(label="Edit Entries...", command=lambda:edAnswers(window))
scoringMenu=Menu(menubar,tearoff=0)
sheepMenu.add_cascade(label="Scoring",menu=scoringMenu)
scoringMenu.add_radiobutton(label="Sheep",value=1, variable=Gametype)
peehsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Peehs",menu=peehsMenu)
peehsMenu.add_radiobutton(label="DM Scoring",value=2, variable=Gametype)
peehsMenu.add_radiobutton(label="FB Scoring",value=3, variable=Gametype)
peehsMenu.add_radiobutton(label="Hybrid",value=4, variable=Gametype)
heepsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Heeps",menu=heepsMenu)
heepsMenu.add_radiobutton(label="2x Heep Bonus",value=7, variable=Gametype)
heepsMenu.add_radiobutton(label="1.5x Heep Bonus",value=6, variable=Gametype)
heepsMenu.add_radiobutton(label="No Heep Bonus",value=5, variable=Gametype)
scoringMenu.add_radiobutton(label="Kangaroo",value=8, variable=Gametype)
scoringMenu.add_radiobutton(label="Manual",value=9, variable=Gametype)
scoringMenu.add_separator()
roundingMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Rounding",menu=roundingMenu)
roundingMenu.add_radiobutton(label="No Rounding",value=0, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Up",value=1, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Down",value=2, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Nearest",value=3, variable=Roundtype)
outputMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="Output",menu=outputMenu)
outputMenu.add_command(label="Copy answers for this question")
outputMenu.add_command(label="Copy total scores up to this question")
outputMenu.add_command(label="Copy score table up to this question")
outputMenu.add_command(label="Copy Player list")
outputMenu.add_separator()
styleMenu=Menu(menubar,tearoff=0)
outputMenu.add_cascade(label="Output Style",menu=styleMenu)
styleMenu.add_radiobutton(label="Forum Table",value=1, variable=Outputtype)
styleMenu.add_radiobutton(label="Forum Formatted Text",value=2, variable=Outputtype)
styleMenu.add_radiobutton(label="Unformatted Text",value=3, variable=Outputtype)
qButton1 = Button(window, text="<",command=qdown).grid(row=0,column=1)
qButton2 = Button(window, text=">",command=qup).grid(row=0,column=3)
myLabel1 = Label(window, text="Q #", padx=5).grid(row=0,column=0)
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0,column=4)
myTextbox1 = Entry(window,width=4 ,validate="key",
validatecommand=(window.register(validate_entry), "%S"))
myTextbox1.insert(INSERT,curQ)
myTextbox1.grid(row=0,column=2)
myTextbox2 = Text(window,state=DISABLED,padx=10,pady=5)
myTextbox2.grid(row=1,column=0,columnspan=5)
window.columnconfigure(4, weight=1)
window.mainloop()
RE: Sheek, the sheep game with a knockout twist. - Neowise - 06-07-2023
better
btw, code runs on https://replit.com/
So, when it is finished, you can run it online, and store your reveal in You replit workspace, just don't share an invite with your players before you reveal
RE: Sheek, the sheep game with a knockout twist. - Neowise - 08-07-2023
Got a start on the groups.
No sorting yet.
Code: from tkinter import *
from tkinter import filedialog, messagebox, ttk
import xml.etree.ElementTree as ET
from enum import Enum
class EdPlayer:
def __init__(self):
self.Name = ""
self.Answers = ""
self.OriginalPosition = -1
self.StartScore = 0
self.NewPlayerOriginalPosition = -1
self.EdIndex = 0
self.NeedsRegrouping = False
def __init__(self, newName, newAnswers, start_score=0, origPos=-1):
self.Name = newName
self.Answers = newAnswers
self.OriginalPosition = origPos
self.StartScore = start_score
self.NewPlayerOriginalPosition = -1
self.EdIndex = 0
self.NeedsRegrouping = False
class ShGame:
class ShQuestion:
def __init__(self, ref_game, new_text):
self.Text = new_text
self.Groups= []
self._Game = ref_game
@property
def GameIndex(self):
return self._Game.Questions.index(self)
@property
def Game(self):
return self._Game
def StartNewGroup(self, new_text):
newGrp = ShGroup(self, new_text)
self.Groups.append(newGrp)
return newGrp
def SyncGroups(self):
self.Groups = [shg for shg in self.Groups if shg.Answers]
def GetAllAnswers(self):
all_answers = []
for grp in self.Groups:
all_answers.extend(grp.Answers)
return all_answers
# returns list of scores for this question
# SCORING METHODS
# Sheep: each player gets total answers in his group as his score
# Peehs1: incorrects = 1.5 * highest correct score
# Peehs2: incorrects = highest correct score + 0.5 * number of distinct
# correct answers
# Heep: highest score gets 0, 2nd highest get doubled
# Kangaroo: must be incorrect; correct answers get 0
def Scores(include_bonus):
curScore = {}
for plr in _Game.Players:
curScore[plr] = 0
if len(_Game.Players) == 0 or len(_Game.Questions) == 0:
return curScore
highest_score = 0
second_highest_score = 0
num_distinct_correct = 0
for grp in self.Groups:
for ans in grp.Answers:
if ans.Player not in curScore:
continue
curScore[ans.Player] = len(grp.Answers)
return curScore
# for peehs/heep
if grp.Correct:
num_distinct_correct += 1
if len(grp.Answers) > highest_score:
second_highest_score = highest_score
highest_score = len(grp.Answers)
elif len(grp.Answers) > second_highest_score and len(grp.Answers) < highest_score:
second_highest_score = len(grp.Answers)
# apply special scores depending on scoring method
for grp in self.Groups:
for ans in grp.Answers:
if ans.Player not in curScore:
continue
if self._Game.Method == ShMethod.Sheep:
if not grp.Correct:
curScore[ans.Player] = 0
# incorrect means invalid for sheep
elif self._Game.Method == ShMethod.PeehsDM:
# incorrect -> 1.5*sheep
if not grp.Correct:
curScore[ans.Player] = 1.5 * highest_score
elif self._Game.Method == ShMethod.PeehsFB:
# incorrect -> sheep + 0.5*distinct
if not grp.Correct:
curScore[ans.Player] = highest_score + 0.5 * num_distinct_correct
elif self._Game.Method == ShMethod.PeehsHybrid:
# incorrect -> sheep + 0.5*distinct
if not grp.Correct:
curScore[ans.Player] = 1.25 * highest_score + 0.25 * num_distinct_correct
elif _Game.Method == ShMethod.Heep or _Game.Method == ShMethod.Heep15 or _Game.Method == ShMethod.Heep2:
if curScore[ans.Player] == highest_score or not grp.Correct:
curScore[ans.Player] = 0
elif curScore[ans.Player] == second_highest_score:
if _Game.Method == ShMethod.Heep15:
curScore[ans.Player] *= 1.5
elif _Game.Method == ShMethod.Heep2:
curScore[ans.Player] *= 2
elif _Game.Method == ShMethod.Kangaroo:
if grp.Correct:
curScore[ans.Player] = 0
elif _Game.Method == ShMethod.Manual:
curScore[ans.Player] = 0
# apply rounding
if _Game.Rounding == ShRoundingType.Up:
curScore[ans.Player] = math.ceil(curScore[ans.Player])
elif _Game.Rounding == ShRoundingType.Down:
curScore[ans.Player] = math.floor(curScore[ans.Player])
elif _Game.Rounding == ShRoundingType.Nearest:
curScore[ans.Player] = round(curScore[ans.Player])
# apply player & group bonuses
if include_bonus:
temp_score = cur_score[ans.Player]
if grp.BonusType == ShBonusType.Override:
temp_score = grp.GroupBonus
elif grp.BonusType == ShBonusType.Add:
temp_score += grp.GroupBonus
if ans.BonusType == ShBonusType.Override:
temp_score = ans.AnswerBonus
elif ans.BonusType == ShBonusType.Add:
temp_score += ans.AnswerBonus
cur_score[ans.Player] = temp_score
def score_up_to(include_bonus):
cur_score = {}
next_score = {}
for plr in _Game.Players:
cur_score[plr] = 0
for que in _Game.Questions:
if que.GameIndex <= self.GameIndex:
next_score = que.scores(include_bonus)
for k, v in next_score.items():
if k in cur_score:
cur_score[k] += v
return cur_score
class ShPlayer:
counter = 0
def __init__(self, ref_game, player_name, start_score=0):
self._Game = ref_game
self.Name = player_name
self.Answers = []
self.StartScore = start_score
ShGame.ShPlayer.counter += 1
@property
def Count(self):
return self.counter
@property
def GameIndex(self):
return self._Game.Players.index(self)
@property
def Game(self):
return self._Game
def __del__(self):
for ans in self.Answers:
self.counter -= 1
ans.Group.Answers.remove(ans)
class ShGroup:
def __init__(self, ref_question, new_text):
self.Text = new_text
self.Correct = True
self.GroupBonus = 0
self.BonusType = NONE
self.Answers = [] # actual answers
self._Question = ref_question # reference to question
# constructor
# declares with an empty list for Answers
#self.Answers = [ShAnswer() for _ in range(len(ref_question.Game.Players))]
#self.Answers = [ShGame.ShAnswer(len(ref_question.Game.Players)) for _ in range(len(ref_question.Game.Players))]
@property
def Question(self):
return self._Question
# moves all answers to ref_group and deletes itself
def MergeToGroup(self, ref_group):
if ref_group == self:
# throw new Exception("Trying to merge a group to itself")
return
while len(self.Answers) != 0:
self.Answers[0].ChangeGroup(ref_group)
self._Question.Groups.remove(self)
def GetScore(self, include_bonus):
if len(self.Answers) == 0:
return 0
else:
try:
baseScore = _Question.Scores(False)[self.Answers[0].Player]
if include_bonus:
if self.BonusType == ShBonusType.Override:
return self.GroupBonus
elif self.BonusType == ShBonusType.Add:
return self.GroupBonus + baseScore
else:
return baseScore
else:
return baseScore
except:
return 0
def __del__(self):
for ans in self.Answers:
ans.Player.Answers.remove(ans)
class ShAnswer:
def __init__(self, ref_group, ref_player, new_text):
self.Text = new_text
self.AnswerBonus = 0
self._Group = ref_group
self._Player = ref_player
@property
def Group(self):
return self._Group
@property
def Player(self):
return self._Player
def ChangeGroup(self, ref_group):
if ref_group == self._Group:
return
if self._Group.Question != ref_group.Question:
raise Exception("Moving an answer to a group in a different question.")
oldGroup = self._Group
self._Group = ref_group
ref_group.Answers.append(self)
oldGroup.Answers.remove(self)
if len(oldGroup.Answers) == 0:
oldGroup.Question.Groups.remove(oldGroup)
def StartNewGroup(self):
oldGroup = self._Group
newGroup = ShGroup(_Group.Question, self.Text)
oldGroup.Question.Groups.append(newGroup)
self._Group = newGroup
newGroup.Answers.append(self)
oldGroup.Answers.remove(self)
if len(oldGroup.Answers) == 0:
oldGroup.Question.Groups.remove(oldGroup)
class ShMethod(Enum):
Sheep = 1
PeehsDM = 2
PeehsFB = 3
PeehsHybrid = 4
Heep = 5
Heep15 = 6
Heep2 = 7
Kangaroo = 8
Manual = 9
class ShBonusType(Enum):
NONE = 0
Add = 1
Override = 2
class ShRoundingType(Enum):
NONE = 0
Up = 1
Down = 2
Nearest = 3
def __init__(self,*args):
if len(args)==0:
self.Questions = []
self.Players = []
self.Method = self.ShMethod.Sheep
self.Rounding = self.ShRoundingType.NONE
elif len(args)==3:
new_questions=args[0]
new_players=args[1]
new_answers=args[2]
if len(new_answers) != len(new_questions) or len(new_answers[0]) != len(new_players):
raise Exception("Answer list must be size [num questions, num players]")
self.Questions = [ShQuestion(self, txt) for txt in new_questions]
self.Players = [ShPlayer(self, txt) for txt in new_players]
for iques in range(len(new_questions)):
for iplayer in range(len(new_players)):
new_group = ShGroup(self.Questions[iques], new_answers[iques][iplayer])
self.Questions[iques].Groups.append(new_group)
new_answer = ShAnswer(new_group, self.Players[iplayer], new_answers[iques][iplayer])
new_group.Answers.append(new_answer)
self.Players[iplayer].Answers.append(new_answer)
def __str__(self):
return 'This is a Game'
def loadReveal(self):
resetProgram()
#print (sg.__dict__)
global myLabel2, Roundtype
#filename = "C:/Users/keith/Desktop/sheep/80s2023.sheep17"
filename = filedialog.askopenfilename(title="Load Sheep Scoring File", filetypes=[("Sheep Score 2017 File", "*.sheep17")])
tree = ET.parse(filename)
root = tree.getroot()
#print(root.tag)
if root.tag == "SheepScore2012Game":
for child in root:
if child.tag == "ScoringMethod":
self.Method = self.ShMethod[child.text]
#Gametype.set(gt[child.text])
elif child.tag == "Rounding":
if child.text =="None":
child.text = "NONE"
self.Rounding = self.ShRoundingType[child.text]
#Roundtype.set(rt[child.text])
elif child.tag == "Question":
#print(child.attrib['GameIndex'], child.text)
qindex = int(child.attrib['GameIndex'])
while len(self.Questions) < qindex + 1:
self.Questions.append(self.ShQuestion(self, "(blank)"))
self.Questions[qindex].Text = child.text
elif child.tag == "Player":
pindex = int(child.attrib['GameIndex'])
start_score = child.attrib['StartScore']
while len(self.Players) < pindex + 1:
self.Players.append(self.ShPlayer(self, "(blank)", start_score))
self.Players[pindex].Name = child.text
elif child.tag == "Group":
group_q_index = int(child.attrib['QuestionIndex'])
tempcorrect = child.attrib['Correct']
tempgroupbonus = child.attrib['GroupBonus']
tempgroupbonustype = child.attrib['BonusType']
newGroup = self.ShGroup(self.Questions[group_q_index], "")
newGroup.Correct = tempcorrect
newGroup.GroupBonus = tempgroupbonus
newGroup.BonusType = tempgroupbonustype
self.Questions[group_q_index].Groups.append(newGroup)
#print(child.tag, child.text)
for item in child:
if item.tag == "Text":
newGroup.Text = item.text
elif item.tag == "Answer":
ans_p_index = int(item.attrib['PlayerIndex'])
tempansbonus = int(item.attrib["AnswerBonus"])
tempansbonustype = item.attrib['BonusType']
anstext = item.text
newAns = ShGame.ShAnswer(newGroup, self.Players[ans_p_index], anstext)
newGroup.Answers.append(newAns)
self.Players[ans_p_index].Answers.append(newAns)
if len(self.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=self.Questions[curQ - 1].Text)
myLabel2.grid(row=0, column=4)
else:
qdown()
updateTreeview()
else:
messagebox.showinfo(title="Greetings", message="This is not a recognized sheep file!")
def qdown():
global curQ
global myLabel2
if curQ>len(sg.Questions): curQ = len(sg.Questions)
if curQ>1:
curQ=curQ-1
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ-1].Text)
myLabel2.grid(row=0, column=4)
updateTreeview()
def qup():
global curQ
global myLabel2
if curQ > len(sg.Questions): curQ = len(sg.Questions)
if curQ < len(sg.Questions):
curQ = curQ + 1
else:
curQ == 1
myTextbox1.delete(0,END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ-1].Text)
myLabel2.grid(row=0, column=4)
updateTreeview()
def resetProgram():
global myTextbox1, myLabel2, players, curQ, current_var
sg.Questions = []
sg.Players = []
players=[]
curQ = 1
current_var.set("")
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
myLabel2.grid_forget()
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0, column=4)
return
def edQL(edQText):
edQL.filename = filedialog.askopenfilename(title="Load Questions from File", filetypes=[("txt files", "*.txt")] )
#print(edQL.filename) #debug code
file1 = open(edQL.filename, 'r')
strvar=file1.read()
edQText.delete(1.0,END)
edQText.insert(INSERT, strvar)
return(edQText)
def edSave(edQW,edQText):
global myLabel2, curQ
sg.Questions = []
questions = edQText.get("1.0",END).splitlines()
qindex=0
for item in questions:
sg.Questions.append(ShGame.ShQuestion(qindex,questions[qindex]))
qindex+=1
window.deiconify()
if curQ==0:curQ=1
if curQ>len(sg.Questions): curQ=len(sg.Questions)
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ - 1].Text)
myLabel2.grid(row=0, column=4)
edQW.destroy()
def edPSave(edAW,edAText):
global players, score, myPlayers
if len(players)>0:
answers = edAText.get(1.0, END).splitlines()
if answers[-1].lstrip() == '':
del answers[-1]
index = 0
if len(answers) >= len(players[curP].Answers):
while index < len(players[curP].Answers):
if answers[index] != players[curP].Answers[index].Text:
players[curP].Answers[index].Text = answers[index]
index += 1
while index < len(answers):
players[curP].Answers.append(ShGame.ShAnswer(ShGame.ShGroup(index, ""), players[curP], answers[index]))
index += 1
if len(answers) < len(players[curP].Answers):
while index < len(answers):
if answers[index] != players[curP].Answers[index].Text:
players[curP].Answers[index].Text = answers[index]
index += 1
while index < len(players[curP].Answers):
del players[curP].Answers[index]
sg.Players=[]
x=0
for item in players:
sg.Players.append(item)
x=x+1
updateTreeview()
window.deiconify()
edAW.destroy()
def edPCancel(parent,child):
parent.deiconify()
child.destroy()
def edCancel(child):
window.deiconify()
child.destroy()
def edPOK(edAText,combo, edAW, newPW, newplayer, x=''):
global players, score, curP
players.append(ShGame.ShPlayer(sg,newplayer,0))
combo['values'] = [item.Name for item in players]
curP+=1
combo.current(curP)
PAnswers = []
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers = answers + item + "\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
edAW.deiconify()
newPW.destroy()
def newPlayer(edAText,combo, edAW):
edAW.withdraw()
newPW = Toplevel(edAW)
newPW.bind('<Return>', lambda x: edPOK(edAText,combo, edAW, newPW, newPEntry.get()))
newPW.title("New Player")
newPLabel = Label(newPW, text="Enter new player name:", padx=10, font=20).grid(row=0, column=0)
newPEntry = Entry(newPW, font=20)
newPEntry.grid(row=1, column=0)
newPOK = Button(newPW, text='OK', command=lambda: edPOK(edAText,combo, edAW, newPW, newPEntry.get())).grid(row=2,column=3)
newPCancel = Button(newPW, text='Cancel', command=lambda: edPCancel(edAW, newPW)).grid(row=2,column=4)
def TextBoxUpdate(edAText,combo):
global curP, current_var, players
#Get current answers
answers=edAText.get(1.0, END).splitlines()
if answers[-1].lstrip()=='':
del answers[-1]
index=0
if len (answers) >= len (players[curP].Answers):
while index < len(players[curP].Answers):
if answers[index]!=players[curP].Answers[index].Text:
players[curP].Answers[index].Text=answers[index]
index+=1
while index < len(answers):
players[curP].Answers.append(ShGame.ShAnswer(ShGame.ShGroup(index,""),players[curP],answers[index]))
index+=1
if len(answers) < len(players[curP].Answers):
while index < len(answers):
if answers[index]!=players[curP].Answers[index].Text:
players[curP].Answers[index].Text=answers[index]
index+=1
while index < len(players[curP].Answers):
del players[curP].Answers[index]
current_value = current_var.get()
index=0
for item in players:
if item.Name==current_value:
curP=index
else: index+=1
if len(players) != 0:
combo.current(curP)
PAnswers=[]
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers=answers+item+"\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
def edAnswers(window):
global players, curP, current_var
players = []
for item in sg.Players:
players.append(item)
curP = len(players)-1
window.withdraw()
edAW = Toplevel(window)
edAW.bind("<<ComboboxSelected>>", lambda x: TextBoxUpdate(edAText,combo))
edAW.title("Edit Entries")
edALabel = Label(edAW, text="Player:")
edALabel.grid(row=0, column=0)
combo = ttk.Combobox(edAW,textvariable=current_var, state="readonly", values=[item.Name for item in players])
if len(players) != 0:
combo.current(curP)
PAnswers=[]
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers=answers+item+"\n"
combo.grid(row=0, column=1)
spacer = Label(edAW).grid(row=0, column=2)
edALabel = Label(edAW, text="Starting Score:", padx=10)
edALabel.grid(row=1, column=0)
edAText = Text(edAW)
if len(players)==0:
edAText.insert(INSERT,'Click Load... to load players and answers\nfrom a PM text file, or click New Player\nto add players manually.')
else:
edAText.insert(INSERT,answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
edALoad = Button(edAW, text="Load", padx=20, command=lambda: edQL(edAText)).grid(row=0,column=3,padx=10,pady=5)
edANP = Button(edAW, text="New Player", padx=4, command=lambda: newPlayer(edAText,combo, edAW)).grid(row=1,column=3,padx=10,pady=5)
edACN = Button(edAW, text="Change Name", padx=0).grid(row=2, column=3, padx=10, pady=5)
edADP = Button(edAW, text="Delete Player", padx=0).grid(row=3, column=3, padx=10, pady=5)
edASave = Button(edAW, text="Save Changes", command=lambda: edPSave(edAW, edAText)).grid(row=9, column=3,padx=10, pady=5)
edACancel = Button(edAW, text="Cancel", padx=20, command=lambda: edCancel(edAW)).grid(row=10, column=3,padx=10, pady=5)
edAW.rowconfigure(4, weight=1)
edAW.columnconfigure(2, weight=1)
return
def edQuestions(window):
window.withdraw()
myfile = "\n".join(item.Text.lstrip() for item in sg.Questions)
edQW = Toplevel(window)
edQW.title("Edit Questions")
edQLabel = Label(edQW,text="Click Load... to load the questions from a text file, or just type them in here one per line")
edQLabel.grid(row=0, columnspan=2)
edQText = Text(edQW)
edQText.insert(INSERT, myfile)
edQText.grid(column=0, rowspan=10, padx=5, pady=5)
edQLoad = Button(edQW, text="Load", padx=20, command=lambda: edQL(edQText)).grid(row=1, column=1)
edQSave = Button(edQW, text="Save Changes", command=lambda: edSave(edQW, edQText)).grid(row=9, column=1)
edQCancel = Button(edQW, text="Cancel", padx=20, command=lambda: edCancel(edQW)).grid(row=10, column=1)
return
def validate_entry(text):
return text.isdecimal()
def outPlayerscore():
print("[", end="")
for i in myPlayers:
if i != myPlayers[-1]:
print(i.score, end=",")
else:
print(i.score, end="")
print("]")
def dothis():
print(sg)
print(sg.__dict__)
print(sg.Questions[0].__dict__)
def updateTreeview():
global myTreeview,curQ
if len(sg.Questions) != 0:
myTreeview.grid_forget()
myTreeview = ttk.Treeview(window, show="tree")
if (curQ > len(sg.Questions)):
curQ == len(sg.Questions)
if (curQ < 1):
curQ = 1
curQuestion = sg.Questions[curQ - 1]
# give instructions if no players loaded
if (len(sg.Players) == 0):
myTreeview.insert('', 'end', text="Click sheep > Edit Entries... to add entries.", iid=0)
myTreeview.grid(row=1, column=0, columnspan=5, sticky='NSEW', padx=10, pady=5)
curgroup = 0
curItem = 0
#print(sg.Questions[0].Groups[0].__dict__)#.Answers[0].__dict__)
# loop through each group
for group in curQuestion.Groups:
group_node = myTreeview.insert("", "end", text=group.Text + " - [" + str(len(group.Answers))+"]")
for answer in group.Answers:
myTreeview.insert(group_node, "end", text=answer.Text + " - " + answer.Player.Name)
myTreeview.grid(row=1, column=0, columnspan=5, sticky='NSEW', padx=10, pady=5)
# text will be added later so don't bother with it in this function
# for grp in curQuestion:
# curGroup=myTreeview.insert('','end',text=".",iid=0)
# myTreeview.insert('','end',text="this is text",iid=0)
gt= {'Sheep':1,'PeehsDM':2, 'PeehsFB':3, 'PeehsHybrid':4, 'Heep':5, 'Heep15':6, 'Heep2':7, 'Kangaroo':8, 'Manual':9}
gtl=['filler','Sheep','PeehsDM','PeehsFB','PeehsHybrid','Heep','Heep15','Heep2','Kangaroo','Manual']
rt= {'None':0,'Up':1,'Down':2,'Nearest':3}
rtl=['None','Up','Down','Nearest']
bt= {'None':1, 'Add':2, 'Override':3}
btl=['filler','None', 'Add', 'Override']
sg = ShGame()
players=[]
score=[]
curQ=1
curP=1
window = Tk()
window.geometry("680x450")
window.title("Sheep Score Foggies Edition")
Outputtype = IntVar()
Outputtype.set(1)
Gametype = IntVar()
Gametype.set(1)
Roundtype = IntVar()
Roundtype.set(0)
current_var = StringVar()
menubar = Menu(window)
window.config(menu=menubar)
fileMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="File",menu=fileMenu)
fileMenu.add_command(label="New Reveal", command=resetProgram)
fileMenu.add_command(label="Load Reveal...", command=sg.loadReveal)
fileMenu.add_command(label="Save Reveal...")
fileMenu.add_command(label="Debug", command=dothis)
fileMenu.add_separator()
fileMenu.add_command(label="Exit",command=quit)
sheepMenu = Menu(menubar,tearoff=0)
menubar.add_cascade(label="Sheep",menu=sheepMenu)
sheepMenu.add_command(label="Edit Questions...", command=lambda:edQuestions(window))
sheepMenu.add_command(label="Edit Entries...", command=lambda:edAnswers(window))
scoringMenu=Menu(menubar,tearoff=0)
sheepMenu.add_cascade(label="Scoring",menu=scoringMenu)
scoringMenu.add_radiobutton(label="Sheep",value=1, variable=Gametype)
peehsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Peehs",menu=peehsMenu)
peehsMenu.add_radiobutton(label="DM Scoring",value=2, variable=Gametype)
peehsMenu.add_radiobutton(label="FB Scoring",value=3, variable=Gametype)
peehsMenu.add_radiobutton(label="Hybrid",value=4, variable=Gametype)
heepsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Heeps",menu=heepsMenu)
heepsMenu.add_radiobutton(label="2x Heep Bonus",value=7, variable=Gametype)
heepsMenu.add_radiobutton(label="1.5x Heep Bonus",value=6, variable=Gametype)
heepsMenu.add_radiobutton(label="No Heep Bonus",value=5, variable=Gametype)
scoringMenu.add_radiobutton(label="Kangaroo",value=8, variable=Gametype)
scoringMenu.add_radiobutton(label="Manual",value=9, variable=Gametype)
scoringMenu.add_separator()
roundingMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Rounding",menu=roundingMenu)
roundingMenu.add_radiobutton(label="No Rounding",value=0, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Up",value=1, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Down",value=2, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Nearest",value=3, variable=Roundtype)
outputMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="Output",menu=outputMenu)
outputMenu.add_command(label="Copy answers for this question")
outputMenu.add_command(label="Copy total scores up to this question")
outputMenu.add_command(label="Copy score table up to this question")
outputMenu.add_command(label="Copy Player list")
outputMenu.add_separator()
styleMenu=Menu(menubar,tearoff=0)
outputMenu.add_cascade(label="Output Style",menu=styleMenu)
styleMenu.add_radiobutton(label="Forum Table",value=1, variable=Outputtype)
styleMenu.add_radiobutton(label="Forum Formatted Text",value=2, variable=Outputtype)
styleMenu.add_radiobutton(label="Unformatted Text",value=3, variable=Outputtype)
qButton1 = Button(window, text="<",command=qdown).grid(row=0,column=1)
qButton2 = Button(window, text=">",command=qup).grid(row=0,column=3)
myLabel1 = Label(window, text="Q #", padx=5).grid(row=0,column=0)
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0,column=4)
myTextbox1 = Entry(window,width=4 ,validate="key",
validatecommand=(window.register(validate_entry), "%S"))
myTextbox1.insert(INSERT,curQ)
myTextbox1.grid(row=0,column=2)
myTreeview = ttk.Treeview(window)
myTreeview.grid(row=1, column=0, columnspan=5, sticky='NSEW', padx=10, pady=5)
window.rowconfigure(1, weight=1)
window.columnconfigure(4, weight=1)
#sg.loadReveal()
window.mainloop()
RE: Sheek, the sheep game with a knockout twist. - Neowise - 08-07-2023
Added more functionality.
+more
update 11/07: Got groups working.
Currently, I repopulate everything going in and out of edit answers.
Code: from tkinter import *
from tkinter import filedialog, messagebox, ttk
import xml.etree.ElementTree as ET
from enum import Enum
import re
class EdPlayer:
def __init__(self,name):
self.Name = name
self.Answers = []
class ShGame:
class ShQuestion:
def __init__(self, ref_game, new_text):
self.Text = new_text
self.Groups= []
self._Game = ref_game
def __str__(self):
return f'Question: {self.Text} Groups: {self.Groups} ref_game: {self._Game}'
@property
def GameIndex(self):
return self._Game.Questions.index(self)
@property
def Game(self):
return self._Game
def StartNewGroup(self, new_text):
newGrp = ShGame.ShGroup(self, new_text)
self.Groups.append(newGrp)
return newGrp
def SyncGroups(self):
self.Groups = [shg for shg in self.Groups if shg.Answers]
def GetAllAnswers(self):
all_answers = []
for grp in self.Groups:
all_answers.extend(grp.Answers)
return all_answers
# returns list of scores for this question
# SCORING METHODS
# Sheep: each player gets total answers in his group as his score
# Peehs1: incorrects = 1.5 * highest correct score
# Peehs2: incorrects = highest correct score + 0.5 * number of distinct
# correct answers
# Heep: highest score gets 0, 2nd highest get doubled
# Kangaroo: must be incorrect; correct answers get 0
def Scores(include_bonus):
curScore = {}
for plr in _Game.Players:
curScore[plr] = 0
if len(_Game.Players) == 0 or len(_Game.Questions) == 0:
return curScore
highest_score = 0
second_highest_score = 0
num_distinct_correct = 0
for grp in self.Groups:
for ans in grp.Answers:
if ans.Player not in curScore:
continue
curScore[ans.Player] = len(grp.Answers)
return curScore
# for peehs/heep
if grp.Correct:
num_distinct_correct += 1
if len(grp.Answers) > highest_score:
second_highest_score = highest_score
highest_score = len(grp.Answers)
elif len(grp.Answers) > second_highest_score and len(grp.Answers) < highest_score:
second_highest_score = len(grp.Answers)
# apply special scores depending on scoring method
for grp in self.Groups:
for ans in grp.Answers:
if ans.Player not in curScore:
continue
if self._Game.Method == ShMethod.Sheep:
if not grp.Correct:
curScore[ans.Player] = 0
# incorrect means invalid for sheep
elif self._Game.Method == ShMethod.PeehsDM:
# incorrect -> 1.5*sheep
if not grp.Correct:
curScore[ans.Player] = 1.5 * highest_score
elif self._Game.Method == ShMethod.PeehsFB:
# incorrect -> sheep + 0.5*distinct
if not grp.Correct:
curScore[ans.Player] = highest_score + 0.5 * num_distinct_correct
elif self._Game.Method == ShMethod.PeehsHybrid:
# incorrect -> sheep + 0.5*distinct
if not grp.Correct:
curScore[ans.Player] = 1.25 * highest_score + 0.25 * num_distinct_correct
elif _Game.Method == ShMethod.Heep or _Game.Method == ShMethod.Heep15 or _Game.Method == ShMethod.Heep2:
if curScore[ans.Player] == highest_score or not grp.Correct:
curScore[ans.Player] = 0
elif curScore[ans.Player] == second_highest_score:
if _Game.Method == ShMethod.Heep15:
curScore[ans.Player] *= 1.5
elif _Game.Method == ShMethod.Heep2:
curScore[ans.Player] *= 2
elif _Game.Method == ShMethod.Kangaroo:
if grp.Correct:
curScore[ans.Player] = 0
elif _Game.Method == ShMethod.Manual:
curScore[ans.Player] = 0
# apply rounding
if _Game.Rounding == ShRoundingType.Up:
curScore[ans.Player] = math.ceil(curScore[ans.Player])
elif _Game.Rounding == ShRoundingType.Down:
curScore[ans.Player] = math.floor(curScore[ans.Player])
elif _Game.Rounding == ShRoundingType.Nearest:
curScore[ans.Player] = round(curScore[ans.Player])
# apply player & group bonuses
if include_bonus:
temp_score = cur_score[ans.Player]
if grp.BonusType == ShBonusType.Override:
temp_score = grp.GroupBonus
elif grp.BonusType == ShBonusType.Add:
temp_score += grp.GroupBonus
if ans.BonusType == ShBonusType.Override:
temp_score = ans.AnswerBonus
elif ans.BonusType == ShBonusType.Add:
temp_score += ans.AnswerBonus
cur_score[ans.Player] = temp_score
def score_up_to(include_bonus):
cur_score = {}
next_score = {}
for plr in _Game.Players:
cur_score[plr] = 0
for que in _Game.Questions:
if que.GameIndex <= self.GameIndex:
next_score = que.scores(include_bonus)
for k, v in next_score.items():
if k in cur_score:
cur_score[k] += v
return cur_score
class ShPlayer:
counter = 0
def __init__(self, ref_game, player_name, start_score=0):
self._Game = ref_game
self.Name = player_name
self.Answers = []
self.StartScore = start_score
ShGame.ShPlayer.counter += 1
def __str__(self):
return f'Player: {self.Name} Answers: {self.Answers} '
@property
def Count(self):
return self.counter
@property
def GameIndex(self):
return self._Game.Players.index(self)
@property
def Game(self):
return self._Game
def __del__(self):
for ans in self.Answers:
self.counter -= 1
print(f'self.Answers: {self.Answers}')
print(f'ans: {ans}')
ans.Group.Answers.remove(ans)
class ShGroup:
def __init__(self, ref_question, new_text):
self.Text = new_text
self.Correct = True
self.GroupBonus = 0
self.BonusType = NONE
self.Answers = []
self._Question = ref_question # reference to question
# constructor
# declares with an empty list for Answers
#self.Answers = [ShAnswer() for _ in range(len(ref_question.Game.Players))]
#self.Answers = [ShGame.ShAnswer(len(ref_question.Game.Players)) for _ in range(len(ref_question.Game.Players))]
def __str__(self):
return f'Group.Text: {self.Text} ref_question: {self._Question} Answers: {self.Answers}'
@property
def Question(self):
return self._Question
# moves all answers to ref_group and deletes itself
def MergeToGroup(self, ref_group):
if ref_group == self:
# throw new Exception("Trying to merge a group to itself")
return
while len(self.Answers) != 0:
self.Answers[0].ChangeGroup(ref_group)
self._Question.Groups.remove(self)
def GetScore(self, include_bonus):
if len(self.Answers) == 0:
return 0
else:
try:
baseScore = _Question.Scores(False)[self.Answers[0].Player]
if include_bonus:
if self.BonusType == ShBonusType.Override:
return self.GroupBonus
elif self.BonusType == ShBonusType.Add:
return self.GroupBonus + baseScore
else:
return baseScore
else:
return baseScore
except:
return 0
def __del__(self):
for ans in self.Answers:
ans.Player.Answers.remove(ans)
class ShAnswer:
def __init__(self, ref_group, ref_player, new_text):
self.Text = new_text
self.AnswerBonus = 0
self._Group = ref_group
self._Player = ref_player
def __str__(self):
return f'Answer.Text:{self.Text} ref_group: {self._Group} ref_player: {self._Player}'
@property
def Group(self):
return self._Group
@property
def Player(self):
return self._Player
def ChangeGroup(self, ref_group):
#print(str(ref_group) +" "+str(self._Group))
if ref_group == self._Group:
return
if self._Group.Question != ref_group.Question:
raise Exception("Moving an answer to a group in a different question.")
oldGroup = self._Group
self._Group = ref_group
#print(ref_group.Answers)
ref_group.Answers.append(self)
#print(oldGroup.Answers)
try:
oldGroup.Answers.remove(self)
except:
pass
if len(oldGroup.Answers) == 0:
oldGroup.Question.Groups.remove(oldGroup)
def StartNewGroup(self):
oldGroup = self._Group
print(oldGroup)
newGroup = ShGame.ShGroup(self._Group.Question, self.Text)
print(newGroup)
oldGroup.Question.Groups.append(newGroup)
self._Group = newGroup
newGroup.Answers.append(self)
oldGroup.Answers.remove(self)
if len(oldGroup.Answers) == 0:
oldGroup.Question.Groups.remove(oldGroup)
class ShMethod(Enum):
Sheep = 1
PeehsDM = 2
PeehsFB = 3
PeehsHybrid = 4
Heep = 5
Heep15 = 6
Heep2 = 7
Kangaroo = 8
Manual = 9
class ShBonusType(Enum):
NONE = 0
Add = 1
Override = 2
class ShRoundingType(Enum):
NONE = 0
Up = 1
Down = 2
Nearest = 3
def __init__(self,*args):
if len(args)==0:
self.Questions = []
self.Players = []
self.Method = self.ShMethod.Sheep
self.Rounding = self.ShRoundingType.NONE
elif len(args)==3:
new_questions=args[0]
new_players=args[1]
new_answers=args[2]
if len(new_answers) != len(new_questions) or len(new_answers[0]) != len(new_players):
raise Exception("Answer list must be size [num questions, num players]")
self.Questions = [ShQuestion(self, txt) for txt in new_questions]
self.Players = [ShPlayer(self, txt) for txt in new_players]
for iques in range(len(new_questions)):
for iplayer in range(len(new_players)):
new_group = ShGroup(self.Questions[iques], new_answers[iques][iplayer])
self.Questions[iques].Groups.append(new_group)
new_answer = ShAnswer(new_group, self.Players[iplayer], new_answers[iques][iplayer])
new_group.Answers.append(new_answer)
self.Players[iplayer].Answers.append(new_answer)
def __str__(self):
return 'This is a Game'
# attempts to guess groupings for ans
def guess_group(self,ans):
#red
anstxt = re.sub(r'\W', '', ans.Text.lower())
for grp in ans.Group.Question.Groups:
print(ans.Group.Question.Groups)
if grp == ans.Group:
continue
if re.sub(r'\W', '', grp.Text.lower()) == anstxt:
ans.ChangeGroup(grp)
return
# didn't find any but let's try individual answers
for grp in ans.Group.Question.Groups:
if grp == ans.Group:
continue
for ans2 in grp.Answers:
if re.sub(r'\W', '', ans2.Text.lower()) == anstxt:
ans.ChangeGroup(grp)
return
def loadReveal(self):
resetProgram()
#print (sg.__dict__)
global myLabel2, Roundtype
#filename = "C:/Users/keith/Desktop/sheep/80s2023.sheep17"
filename = filedialog.askopenfilename(title="Load Sheep Scoring File", filetypes=[("Sheep Score 2017 File", "*.sheep17")])
tree = ET.parse(filename)
root = tree.getroot()
#print(root.tag)
if root.tag == "SheepScore2012Game":
for child in root:
if child.tag == "ScoringMethod":
self.Method = self.ShMethod[child.text]
#Gametype.set(gt[child.text])
elif child.tag == "Rounding":
if child.text =="None":
child.text = "NONE"
self.Rounding = self.ShRoundingType[child.text]
#Roundtype.set(rt[child.text])
elif child.tag == "Question":
#print(child.attrib['GameIndex'], child.text)
qindex = int(child.attrib['GameIndex'])
while len(self.Questions) < qindex + 1:
self.Questions.append(self.ShQuestion(self, "(blank)"))
self.Questions[qindex].Text = child.text
elif child.tag == "Player":
pindex = int(child.attrib['GameIndex'])
start_score = child.attrib['StartScore']
while len(self.Players) < pindex + 1:
self.Players.append(self.ShPlayer(self, "(blank)", start_score))
self.Players[pindex].Name = child.text
elif child.tag == "Group":
group_q_index = int(child.attrib['QuestionIndex'])
tempcorrect = child.attrib['Correct']
tempgroupbonus = child.attrib['GroupBonus']
tempgroupbonustype = child.attrib['BonusType']
newGroup = self.ShGroup(self.Questions[group_q_index], "")
newGroup.Correct = tempcorrect
newGroup.GroupBonus = tempgroupbonus
newGroup.BonusType = tempgroupbonustype
self.Questions[group_q_index].Groups.append(newGroup)
#print(child.tag, child.text)
for item in child:
if item.tag == "Text":
newGroup.Text = item.text
elif item.tag == "Answer":
ans_p_index = int(item.attrib['PlayerIndex'])
tempansbonus = int(item.attrib["AnswerBonus"])
tempansbonustype = item.attrib['BonusType']
anstext = item.text
newAns = ShGame.ShAnswer(newGroup, self.Players[ans_p_index], anstext)
newAns.AnswerBonus = tempansbonus
newAns.BonusType = tempansbonustype
newGroup.Answers.append(newAns)
self.Players[ans_p_index].Answers.append(newAns)
if len(self.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=self.Questions[curQ - 1].Text)
myLabel2.grid(row=0, column=4)
else:
qdown()
updateTreeview()
else:
messagebox.showinfo(title="Greetings", message="This is not a recognized sheep file!")
def qdown():
global curQ
global myLabel2
if curQ>len(sg.Questions): curQ = len(sg.Questions)
if curQ>1:
curQ=curQ-1
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ-1].Text)
myLabel2.grid(row=0, column=4)
updateTreeview()
def qup():
global curQ
global myLabel2
if curQ > len(sg.Questions): curQ = len(sg.Questions)
if curQ < len(sg.Questions):
curQ = curQ + 1
else:
curQ == 1
myTextbox1.delete(0,END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if curQ == 0: return
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ-1].Text)
myLabel2.grid(row=0, column=4)
updateTreeview()
def resetProgram():
global myTextbox1, myLabel2, players, curQ, current_var, curP
sg.Questions = []
sg.Players = []
sg.Groups= []
players=[]
curQ = 1
curP = 0
current_var.set("")
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
myLabel2.grid_forget()
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0, column=4)
updateTreeview()
return
def edAL(edAText,combo):
global players, curP
players=[]
existing_players = []
answers = []
for x in players: existing_players.append(x.Name)
#file1 = open("C:/Users/keith/Desktop/sheep/answers.txt", 'r', encoding="utf8")
file1 = open(filedialog.askopenfilename(title="Load Players and Answers from File", filetypes=[("txt files", "*.txt")] ), 'r', encoding="utf8")
found = 0
next_player = 0
name = ""
for line in file1:
line=line.strip()
if found==0 and line[0:6]=="From: ":
found=1
name=line[6:]
if found==2 and line=="------------------------------------------------------------------------":
found = 0
next_player=1
if found==2:
answers.append(line)
if found==1 and line=="------------------------------------------------------------------------":
found = 2
if next_player==1:
if name not in existing_players:
player=EdPlayer(name)
existing_players.append(name)
index = 0 # question 0
#print(name + " with answers= " + str(answers))
for ans in answers:
player.Answers.append(ans)
answers = []
players.append(player)
#print("appended")
next_player = 0
else:
print(name + "exists in "+str(existing_players))
#print(for a in sg.Players: print(a.Name))
#player=sg.Players.pop(existing_players.index(name))
print("Duplicate Player " + name)
answers = []
print("dumped duplicate")
next_player=0
players = sorted(players, key=lambda w: w.Name.lower())
#curP = len(players)-1
combo['values'] = [item.Name for item in players]
combo.current(curP)
PAnswers = []
answers = ""
for x in players[curP].Answers: PAnswers.append(x)
for item in PAnswers: answers = answers + item + "\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
return(edAText)
def edQL(edQText):
#file1 = open("C:/Users/keith/Desktop/sheep/questions.txt", 'r')
file1 = open(filedialog.askopenfilename(title="Load Questions from File", filetypes=[("txt files", "*.txt")] ), 'r')
strvar=file1.read()
edQText.delete(1.0,END)
edQText.insert(INSERT, strvar)
return(edQText)
def edSave(edQW,edQText):
global myLabel2, curQ
sg.Questions = []
questions = edQText.get("1.0",END).splitlines()
qindex=0
for item in questions:
sg.Questions.append(ShGame.ShQuestion(sg,item))
qindex+=1
window.deiconify()
if curQ==0:curQ=1
if curQ>len(sg.Questions): curQ=len(sg.Questions)
myTextbox1.delete(0, END)
myTextbox1.insert(INSERT, curQ)
myTextbox1.grid_forget()
myTextbox1.grid(row=0, column=2)
if len(sg.Questions) >= curQ:
myLabel2.grid_forget()
myLabel2 = Label(window, text=sg.Questions[curQ - 1].Text)
myLabel2.grid(row=0, column=4)
edQW.destroy()
def edPSave(edAW,edAText,combo):
global players, score, myPlayers, curP
if len(players)==0:
sg.Players = []
for x in range(len(sg.Questions)):
sg.Questions[x].Groups = []
if len(players)>0:
combo.event_generate('<<ComboboxSelected>>') #store values of currently selected player
who=players[curP].Name
players = sorted(players, key=lambda w: w.Name.lower())
index=0
for x in players:
if x.Name == who:
break
index += 1
curP = index
sg.Players = [] #Remake the Game players from the entries.
for qs in sg.Questions: #Trash all groups
qs.Groups=[]
for pnum, player in enumerate(players):
#do the stuff to make a player and answers.
sg.Players.append(ShGame.ShPlayer(sg, player.Name,0))
for qnum, anstxt in enumerate(player.Answers):
while qnum == len(sg.Questions):
sg.Questions.append(ShGame.ShQuestion(sg,""))
newgroup = ShGame.ShGroup(sg.Questions[qnum], anstxt)
#sg.Questions[qnum].Groups.append(newgroup)
sg.Players[pnum].Answers.append(ShGame.ShAnswer(newgroup, sg.Players[pnum], anstxt))
#print(sg.Players)
players=[]
#print(f'# players: {len(sg.Players)}')
todelete=[]
for x, player in enumerate(sg.Players):
for i, ans in enumerate(player.Answers):
present_groups=[]
for m in ans.Group.Question.Groups:
present_groups.append(m.Text)
if ans.Text not in present_groups:
ans.Group.Question.Groups.append(ShGame.ShGroup(ans.Group.Question,ans.Text))
present_groups.append(ans.Text)
#print(present_groups)
#print(present_groups.index(ans.Text))
ans.Group.Question.Groups[present_groups.index(ans.Text)].Answers.append(ans)
for x, player in enumerate(sg.Players):
for i, ans in enumerate(player.Answers):
sg.Players[x].Answers.pop(i)
#print(todelete)
#ans.Group.Question.Groups.append(ans) #to fix, should not be appending answers into groups.
#sg.Players[x].Answers.pop(i)
#print(ans, ans.Group.Question.Groups)
#ans.StartNewGroup()
#sg.guess_group(ans)
# for y in range(len(sg.Questions)):
# ans = sg.Players[x].Answers[y]
# tempAnsTxt = "(blank)"
# if ans.Text.strip() != "":
# tempAnsTxt = ans.Text.strip()
# ans.Text = tempAnsTxt
updateTreeview()
window.deiconify()
edAW.destroy()
def edPCancel(parent,child):
parent.deiconify()
child.destroy()
def edCancel(child):
window.deiconify()
child.destroy()
def edPOK(edAText,combo, edAW, newPW, newplayer, x=''):
global players, score, curP
players.append(ShGame.ShPlayer(sg,newplayer,0))
players = sorted(players,key=lambda w: w.Name.lower())
index=0
for x in players:
if x.Name==newplayer:
break
index+=1
curP=index-1
combo['values'] = [item.Name for item in players]
curP+=1
combo.current(curP)
PAnswers = []
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers = answers + item + "\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
edAW.deiconify()
newPW.destroy()
def edROK(edAText,combo, edAW, newPW, newplayer, x=''):
global players, score, curP
names=[]
for x in players: names.append(x.Name)
if newplayer not in names and newplayer !='':
players[curP].Name=newplayer
combo['values'] = [item.Name for item in players]
combo.current(curP)
edAW.deiconify()
newPW.destroy()
def newPlayer(edAText,combo, edAW):
TextBoxUpdate(edAText,combo)
edAW.withdraw()
newPW = Toplevel(edAW)
newPW.bind('<Return>', lambda x: edPOK(edAText,combo, edAW, newPW, newPEntry.get()))
newPW.title("New Player")
newPLabel = Label(newPW, text="Enter new player name:", padx=10, font=20).grid(row=0, column=0)
newPEntry = Entry(newPW, font=20)
newPEntry.grid(row=1, column=0)
newPOK = Button(newPW, text='OK', command=lambda: edPOK(edAText,combo, edAW, newPW, newPEntry.get())).grid(row=2,column=3)
newPCancel = Button(newPW, text='Cancel', command=lambda: edPCancel(edAW, newPW)).grid(row=2,column=4)
newPEntry.focus_force()
def renamePlayer(edAText, combo, edAW):
global players
if len(players) > 0:
TextBoxUpdate(edAText, combo)
edAW.withdraw()
newPW = Toplevel(edAW)
newPW.bind('<Return>', lambda x: edROK(edAText, combo, edAW, newPW, newPEntry.get()))
newPW.title("Rename Player")
newPLabel = Label(newPW, text="Rename the player:", padx=10, font=20).grid(row=0, column=0)
entry_text=StringVar()
newPEntry = Entry(newPW, font=20, textvariable=entry_text)
entry_text.set(combo.get())
newPEntry.grid(row=1, column=0)
newPOK = Button(newPW, text='OK', command=lambda: edROK(edAText, combo, edAW, newPW, newPEntry.get())).grid(row=2, column=3)
newPCancel = Button(newPW, text='Cancel', command=lambda: edPCancel(edAW, newPW)).grid(row=2, column=4)
newPEntry.focus_force()
def delPlayer(edAText,combo):
global players, curP
if len(players)>0:
names=[]
for x in players: names.append(x.Name)
index=names.index(combo.get())
players.pop(index)
if curP==len(players):
curP-=1
combo['values'] = [item.Name for item in players]
if len(players)==0:
combo.set('')
PAnswers = []
answers = ""
edAText.delete(1.0, END)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
else:
combo.current(curP)
PAnswers = []
answers = ""
for x in players[curP].Answers: PAnswers.append(x.Text)
for item in PAnswers: answers = answers + item + "\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
def TextBoxUpdate(edAText,combo):
global curP, current_var, players
#Get current answers
if len(players)>0:
answers=edAText.get(1.0, END).splitlines()
if answers[-1].lstrip()=='':
del answers[-1]
index=0
if len (answers) >= len (players[curP].Answers):
while index < len(players[curP].Answers):
if answers[index]!=players[curP].Answers[index]:
players[curP].Answers[index]=answers[index]
index+=1
while index < len(answers):
players[curP].Answers.append(ShGame.ShAnswer(ShGame.ShGroup(index,""),players[curP],answers[index]))
index+=1
if len(answers) < len(players[curP].Answers):
while index < len(answers):
if answers[index]!=players[curP].Answers[index].Text:
players[curP].Answers[index].Text=answers[index]
index+=1
while index < len(players[curP].Answers):
del players[curP].Answers[index]
current_value = current_var.get()
index=0
for item in players:
if item.Name==current_value:
curP=index
else: index+=1
if len(players) != 0:
combo.current(curP)
PAnswers=[]
answers = ""
for x in players[curP].Answers: PAnswers.append(x)
for item in PAnswers: answers=answers+str(item)+"\n"
edAText.delete(1.0, END)
edAText.insert(INSERT, answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
def edAnswers(window):
global players, curP, current_var
def select_next(event):
selection = combo.current() # get the current selection
last = len(combo['values']) - 1 # index of last item
key = event.keysym # get the key that was pressed
if key == 'Up':
try:
combo.current(selection - 1) # set the combobox to the previous item
combo.event_generate('<<ComboboxSelected>>')
except TclError: # end of list reached
pass #combo.current(last) # wrap around to last item
elif key == 'Down':
try:
combo.current(selection + 1) # set the combobox to the next item
combo.event_generate('<<ComboboxSelected>>')
except TclError: # end of list reached
pass #combo.current(0) # wrap around to first item
return 'break' # tell tk to dispose of this event and don't show the menu!
window.withdraw()
edAW = Toplevel(window)
edAW.bind("<<ComboboxSelected>>", lambda x: TextBoxUpdate(edAText,combo))
players=[]
if len(sg.Players) != 0:
playerlist=[]
# for index, item in enumerate(sg.Players):
# for ans in item.Answers:
# if ans.Player.Name not in playerlist:
# players.append(EdPlayer(ans.Player.Name))
# playerlist.append(ans.Player.Name)
# players[playerlist.index(ans.Player.Name)].Answers.append(ans.Text)
# #print(ans.Text, " ", ans.Player.Name)
# #print(ans)
for qnum, question in enumerate(sg.Questions):
for gnum, grp in enumerate(sg.Questions[qnum].Groups):
for ans in grp.Answers:
if ans.Player.Name not in playerlist:
players.append(ShGame.ShPlayer(sg, ans.Player.Name, 0))
playerlist.append(ans.Player.Name)
players[playerlist.index(ans.Player.Name)].Answers.append(ans.Text)
print(ans.Text," ",ans.Player.Name)
print(len(players))
if curP >= len(players):
curP = len(players)-1
#print(f'curP {curP}')
answers=""
#print("here")
#if curP==0:curP+=1
if len(players)==0:
answers='Click Load... to load players and answers\nfrom a PM text file, or click New Player\nto add players manually.'
curP=0
else:
PAnswers=[]
for x in players[curP].Answers: PAnswers.append(x)
for item in PAnswers: answers=answers+item+"\n"
combo = ttk.Combobox(edAW, textvariable=current_var, state="readonly", values=[item.Name for item in players])
if len(players)!=0:combo.current(curP)
combo.bind('<Up>', select_next) # up arrow
combo.bind('<Down>',select_next) # down arrow
combo.grid(row=0, column=1)
edAW.title("Edit Entries")
edALabel = Label(edAW, text="Player:")
edALabel.grid(row=0, column=0)
spacer = Label(edAW).grid(row=0, column=2)
edALabel = Label(edAW, text="Starting Score:", padx=10)
edALabel.grid(row=1, column=0)
edAText = Text(edAW)
if len(players)==0:
edAText.insert(INSERT,'Click Load... to load players and answers\nfrom a PM text file, or click New Player\nto add players manually.')
else:
edAText.insert(INSERT,answers)
edAText.grid(column=0, columnspan=3, rowspan=10, padx=5, pady=5)
edALoad = Button(edAW, text="Load", padx=20, command=lambda: edAL(edAText,combo)).grid(row=0,column=3,padx=10,pady=5)
edANP = Button(edAW, text="New Player", padx=4, command=lambda: newPlayer(edAText,combo, edAW)).grid(row=1,column=3,padx=10,pady=5)
edACN = Button(edAW, text="Change Name", padx=0,command=lambda: renamePlayer(edAText,combo, edAW)).grid(row=2, column=3, padx=10, pady=5)
edADP = Button(edAW, text="Delete Player", padx=0, command=lambda: delPlayer(edAText,combo)).grid(row=3, column=3, padx=10, pady=5)
edASave = Button(edAW, text="Save Changes", command=lambda: edPSave(edAW, edAText,combo)).grid(row=9, column=3,padx=10, pady=5)
edACancel = Button(edAW, text="Cancel", padx=20, command=lambda: edCancel(edAW)).grid(row=10, column=3,padx=10, pady=5)
edAW.rowconfigure(4, weight=1)
edAW.columnconfigure(2, weight=1)
return
def edQuestions(window):
window.withdraw()
myfile = "\n".join(item.Text.lstrip() for item in sg.Questions)
edQW = Toplevel(window)
edQW.title("Edit Questions")
edQLabel = Label(edQW,text="Click Load... to load the questions from a text file, or just type them in here one per line")
edQLabel.grid(row=0, columnspan=2)
edQText = Text(edQW)
edQText.insert(INSERT, myfile)
edQText.grid(column=0, rowspan=10, padx=5, pady=5)
edQLoad = Button(edQW, text="Load", padx=20, command=lambda: edQL(edQText)).grid(row=1, column=1)
edQSave = Button(edQW, text="Save Changes", command=lambda: edSave(edQW, edQText)).grid(row=9, column=1)
edQCancel = Button(edQW, text="Cancel", padx=20, command=lambda: edCancel(edQW)).grid(row=10, column=1)
return
def validate_entry(text):
return text.isdecimal()
def outPlayerscore():
print("[", end="")
for i in myPlayers:
if i != myPlayers[-1]:
print(i.score, end=",")
else:
print(i.score, end="")
print("]")
def dothis():
print("sg "+str(sg))
print("sg.dict"+str(sg.__dict__))
print("Questions[0]"+str(sg.Questions[0].__dict__))
print("Questions[0].Groups[0]" + str(sg.Questions[0].Groups[0].__dict__))
print("Players[0]" + str(sg.Players[0].__dict__))
def updateTreeview():
global myTreeview,curQ,vsb
if len(sg.Questions) != 0:
myTreeview.grid_forget()
vsb.grid_forget()
myTreeview = ttk.Treeview(window, show="tree")
vsb = ttk.Scrollbar(window,orient="vertical" ,command=myTreeview.yview)
myTreeview.configure(yscrollcommand=vsb.set)
vsb.grid(column=5, sticky='ns')
if (curQ > len(sg.Questions)):
curQ == len(sg.Questions)
if (curQ < 1):
curQ = 1
curQuestion = sg.Questions[curQ - 1]
# give instructions if no players loaded
if (len(sg.Players) == 0):
myTreeview.insert('', 'end', text="Click sheep > Edit Entries... to add entries.", iid=0)
myTreeview.grid(row=1, column=0, columnspan=5, sticky='NSEW', padx=10, pady=5)
curgroup = 0
curItem = 0
#print(sg.Questions[0].Groups[0].__dict__)#.Answers[0].__dict__)
# loop through each group
for group in curQuestion.Groups:
#print(f'Group: {group}')
group_node = myTreeview.insert("", "end", text=group.Text + f" -[{len(group.Answers)}]")
for answer in group.Answers:
#print(f'answer: {answer}')
myTreeview.insert(group_node, "end", text=answer.Text + " - " + answer.Player.Name)
myTreeview.grid(row=1, column=0, columnspan=5, sticky='NSEW', padx=10, pady=5)
else:
myTreeview.grid_forget()
vsb.grid_forget()
myTreeview.delete(*myTreeview.get_children())
myTreeview.grid(row=1, column=0, columnspan=5, sticky='NSEW', padx=10, pady=5)
# text will be added later so don't bother with it in this function
# for grp in curQuestion:
# curGroup=myTreeview.insert('','end',text=".",iid=0)
# myTreeview.insert('','end',text="this is text",iid=0)
gt= {'Sheep':1,'PeehsDM':2, 'PeehsFB':3, 'PeehsHybrid':4, 'Heep':5, 'Heep15':6, 'Heep2':7, 'Kangaroo':8, 'Manual':9}
gtl=['filler','Sheep','PeehsDM','PeehsFB','PeehsHybrid','Heep','Heep15','Heep2','Kangaroo','Manual']
rt= {'None':0,'Up':1,'Down':2,'Nearest':3}
rtl=['None','Up','Down','Nearest']
bt= {'None':1, 'Add':2, 'Override':3}
btl=['filler','None', 'Add', 'Override']
sg = ShGame()
players=[]
score=[]
curQ=1
curP=1
window = Tk()
window.geometry("680x450")
window.title("Sheep Score Foggies Edition")
Outputtype = IntVar()
Outputtype.set(1)
Gametype = IntVar()
Gametype.set(1)
Roundtype = IntVar()
Roundtype.set(0)
current_var = StringVar()
menubar = Menu(window)
window.config(menu=menubar)
fileMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="File",menu=fileMenu)
fileMenu.add_command(label="New Reveal", command=resetProgram)
fileMenu.add_command(label="Load Reveal...", command=sg.loadReveal)
fileMenu.add_command(label="Save Reveal...")
fileMenu.add_command(label="Debug", command=dothis)
fileMenu.add_separator()
fileMenu.add_command(label="Exit",command=quit)
sheepMenu = Menu(menubar,tearoff=0)
menubar.add_cascade(label="Sheep",menu=sheepMenu)
sheepMenu.add_command(label="Edit Questions...", command=lambda:edQuestions(window))
sheepMenu.add_command(label="Edit Entries...", command=lambda:edAnswers(window))
scoringMenu=Menu(menubar,tearoff=0)
sheepMenu.add_cascade(label="Scoring",menu=scoringMenu)
scoringMenu.add_radiobutton(label="Sheep",value=1, variable=Gametype)
peehsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Peehs",menu=peehsMenu)
peehsMenu.add_radiobutton(label="DM Scoring",value=2, variable=Gametype)
peehsMenu.add_radiobutton(label="FB Scoring",value=3, variable=Gametype)
peehsMenu.add_radiobutton(label="Hybrid",value=4, variable=Gametype)
heepsMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Heeps",menu=heepsMenu)
heepsMenu.add_radiobutton(label="2x Heep Bonus",value=7, variable=Gametype)
heepsMenu.add_radiobutton(label="1.5x Heep Bonus",value=6, variable=Gametype)
heepsMenu.add_radiobutton(label="No Heep Bonus",value=5, variable=Gametype)
scoringMenu.add_radiobutton(label="Kangaroo",value=8, variable=Gametype)
scoringMenu.add_radiobutton(label="Manual",value=9, variable=Gametype)
scoringMenu.add_separator()
roundingMenu=Menu(menubar,tearoff=0)
scoringMenu.add_cascade(label="Rounding",menu=roundingMenu)
roundingMenu.add_radiobutton(label="No Rounding",value=0, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Up",value=1, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Down",value=2, variable=Roundtype)
roundingMenu.add_radiobutton(label="Round Nearest",value=3, variable=Roundtype)
outputMenu=Menu(menubar,tearoff=0)
menubar.add_cascade(label="Output",menu=outputMenu)
outputMenu.add_command(label="Copy answers for this question")
outputMenu.add_command(label="Copy total scores up to this question")
outputMenu.add_command(label="Copy score table up to this question")
outputMenu.add_command(label="Copy Player list")
outputMenu.add_separator()
styleMenu=Menu(menubar,tearoff=0)
outputMenu.add_cascade(label="Output Style",menu=styleMenu)
styleMenu.add_radiobutton(label="Forum Table",value=1, variable=Outputtype)
styleMenu.add_radiobutton(label="Forum Formatted Text",value=2, variable=Outputtype)
styleMenu.add_radiobutton(label="Unformatted Text",value=3, variable=Outputtype)
qButton1 = Button(window, text="<",command=qdown).grid(row=0,column=1)
qButton2 = Button(window, text=">",command=qup).grid(row=0,column=3)
myLabel1 = Label(window, text="Q #", padx=5).grid(row=0,column=0)
myLabel2 = Label(window, text="Click Sheep > Edit Questions... to begin.")
myLabel2.grid(row=0,column=4)
myTextbox1 = Entry(window,width=4 ,validate="key",
validatecommand=(window.register(validate_entry), "%S"))
myTextbox1.insert(INSERT,curQ)
myTextbox1.grid(row=0,column=2)
myTreeview = ttk.Treeview(window)
myTreeview.grid(row=1, column=0, columnspan=5, sticky='NSEW', padx=10, pady=5)
vsb = ttk.Scrollbar(window,orient="vertical" ,command=myTreeview.yview)
window.rowconfigure(1, weight=1)
window.columnconfigure(4, weight=1)
#sg.loadReveal()
window.mainloop()
|