Skip to content

Commit

Permalink
Gym module created (#185)
Browse files Browse the repository at this point in the history
* Gym module created

* Update gym.py

* Updated Gym Module and created Unit tests for them

* updated issued for the GYM Module

* updated variable name

* updated gym module

* udpated unit testing for Gym module

* Apply suggestions from code review

* Apply suggestions from code review

* Fix from_text return type to support 3.9 and 3.10

---------

Co-authored-by: Tianyi Zheng <[email protected]>
  • Loading branch information
csidarous and tianyizheng02 authored Aug 8, 2024
1 parent 61f69b6 commit 966b603
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 0 deletions.
86 changes: 86 additions & 0 deletions pittapi/gym.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""
The Pitt API, to access workable data of the University of Pittsburgh
Copyright (C) 2015 Ritwik Gupta
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""

from __future__ import annotations

from bs4 import BeautifulSoup
import requests
from typing import NamedTuple

GYM_URL = "https://connect2concepts.com/connect2/?type=bar&key=17c2cbcb-ec92-4178-a5f5-c4860330aea0"

GYM_NAMES = [
"Baierl Rec Center",
"Bellefield Hall: Fitness Center & Weight Room",
"Bellefield Hall: Court & Dance Studio",
"Trees Hall: Fitness Center",
"Trees Hall: Courts",
"Trees Hall: Racquetball Courts & Multipurpose Room",
"William Pitt Union",
"Pitt Sports Dome",
]


class Gym(NamedTuple):
name: str
date: str
count: int
percentage: int

@classmethod
def from_text(cls, text: str) -> Gym:
info = text.split("|")
name = info[0]
if len(info) < 4:
return cls(name=name, date=None, count=None, percentage=None)
count = int(info[2][12:])
date = info[3][9:]
try:
percentage = int(info[4].rstrip("%"))
except ValueError:
percentage = 0

return cls(name=name, date=date, count=count, percentage=percentage)


def get_all_gyms_info() -> list[Gym]:
"""Fetches list of Gym named tuples with all gym information"""
# Was getting a Mod Security Error
# Fix: https://stackoverflow.com/questions/61968521/python-web-scraping-request-errormod-security
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:55.0) Gecko/20100101 Firefox/55.0",
}

page = requests.get(GYM_URL, headers=headers)
soup = BeautifulSoup(page.text, "html.parser")
gym_info_list = soup.find_all("div", class_="barChart")

# Iterate through list and add to dictionary
gyms = [Gym.from_text(gym.get_text("|", strip=True)) for gym in gym_info_list]
return gyms


def get_gym_info(gym_name: str) -> Gym | None:
"""Fetches the information of a singular gym as a tuple"""
info = get_all_gyms_info()
if gym_name in GYM_NAMES:
for gym in info:
if gym.name == gym_name and gym.date and gym.count and gym.percentage:
return gym
return None
62 changes: 62 additions & 0 deletions tests/gym_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import unittest
import responses
from pittapi import gym
from tests.mocks.gym_mocks import mock_gym_html


class GymTest(unittest.TestCase):
def __init__(self, *args, **kwargs):
unittest.TestCase.__init__(self, *args, **kwargs)

@responses.activate
def test_fetch_gym_info(self):

responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200)

gym_info = gym.get_all_gyms_info()
expected_info = [
gym.Gym(name="Baierl Rec Center", date="07/09/2024 09:05 AM", count=100, percentage=50),
gym.Gym(name="Bellefield Hall: Fitness Center & Weight Room", date="07/09/2024 09:05 AM", count=50, percentage=0),
gym.Gym(name="Bellefield Hall: Court & Dance Studio", date=None, count=None, percentage=None),
gym.Gym(name="Trees Hall: Fitness Center", date="07/09/2024 09:05 AM", count=70, percentage=58),
gym.Gym(name="Trees Hall: Courts", date="07/09/2024 09:05 AM", count=20, percentage=33),
gym.Gym(
name="Trees Hall: Racquetball Courts & Multipurpose Room",
date="07/09/2024 09:05 AM",
count=10,
percentage=25,
),
gym.Gym(name="William Pitt Union", date="07/09/2024 09:05 AM", count=25, percentage=25),
gym.Gym(name="Pitt Sports Dome", date="07/09/2024 09:05 AM", count=15, percentage=20),
]

