Skip to content

Commit

Permalink
Merge branch 'master' of github.com:stuartthomas25/JParty
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartthomas25 committed Aug 22, 2024
2 parents 1d10026 + 6ee5e88 commit 52da4ea
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 23 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The host sees the answer on the laptop screen and can adjudicate with the arrow
- WebSocket buzzer for use on mobile devices
- Up to 8 players
- Complete access to all games on J-Archive
- Load custom games via a <a href="https://docs.google.com/spreadsheets/d/1_vBBsWn-EVc7npamLnOKHs34Mc2iAmd9hOGSzxHQX0Y/edit?usp=sharing">simple Google Sheets template</a>
- Load custom games via a <a href="https://docs.google.com/spreadsheets/d/1JqfJ_OgTstaXTyH5nV3_eN6YXqvZ1RviPmN7OwLhG0U/edit?usp=sharing">simple Google Sheets template</a>
- Scrape games from https://jeopardylabs.com using this <a href="https://chrome.google.com/webstore/detail/jeopardy-labs-to-csv/biijijhfghhckhlkjbonjedmgnkmenlk?hl=en&authuser=0">Google Chrome extension</a>
- Final Jeopardy, Daily Doubles, Double Jeopardy

Expand All @@ -54,30 +54,30 @@ The host sees the answer on the laptop screen and can adjudicate with the arrow

To debug, run

`
pip install -r requirements.txt;
cd jparty;
```
conda env create -f environment.yml
cd jparty
python ../run.py
`
```

Too build from source, run
To build from source, run

`
```
pyinstaller -y JParty.spec
`
```

## FAQ

