Skip to content

Commit fab9b11

Browse files
authored
Merge pull request #82 from ComputerScienceHouse/develop
Version 3.0.4
2 parents a63c060 + 2e400de commit fab9b11

File tree

12 files changed

+384
-145
lines changed

12 files changed

+384
-145
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "CSH Packet",
33
"name": "csh-packet",
4-
"version": "3.0.3",
4+
"version": "3.0.4",
55
"description": "A webpacket for CSH",
66
"bugs": {
77
"url": "https://github.com/ComputerScienceHouse/packet/issues",

packet/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.0.3"
1+
__version__ = "3.0.4"

packet/commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def fetch_results():
187187
required = packet.signatures_required()
188188

189189
upper_ratio = sum((received["eboard"], received["upperclassmen"], received["miscellaneous"])) / \
190-
sum((required["eboard"], required["upperclassmen"], required["misc"]))
190+
sum((required["eboard"], required["upperclassmen"], required["miscellaneous"]))
191191
print("\tUpperclassmen score: {}%".format(round(upper_ratio * 100, 2)))
192192

193193
total_ratio = sum(received.values()) / sum(required.values())
@@ -198,7 +198,7 @@ def fetch_results():
198198
print("\tEboard: {}/{}".format(received["eboard"], required["eboard"]))
199199
print("\tUpperclassmen: {}/{}".format(received["upperclassmen"], required["upperclassmen"]))
200200
print("\tFreshmen: {}/{}".format(received["freshmen"], required["freshmen"]))
201-
print("\tMisc: {}/{}".format(len(packet.misc_signatures), required["misc"]))
201+
print("\tMiscellaneous: {}/{}".format(len(packet.misc_signatures), required["miscellaneous"]))
202202

203203
print()
204204

packet/member.py

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
from collections import namedtuple
2+
from logging import getLogger
3+
4+
from sqlalchemy import exc, text
5+
6+
from .models import db, REQUIRED_MISC_SIGNATURES
7+
from .packet import get_number_required, get_misc_signatures
8+
9+
LOGGER = getLogger(__name__)
10+
11+
12+
def current_packets(member, intro=False, onfloor=False):
13+
"""
14+
Get a list of currently open packets with the signed state of each packet.
15+
:param member: the member currently viewing all packets
16+
:param intro: true if current member is an intro member
17+
:param other: true if current member is off floor or alumni
18+
:return: <tuple> a list of packets that are currently open, and their attributes
19+
"""
20+
21+
# Tuple for compatibility with UI code. Should be refactored or deleted altogether later
22+
SPacket = namedtuple('spacket', ['rit_username', 'name', 'did_sign', 'total_signatures', 'required_signatures'])
23+
24+
packets = []
25+
required = get_number_required()
26+
27+
if intro and onfloor:
28+
required -= 1
29+
30+
signed_packets = get_signed_packets(member, intro, onfloor)
31+
misc_signatures = get_misc_signatures()
32+
33+
try:
34+
for pkt in query_packets_with_signed():
35+
signed = signed_packets.get(pkt.username)
36+
misc = misc_signatures.get(pkt.username)
37+
if signed is None:
38+
signed = False
39+
if misc is None:
40+
misc = 0
41+
if misc > REQUIRED_MISC_SIGNATURES:
42+
misc = REQUIRED_MISC_SIGNATURES
43+
packets.append(SPacket(pkt.username, pkt.name, signed, pkt.received + misc, required))
44+
45+
except exc.SQLAlchemyError as e:
46+
LOGGER.error(e)
47+
raise e
48+
49+
return packets
50+
51+
52+
def get_signed_packets(member, intro=False, onfloor=False):
53+
"""
54+
Get a list of all packets that a member has signed
55+
:param member: member retrieving prior packet signatures
56+
:param intro: is the member an intro member?
57+
:param onfloor: is the member on floor?
58+
:return: <dict> usernames mapped to signed status
59+
"""
60+
signed_packets = {}
61+
62+
try:
63+
if intro and onfloor:
64+
for signature in query_signed_intromember(member):
65+
signed_packets[signature.username] = signature.signed
66+
67+
if not intro:
68+
if onfloor:
69+
for signature in query_signed_upperclassman(member):
70+
signed_packets[signature.username] = signature.signed
71+
72+
else:
73+
for signature in query_signed_alumni(member):
74+
signed_packets[signature.username] = bool(signature.signed)
75+
76+
except exc.SQLAlchemyError as e:
77+
LOGGER.error(e)
78+
raise e
79+
80+
return signed_packets
81+
82+
83+
def query_packets_with_signed():
84+
"""
85+
Query the database and return a list of currently open packets and the number of signatures they currently have
86+
:return: a list of results: intro members with open packets, their name, username, and number of signatures received
87+
"""
88+
try:
89+
return db.engine.execute("""
90+
SELECT packets.username AS username, packets.name AS name, coalesce(packets.sigs_recvd, 0) AS received
91+
FROM ( ( SELECT freshman.rit_username
92+
AS username, freshman.name AS name, packet.id AS id, packet.start AS start, packet.end AS end
93+
FROM freshman INNER JOIN packet ON freshman.rit_username = packet.freshman_username) AS a
94+
LEFT JOIN ( SELECT totals.id AS id, coalesce(sum(totals.signed), 0) AS sigs_recvd
95+
FROM ( SELECT packet.id AS id, coalesce(count(signature_fresh.signed), 0) AS signed
96+
FROM packet FULL OUTER JOIN signature_fresh ON signature_fresh.packet_id = packet.id
97+
WHERE signature_fresh.signed = TRUE AND packet.start < now() AND now() < packet.end
98+
GROUP BY packet.id
99+
UNION SELECT packet.id AS id, coalesce(count(signature_upper.signed), 0) AS signed FROM packet
100+
FULL OUTER JOIN signature_upper ON signature_upper.packet_id = packet.id
101+
WHERE signature_upper.signed = TRUE AND packet.start < now() AND now() < packet.end
102+
GROUP BY packet.id ) totals GROUP BY totals.id ) AS b ON a.id = b.id ) AS packets
103+
WHERE packets.start < now() AND now() < packets.end;
104+
""")
105+
106+
except exc.SQLAlchemyError:
107+
raise exc.SQLAlchemyError("Error: Failed to get open packets with signatures received from database")
108+
109+
110+
def query_signed_intromember(member):
111+
"""
112+
Query the database and return the list of packets signed by the given intro member
113+
:param member: the user making the query
114+
:return: list of results matching the query
115+
"""
116+
117+
s = text(
118+
"SELECT DISTINCT packet.freshman_username AS username, signature_fresh.signed AS signed FROM packet "
119+
"INNER JOIN signature_fresh ON packet.id = signature_fresh.packet_id "
120+
"WHERE signature_fresh.freshman_username = :member;")
121+
try:
122+
return db.engine.execute(s, member=member)
123+
124+
except exc.SQLAlchemyError:
125+
raise exc.SQLAlchemyError("Error: Failed to get intromember's signatures from database")
126+
127+
128+
def query_signed_upperclassman(member):
129+
"""
130+
Query the database and return the list of packets signed by the given upperclassman
131+
:param member: the user making the query
132+
:return: list of results matching the query
133+
"""
134+
135+
s = text("SELECT DISTINCT packet.freshman_username AS username, signature_upper.signed AS signed FROM packet "
136+
"INNER JOIN signature_upper ON packet.id = signature_upper.packet_id "
137+
"WHERE signature_upper.member = :member;")
138+
139+
try:
140+
return db.engine.execute(s, member=member)
141+
142+
except exc.SQLAlchemyError:
143+
raise exc.SQLAlchemyError("Error: Failed to get upperclassman's signatures from database")
144+
145+
146+
def query_signed_alumni(member):
147+
"""
148+
Query the database and return the list of packets signed by the given alumni/off-floor
149+
:param member: the user making the query
150+
:return: list of results matching the query
151+
"""
152+
153+
s = text("SELECT DISTINCT packet.freshman_username AS username, signature_misc.member AS signed FROM packet "
154+
"LEFT OUTER JOIN signature_misc ON packet.id = signature_misc.packet_id "
155+
"WHERE signature_misc.member = :member OR signature_misc.member ISNULL;")
156+
157+
try:
158+
return db.engine.execute(s, member=member)
159+
160+
except exc.SQLAlchemyError:
161+
raise exc.SQLAlchemyError("Error: Failed to get alumni's signatures from database")

packet/models.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from datetime import datetime
66
from functools import lru_cache
77

8-
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, Boolean
8+
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, Boolean, and_, or_
99
from sqlalchemy.orm import relationship
1010

1111
from . import db
@@ -50,25 +50,50 @@ def is_open(self):
5050
return self.start < datetime.now() < self.end
5151

5252
@lru_cache(maxsize=1024)
53-
def signatures_required(self):
53+
def signatures_required(self, total=False):
54+
if total:
55+
return len(self.upper_signatures) + len(self.fresh_signatures) + REQUIRED_MISC_SIGNATURES
5456
eboard = UpperSignature.query.with_parent(self).filter_by(eboard=True).count()
5557
return {'eboard': eboard,
5658
'upperclassmen': len(self.upper_signatures) - eboard,
5759
'freshmen': len(self.fresh_signatures),
58-
'misc': REQUIRED_MISC_SIGNATURES}
60+
'miscellaneous': REQUIRED_MISC_SIGNATURES}
5961

