Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c030054
init: boilerplate code
jsl1114 Nov 5, 2025
e4f701e
version req change
jsl1114 Nov 5, 2025
a5dc0e9
feat: emojibank and random emoji generator
jsl1114 Nov 5, 2025
ec6a033
feat: add scoring algorithm
jsl1114 Nov 5, 2025
dbaf03d
feat: quiz helper functions
jsl1114 Nov 5, 2025
872a3b4
feat: cli and emoji quiz flow
jsl1114 Nov 5, 2025
f6c4610
feat: pipfile and build req setup
jsl1114 Nov 5, 2025
f798685
Init and add local build run instruction
jsl1114 Nov 5, 2025
859bf0c
Merge pull request #1 from swe-students-fall2025/feat/add-boilerplate…
jsl1114 Nov 5, 2025
f02fea5
Update team member information in README
SnazzyBeatle115 Nov 5, 2025
8fafd23
chore(data): add CSVs and wire up loaders
myapyke123 Nov 5, 2025
6d711c2
Merge pull request #2 from swe-students-fall2025/feature/data-files
myapyke123 Nov 5, 2025
0c97741
build workflow
SnazzyBeatle115 Nov 5, 2025
9b0cf9e
Merge branch 'main' of https://github.com/swe-students-fall2025/3-pyt…
SnazzyBeatle115 Nov 5, 2025
7754333
badge readme
SnazzyBeatle115 Nov 5, 2025
e272f24
first data.random_emojis test
SnazzyBeatle115 Nov 5, 2025
f0eb7b5
Delete quizproject/data directory to work on emoji quiz
KhushbooAgrawal190803 Nov 5, 2025
5edf11e
tests for random emojis
SnazzyBeatle115 Nov 5, 2025
d3b5e86
Merge pull request #3 from swe-students-fall2025/KhushbooAgrawal19080…
ll5373128 Nov 5, 2025
c16095c
Merge pull request #4 from swe-students-fall2025/tests
KhushbooAgrawal190803 Nov 5, 2025
cd590f9
get_theme_item() tests
SnazzyBeatle115 Nov 5, 2025
4dcdaed
Merge pull request #5 from swe-students-fall2025/tests-for-data
KhushbooAgrawal190803 Nov 5, 2025
42db057
coverage
SnazzyBeatle115 Nov 5, 2025
346829e
Merge branch 'main' of https://github.com/swe-students-fall2025/3-pyt…
SnazzyBeatle115 Nov 5, 2025
0e5546e
bumpver
SnazzyBeatle115 Nov 5, 2025
0556c0c
updated CI / CD workflows
SnazzyBeatle115 Nov 5, 2025
2eae4b1
deliver workflow fix
SnazzyBeatle115 Nov 5, 2025
101a8cd
update readme
SnazzyBeatle115 Nov 5, 2025
8baa0ba
again.,
SnazzyBeatle115 Nov 5, 2025
9530d7e
maybe fix upload?
SnazzyBeatle115 Nov 5, 2025
d956481
it works on my machine..
SnazzyBeatle115 Nov 5, 2025
d6622fe
no more autobump
SnazzyBeatle115 Nov 5, 2025
6ad73b9
test(scoring): added a streak function to score file and made test file
myapyke123 Nov 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: CI
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
python-version: ["3.9", "3.11"]
steps:
- uses: actions/checkout@v4
- name: Install Python, pipenv and Pipfile packages
uses: kojoru/prepare-pipenv@v1
with:
python-version: ${{ matrix.python-version }}
- name: Turn on 'editable' mode
run: |
pipenv install -e .
- name: Test with pytest
run: |
pipenv install pytest
pipenv --venv
pipenv run python -m pytest
28 changes: 28 additions & 0 deletions .github/workflows/deliver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: CD
on:
push:
branches:
- main
jobs:
deliver:
# needs: [build]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: Install Python, pipenv and Pipfile packages
uses: kojoru/prepare-pipenv@v1
# you gotta do it manually bud, im not making it commit the new version number
# - name: Install bumpver and bump
# run: |
# pipenv install bumpver
# pipenv run bumpver update -p
- name: Build package
run: |
pipenv install build
pipenv run python -m build .
- name: Publish to PyPI test server
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository-url: https://test.pypi.org/legacy/
23 changes: 23 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[[source]]
url = "https://test.pypi.org/simple/"
verify_ssl = true
name = "testpypi"