self.assertEqual(gym_info, expected_info)

@responses.activate
def test_get_gym_info(self):
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200)

gym_info = gym.get_gym_info("Baierl Rec Center")
expected_info = gym.Gym(name="Baierl Rec Center", date="07/09/2024 09:05 AM", count=100, percentage=50)
self.assertEqual(gym_info, expected_info)

@responses.activate
def test_invalid_gym_name(self):
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200)

gym_info = gym.get_gym_info("Invalid Gym Name")
self.assertIsNone(gym_info)

@responses.activate
def test_valid_gym_name_not_all_info(self):
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200)

gym_info = gym.get_gym_info("Bellefield Hall: Court & Dance Studio")
self.assertIsNone(gym_info)

@responses.activate
def test_percentage_value_error(self):
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200)

gym_info = gym.get_gym_info("Bellefield Hall: Fitness Center & Weight Roomo")
self.assertIsNone(gym_info)
121 changes: 121 additions & 0 deletions tests/mocks/gym_mocks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
mock_gym_html = """
<div class="barChart" style="width:90%;">
Baierl Rec Center
<br>
<span style="color:green">(Open)</span>
<br>
Last Count: 100
<br>
Updated: 07/09/2024 09:05 AM
<div class="barChart_row" data-value="50.0">
<span class="barChart__value">50%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
<div class="barChart" style="width:90%;">
Bellefield Hall: Fitness Center & Weight Room
<br>
<span style="color:green">(Open)</span>
<br>
Last Count: 50
<br>
Updated: 07/09/2024 09:05 AM
<div class="barChart_row" data-value="33.0">
<span class="barChart__value">non%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
<div class="barChart" style="width:90%;">
Bellefield Hall: Court & Dance Studio
<br>
<span style="color:green">(Open)</span>
<br>
<!-- Missing Last Count -->
<!-- Missing Updated Date -->
<div class="barChart_row" data-value="38.0">
<span class="barChart__value">38%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
<div class="barChart" style="width:90%;">
Trees Hall: Fitness Center
<br>
<span style="color:green">(Open)</span>
<br>
Last Count: 70
<br>
Updated: 07/09/2024 09:05 AM
<div class="barChart_row" data-value="58.0">
<span class="barChart__value">58%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
<div class="barChart" style="width:90%;">
Trees Hall: Courts
<br>
<span style="color:green">(Open)</span>
<br>
Last Count: 20
<br>
Updated: 07/09/2024 09:05 AM
<div class="barChart_row" data-value="33.0">
<span class="barChart__value">33%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
<div class="barChart" style="width:90%;">
Trees Hall: Racquetball Courts & Multipurpose Room
<br>
<span style="color:green">(Open)</span>
<br>
Last Count: 10
<br>
Updated: 07/09/2024 09:05 AM
<div class="barChart_row" data-value="25.0">
<span class="barChart__value">25%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
<div class="barChart" style="width:90%;">
William Pitt Union
<br>
<span style="color:green">(Open)</span>
<br>
Last Count: 25
<br>
Updated: 07/09/2024 09:05 AM
<div class="barChart_row" data-value="25.0">
<span class="barChart__value">25%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
<div class="barChart" style="width:90%;">
Pitt Sports Dome
<br>
<span style="color:green">(Open)</span>
<br>
Last Count: 15
<br>
Updated: 07/09/2024 09:05 AM
<div class="barChart_row" data-value="20.0">
<span class="barChart__value">20%</span>
<span class="barChart__bar" style=" background: rgb(239, 239, 239);">
<span class="barChart__barFill" style="background: #2A5B84;"></span>
</span>
</div>
</div>
"""

0 comments on commit 966b603

Please sign in to comment.