### How does it work? (technical details)
JParty minimally scrapes the J-Archive (https://j-archive.com) to download a previously-played game and then simulates that on the screen. The game then uses PyQt6 to produce a GUI that simulates the motions of a full _Jeopardy!_ game. A `tornado` web server uses WebSockets to connect to the contestants' smartphones. If that's all gibberish to you, don't worry! You can still play without any technical knowledge.

### Can I create my own custom game?
Yes! JParty supports playing your own custom game via <a target=_blank href="https://docs.google.com/spreadsheets/d/1_vBBsWn-EVc7npamLnOKHs34Mc2iAmd9hOGSzxHQX0Y/edit?usp=sharing">this simple Google Sheets template</a>. First, make a copy of the template and change the sharing permissions to "Anyone With the Link Can View". Then, copy the Google Sheet file ID and paste it into the "Game ID" box. There are more detailed instructions on the template page. Limitations: there is no way to add pictures (yet!) and you are limited to the traditional 6 categories x 5 dollar values board.
Yes! JParty supports playing your own custom game via <a target=_blank href="https://docs.google.com/spreadsheets/d/1JqfJ_OgTstaXTyH5nV3_eN6YXqvZ1RviPmN7OwLhG0U/edit?usp=sharing">this simple Google Sheets template</a>. First, make a copy of the template and change the sharing permissions to "Anyone With the Link Can View". Then, copy the Google Sheet file ID and paste it into the "Game ID" box. There are more detailed instructions on the template page. Limitations: there is no way to add pictures (yet!) and you are limited to the traditional 6 categories x 5 dollar values board.

If you don't want to write your own questions but want to play a topical _Jeopardy!_ game, use this handy <a target=_blank href="https://chrome.google.com/webstore/detail/jeopardy-labs-to-csv/biijijhfghhckhlkjbonjedmgnkmenlk?hl=en&authuser=0">Google Chrome extension to scrape Jeopardy Labs questions</a> (<a href=https://github.com/benf2004/JeopardyLabsToCSV>source code</a>). There are millions of games available on https://jeopardylabs.com that are free to play on a variety of topics. While Jeopardy Labs is a great repository for many topical games & worked great 20 years ago, it lacks in features such as daily doubles, final jeopardy, music/sound effects, and buzzers.

To use the extension:
1. Make a copy of the <a target=_blank href="https://docs.google.com/spreadsheets/d/1_vBBsWn-EVc7npamLnOKHs34Mc2iAmd9hOGSzxHQX0Y/edit?usp=sharing">Jparty Google Sheets custom game template</a>
1. Make a copy of the <a target=_blank href="https://docs.google.com/spreadsheets/d/1JqfJ_OgTstaXTyH5nV3_eN6YXqvZ1RviPmN7OwLhG0U/edit?usp=sharing">Jparty Google Sheets custom game template</a>
2. Find a game on https://jeopardylabs.com.
3. Click the extension icon.
4. The questions will download as a csv (spreadsheet) in the style of the template.
Expand Down
11 changes: 11 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: JParty
dependencies:
- requests==2.31.0
- tornado==6.3.3
- beautifulsoup4==4.11.1
- pip
- pip:
- pyinstaller==6.6.0
- pyqt6==6.4.0
- qrcode==7.3.1
- simpleaudio==1.0.4
26 changes: 15 additions & 11 deletions jparty/retrieve.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,24 @@ def get_Gsheet_game(file_id):

def get_game(game_id):
if len(str(game_id)) < 7:
return get_wayback_jarchive_game(game_id)
try:
return get_wayback_game(game_id)
except Exception as e:
logging.error(e)
return get_jarchive_game(game_id)
else:
return get_Gsheet_game(str(game_id))


def findanswer(clue):
return re.findall(r'correct_response">(.*?)</em', unescape(str(clue)))[0]

def get_JArchive_Game(game_id, wayback_url=None):
logging.info(f"getting game {game_id}")
if wayback_url is not None:
r = requests.get(wayback_url)
else:
r = requests.get(f"http://www.j-archive.com/showgame.php?game_id={game_id}")
def get_jarchive_game(game_id):
return get_generic_game(game_id, f"http://www.j-archive.com/showgame.php?game_id={game_id}")

def get_generic_game(game_id, url):
logging.info(f"getting game {game_id} from url {url}")
r = requests.get(url)
soup = BeautifulSoup(r.text, "html.parser")
datesearch = re.search(
r"- \w+, (.*?)$", soup.select("#game_title > h1")[0].contents[0]
Expand Down Expand Up @@ -121,7 +125,7 @@ def get_JArchive_Game(game_id, wayback_url=None):

return GameData(boards, date, comments)

def get_wayback_jarchive_game(game_id):
def get_wayback_game(game_id):
# kudos to Abhi Kumbar: https://medium.com/analytics-vidhya/the-wayback-machine-scraper-63238f6abb66
# this query's the wayback cdx api for possible instances of the saved jarchive page with the specified game id & returns the latest one
JArchive_url = f"j-archive.com/showgame.php?game_id={str(game_id)}" # use the url w/o the http:// or https:// to include both in query
Expand All @@ -130,9 +134,8 @@ def get_wayback_jarchive_game(game_id):
parse_url = json.loads(urls) # parses the JSON from urls.
if len(parse_url) == 0: # if no results, return None
logging.info("no games found in wayback")
# return None
# alternative: use fallback to get game from scraping j-archive directly
return get_JArchive_Game(game_id)
raise Exception("no games found in wayback")

## Extracts timestamp and original columns from urls and compiles a url list.
url_list = []
Expand All @@ -143,7 +146,8 @@ def get_wayback_jarchive_game(game_id):
final_url = f'http://web.archive.org/web/{waylink}'
url_list.append(final_url)
latest_url = url_list[-1]
return get_JArchive_Game(game_id, latest_url)
return get_generic_game(game_id, latest_url)


def get_game_sum(soup):
date = re.search(
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PyQt6==6.4.0
requests==2.31.0
requests==2.32.0
simpleaudio==1.0.4
tornado==6.3.3
BeautifulSoup4==4.11.1
pyinstaller==5.6.2
pyinstaller==5.13.1
qrcode==7.3.1

0 comments on commit 52da4ea

Please sign in to comment.