60-
def signatures_received(self):
62+
def signatures_received(self, total=False):
6163
"""
6264
Result capped so it will never be greater than that of signatures_required()
6365
"""
64-
eboard_count = UpperSignature.query.with_parent(self).filter_by(signed=True, eboard=True).count()
65-
upper_count = UpperSignature.query.with_parent(self).filter_by(signed=True, eboard=False).count()
66-
fresh_count = FreshSignature.query.with_parent(self).filter_by(signed=True).count()
6766
misc_count = len(self.misc_signatures)
6867

6968
if misc_count > REQUIRED_MISC_SIGNATURES:
7069
misc_count = REQUIRED_MISC_SIGNATURES
7170

71+
if total:
72+
return db.session.query(Packet.freshman_username) \
73+
.select_from(Packet).outerjoin(UpperSignature).outerjoin(FreshSignature) \
74+
.filter(or_(and_(Packet.freshman_username == self.freshman_username, UpperSignature.signed),
75+
and_(Packet.freshman_username == self.freshman_username, FreshSignature.signed))) \
76+
.distinct().count() + misc_count
77+
78+
eboard_count = db.session.query(UpperSignature.member) \
79+
.select_from(Packet).join(UpperSignature) \
80+
.filter(Packet.freshman_username == self.freshman_username,
81+
UpperSignature.signed, UpperSignature.eboard) \
82+
.distinct().count()
83+
84+
upper_count = db.session.query(UpperSignature.member) \
85+
.select_from(Packet).join(UpperSignature) \
86+
.filter(Packet.freshman_username == self.freshman_username,
87+
UpperSignature.signed,
88+
UpperSignature.eboard.isnot(True)) \
89+
.distinct().count()
90+
91+
fresh_count = db.session.query(FreshSignature.freshman_username) \
92+
.select_from(Packet).join(FreshSignature) \
93+
.filter(Packet.freshman_username == self.freshman_username,
94+
FreshSignature.signed) \
95+
.distinct().count()
96+
7297
return {'eboard': eboard_count,
7398
'upperclassmen': upper_count,
7499
'freshmen': fresh_count,

0 commit comments

Comments
 (0)