[packages]
twine = "*"
build = "*"
pytest = "*"
coverage = "*"
pytest-cov = "*"
emojiguessr = {file = ".", editable = true}
bumpver = "*"

[dev-packages]

[requires]
python_version = "3"
536 changes: 536 additions & 0 deletions Pipfile.lock

Large diffs are not rendered by default.

37 changes: 35 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
# Python Package Exercise
# EmojiGuessr

An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details.
<!-- The badge should be replaced by the actual CI badge -->
[![](https://github.com/swe-students-fall2025/3-python-package-team_saffron/actions/workflows/build.yaml/badge.svg)](https://github.com/swe-students-fall2025/3-python-package-team_saffron/actions/workflows/build.yaml)

[![](https://github.com/swe-students-fall2025/3-python-package-team_saffron/actions/workflows/deliver.yaml/badge.svg)](https://github.com/swe-students-fall2025/3-python-package-team_saffron/actions/workflows/deliver.yaml)

Link to PyPI: []()

EmojiGuessr is a Python package that turns emoji strings into quick guessing games. Pick a theme, get an emoji clue and guess the name!

## Team Members
[Jason Liu](https://github.com/jsl1114)

[David Shen](https://github.com/snazzybeatle115)

member3

member4

member5

## Installation

pipenv install -i https://test.pypi.org/simple/ emojiguessr==0.0.1

## Usage (code examples)

## Develop and Contribute

### Local build & run (using `pipenv`)
1. Get [`pipenv`](https://pipenv.pypa.io/en/latest/installation.html) installed
2. `cd` into the project directory
3. `pipenv install`
4. install the package in editable mode using `pipenv install -e .`
5. run the command line interface by using `pipenv run emojiguessr` followed by flags and configurations
Empty file added examples/demo.py
Empty file.
35 changes: 35 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[bumpver]
current_version = "0.3.2"
version_pattern = "MAJOR.MINOR.PATCH"


[bumpver.file_patterns]
"pyproject.toml" = [
'version = "{version}"',
]

[project]
name = "emojiguessr"
version = "0.3.2"
description = "A tiny emoji guessing game"
readme = "README.md"
requires-python = ">=3.9"
authors = [
{ name = "Team Saffron"}
]
license = { text = "GNU GENERAL PUBLIC LICENSE" }
dependencies = []

[project.urls]
Homepage = "https://github.com/swe-students-fall2025/3-python-package-team_saffron"
Issues = "https://github.com/swe-students-fall2025/3-python-package-team_saffron/issues"

[project.scripts]
emojiguessr = "emojiguessr.__main__:main"

[tool.setuptools.packages.find]
where = ["src"]
10 changes: 10 additions & 0 deletions src/emojiguessr/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from .data import random_emojis
from .quiz import make_quiz_item, check_answer
from .score import score

__all__ = [
"random_emojis",
"make_quiz_item",
"check_answer",
"score",
]
130 changes: 130 additions & 0 deletions src/emojiguessr/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import argparse
from emojiguessr import make_quiz_item, check_answer, score
from emojiguessr.data import _EMOJI_BANK


def run_quiz(num_questions, theme, case_sensitive, allow_partial, max_attempts):
s = 0
for i in range(1, num_questions + 1):
item = make_quiz_item(theme=theme)
clue = item["clue"]
answer = item["answer"]

print(f"\nQuestion {i}/{num_questions}")
print(f"Theme: {item['theme']}")
print(f"Emoji: {clue}")

attempts_left = max_attempts
while attempts_left > 0:
guess = input("Your guess: ")

is_right = check_answer(
correct=answer,
guess=guess,
case_sensitive=case_sensitive,
allow_partial=allow_partial,
)

s = score(s, correct=is_right)

if is_right:
print("✅ Correct!")
break
else:
attempts_left -= 1
if attempts_left > 0:
print(f"❌ Wrong! {attempts_left} attempts left.")
else:
print(f"❌ Nope — it was: {answer}")

print(f"\nFinal score: {s}/{num_questions}")


def list_themes():
print("Available themes:")
for theme in sorted(_EMOJI_BANK.keys()):
print(f" - {theme}")


def list_commands():
print("Available commands:")
print(" --num-questions, -n : Number of questions to ask (default: 3)")
print(" --theme, -t : Emoji theme to use (default: food)")
print(" --case-sensitive : Make answers case-sensitive (default: off)")
print(" --no-partial : Disable partial matches")
print(
" --max-attempts, -a : Maximum number of attempts per question (default: 1)"
)
print(" --list-themes, -lt : List available themes and exit")
print(" --list-commands, -lc : List available commands and exit")


def main():
parser = argparse.ArgumentParser(
prog="emojiguessr",
description="Play a quick emoji guessing game in your terminal.",
)
parser.add_argument(
"--num-questions",
"-n",
type=int,
default=3,
help="Number of questions to ask (default: 3)",
)
parser.add_argument(
"--theme",
"-t",
default="food",
help="Emoji theme to use (default: food). Use --list-themes to see options.",
)
parser.add_argument(
"--case-sensitive",
action="store_true",
help="Make answers case-sensitive (default: off)",
)
parser.add_argument(
"--no-partial",
action="store_true",
help="Disable partial matches (so 'jurassic' won't match 'jurassic park')",
)
parser.add_argument(
"--max-attempts",
"-a",
type=int,
default=1,
help="Maximum number of attempts per question (default: 1)",
)
parser.add_argument(
"--list-themes",
"-lt",
action="store_true",
help="List available themes and exit.",
)
parser.add_argument(
"--list-commands",
"-lc",
action="store_true",
help="List available commands and exit.",
)

args = parser.parse_args()

if args.list_themes:
list_themes()
return

if args.list_commands:
list_commands()
return

run_quiz(
num_questions=args.num_questions,
theme=args.theme,
case_sensitive=args.case_sensitive,
allow_partial=not args.no_partial,
max_attempts=args.max_attempts,
)


if __name__ == "__main__":
main()
94 changes: 94 additions & 0 deletions src/emojiguessr/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import random

_EMOJI_BANK = {
"food": [
("🍕", "pizza"),
("🍣", "sushi"),
("🍔", "burger"),
("🍟", "fries"),
("🌮", "taco"),
("🍜", "ramen"),
("🥐", "croissant"),
("🍩", "donut"),
("🍎", "apple"),
("🍰", "cake"),
],
"animals": [
("🐶", "dog"),
("🐱", "cat"),
("🐼", "panda"),
("🦁", "lion"),
("🐸", "frog"),
("🐧", "penguin"),
("🦊", "fox"),
("🐘", "elephant"),
("🐢", "turtle"),
("🦄", "unicorn"),
],
"movies": [
("🧙‍♂️💍", "lord of the rings"),
("🚢🧊", "titanic"),
("🦖🏞️", "jurassic park"),
("👸🏼❄️", "frozen"),
("🧔⚡", "harry potter"),
("👨‍🚀🌕", "space movie"),
("🦸‍♂️", "superman"),
("🚗💨", "fast and furious"),
],
"games": [
("🎮", "video game"),
("♟️", "chess"),
("🃏", "card game"),
("🎯", "darts"),
("🕹️", "arcade"),
("🎲", "board game"),
],
"cities": [
("🇺🇸🗽", "new york"),
("🇫🇷🗼", "paris"),
("🇬🇧🎡", "london"),
("⛩️🌸", "kyoto"),
("🇯🇵🗼", "tokyo"),
("🇦🇺🌉", "sydney"),
("🇮🇹🏛️", "rome"),
("🇪🇬🕌", "cairo"),
("🇧🇷🎭", "rio de janeiro"),
("🇨🇳🐼", "chengdu"),
],
"feelings": [
("😀", "happy"),
("😢", "sad"),
("😡", "angry"),
("🤔", "thinking"),
("🥱", "tired"),
("🤒", "sick"),
("😎", "cool"),
("🥳", "celebrating"),
],
"dev": [
("💻☕", "coding"),
("🐍📦", "python package"),
("🐛🔍", "debugging"),
("📦⬆️", "deploy"),
("🧪✅", "tests passing"),
("⚠️🐛", "bug"),
],
}


def random_emojis(count=3, theme="food"):
items = _EMOJI_BANK.get(theme)
if not items:
all_emoji = [e for v in _EMOJI_BANK.values() for (e, _) in v]
random.shuffle(all_emoji)
return all_emoji[: min(count, len(all_emoji))]
emojis = [e for (e, _) in items]
random.shuffle(emojis)
return emojis[:count]


def get_theme_item(theme="food"):
items = _EMOJI_BANK.get(theme)
if not items:
items = _EMOJI_BANK["food"]
return random.choice(items)
Loading
Loading