def build_info():
feeds = [f for f in Feed.get_simple_feeds() if f.category == "federal-bills"]
groups = [
( g[0], # title
g[1], # text 1
g[2], # text 2
"/congress/bills/browse?status=" + ",".join(str(s) for s in g[4]), # link
load_bill_status_qs(g[4]).count(), # count in category
load_bill_status_qs(g[4]).order_by('-current_status_date')[0:6], # top 6 in this category
)
for g in bill_status_groups ]
dhg_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=10)).filter(docs_house_gov_postdate__gt=F('current_status_date'))
sfs_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=5)).filter(senate_floor_schedule_postdate__gt=F('current_status_date'))
coming_up = list(dhg_bills | sfs_bills)
coming_up.sort(key = lambda b : b.docs_house_gov_postdate if (b.docs_house_gov_postdate and (not b.senate_floor_schedule_postdate or b.senate_floor_schedule_postdate < b.docs_house_gov_postdate)) else b.senate_floor_schedule_postdate, reverse=True)
start, end = get_congress_dates(CURRENT_CONGRESS)
end_year = end.year if end.month > 1 else end.year-1 # count January finishes as the prev year
current_congress_years = '%d-%d' % (start.year, end.year)
current_congress = ordinal(CURRENT_CONGRESS)
return {
"feeds": feeds,
"total": Bill.objects.filter(congress=CURRENT_CONGRESS).count(),
"current_congress_years": current_congress_years,
"current_congress": current_congress,
"groups": groups,
"coming_up": coming_up,
"subjects": subject_choices(),
"BILL_STATUS_INTRO": (BillStatus.introduced, BillStatus.referred, BillStatus.reported),
}
def get_roles_of_people(congressnumber):
congress_dates = get_congress_dates(congressnumber)
return PersonRole.objects.filter(
role_type__in=(RoleType.senator, RoleType.representative),
startdate__lt=congress_dates[1], # start dates of next congress are on this day too
enddate__gt=congress_dates[0] # end dates from previous congress are on this day too
).select_related("person")\
.order_by('-startdate') # so we put people in the right list by their most recent term
def bill_text(request, congress, type_slug, number, version=None):
if version == "":
version = None
try:
bill_type = BillType.by_slug(type_slug)
except BillType.NotFound:
raise Http404("Invalid bill type: " + type_slug)
bill = get_object_or_404(Bill, congress=congress, bill_type=bill_type, number=number)
from .billtext import load_bill_text, get_bill_text_versions
try:
textdata = load_bill_text(bill, version)
except IOError:
textdata = None
# Get a list of the alternate versions of this bill.
alternates = None
is_latest = True
if textdata:
alternates = []
for v in get_bill_text_versions(bill):
try:
alternates.append(load_bill_text(bill, v, mods_only=True))
except IOError:
pass
alternates.sort(key = lambda mods : mods["docdate"])
if len(alternates) > 0:
is_latest = False
if textdata["doc_version"] == alternates[-1]["doc_version"]:
is_latest = True
# Get a list of related bills.
from .billtext import get_current_version
related_bills = []
for rb in list(bill.find_reintroductions()) + [r.related_bill for r in bill.get_related_bills()]:
try:
rbv = get_current_version(rb)
if not (rb, rbv) in related_bills: related_bills.append((rb, rbv))
except IOError:
pass # text not available
for btc in BillTextComparison.objects.filter(bill1=bill).exclude(bill2=bill):
if not (btc.bill2, btc.ver2) in related_bills: related_bills.append((btc.bill2, btc.ver2))
for btc in BillTextComparison.objects.filter(bill2=bill).exclude(bill1=bill):
if not (btc.bill1, btc.ver1) in related_bills: related_bills.append((btc.bill1, btc.ver1))
return {
"bill_subpage": "Text",
'bill': bill,
"congressdates": get_congress_dates(bill.congress),
"textdata": textdata,
"version": version,
"is_latest": is_latest,
"alternates": alternates,
"related_bills": related_bills,
"days_old": (datetime.datetime.now().date() - bill.current_status_date).days,
"is_on_bill_text_page": True, # for the header tabs
}
def analysis_methodology(request):
from settings import CURRENT_CONGRESS
from person.models import RoleType
from bill.models import BillType
from us import get_congress_dates
import json
from person.analysis import load_sponsorship_analysis2
def make_chart_series(role_type):
data = load_sponsorship_analysis2(CURRENT_CONGRESS, role_type, None)
if not data: return None
ret = { }
for p in data["all"]:
ret.setdefault(p["party"], {
"type": "party",
"party": p["party"],
"data": [],
})["data"].append({
"x": float(p["ideology"]),
"y": float(p["leadership"]),
"name": p["name"],
})
ret = list(ret.values())
ret.sort(key = lambda s : len(s["data"]), reverse=True)
data = dict(data) # clone before modifying, just in case
data["series"] = json.dumps(ret)
return data
import bill.prognosis
import bill.prognosis_model
import bill.prognosis_model_test
prognosis_factors = sorted([dict(v) for v in bill.prognosis_model.factors.values()],
key = lambda m : m["count"], reverse=True)
for v in prognosis_factors:
v["factors"] = sorted(v["factors"].values(), key = lambda f : f["regression_beta"], reverse=True)
prognosis_test = sorted(bill.prognosis_model_test.model_test_results.values(),
key = lambda v : v["count"], reverse=True)
return {
"ideology": lambda : { # defer until cache miss
"house": make_chart_series(RoleType.representative),
"senate": make_chart_series(RoleType.senator),
},
"current_congress": CURRENT_CONGRESS,
"prognosis_training_congress": bill.prognosis_model.congress,
"prognosis_training_congress_dates": get_congress_dates(bill.prognosis_model.congress),
"prognosis_factors": prognosis_factors,
"prognosis_test": prognosis_test,
"prognosis_testing_traincongress": bill.prognosis_model_test.train_congress,
"prognosis_testing_testcongress": bill.prognosis_model_test.test_congress,
}
def build_info():
# feeds about all legislation that we offer the user to subscribe to
feeds = [f for f in Feed.get_simple_feeds() if f.category == "federal-bills"]
# info about bills by status
groups = [
( g[0], # title
g[1], # text 1
g[2], # text 2
"/congress/bills/browse?status=" + ",".join(str(s) for s in g[4]) + "&sort=-current_status_date", # link
load_bill_status_qs(g[4]).count(), # count in category
load_bill_status_qs(g[4]).order_by('-current_status_date')[0:6], # top 6 in this category
)
for g in bill_status_groups ]
# legislation coming up
dhg_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=10)).filter(docs_house_gov_postdate__gt=F('current_status_date'))
sfs_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=5)).filter(senate_floor_schedule_postdate__gt=F('current_status_date'))
coming_up = list(dhg_bills | sfs_bills)
coming_up.sort(key = lambda b : b.docs_house_gov_postdate if (b.docs_house_gov_postdate and (not b.senate_floor_schedule_postdate or b.senate_floor_schedule_postdate < b.docs_house_gov_postdate)) else b.senate_floor_schedule_postdate, reverse=True)
# top tracked bills
top_bills = Feed.objects\
.filter(feedname__startswith='bill:')\
.filter(feedname__regex='^bill:[hs][jcr]?%d-' % CURRENT_CONGRESS)
top_bills = top_bills\
.annotate(count=Count('tracked_in_lists'))\
.order_by('-count')\
.values('feedname', 'count')\
[0:25]
top_bills = [(Bill.from_feed(Feed.from_name(bf["feedname"])), bf["count"]) for bf in top_bills]
# current congrss years
start, end = get_congress_dates(CURRENT_CONGRESS)
end_year = end.year if end.month > 1 else end.year-1 # count January finishes as the prev year
current_congress_years = '%d-%d' % (start.year, end.year)
current_congress = ordinal(CURRENT_CONGRESS)
return {
"feeds": feeds,
"total": Bill.objects.filter(congress=CURRENT_CONGRESS).count(),
"current_congress_years": current_congress_years,
"current_congress": current_congress,
"groups": groups,
"coming_up": coming_up,
"top_tracked_bills": top_bills,
"subjects": subject_choices(),
"BILL_STATUS_INTRO": (BillStatus.introduced, BillStatus.referred, BillStatus.reported),
}
def build_info():
# feeds about all legislation that we offer the user to subscribe to
feeds = [f for f in Feed.get_simple_feeds() if f.category == "federal-bills"]
# info about bills by status
groups = [
( g[0], # title
g[1], # text 1
g[2], # text 2
"/congress/bills/browse?status=" + ",".join(str(s) for s in g[4]) + "&sort=-current_status_date", # link
load_bill_status_qs(g[4]).count(), # count in category
load_bill_status_qs(g[4]).order_by('-current_status_date')[0:6], # top 6 in this category
)
for g in bill_status_groups ]
# legislation coming up
dhg_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, docs_house_gov_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=10)).filter(docs_house_gov_postdate__gt=F('current_status_date'))
sfs_bills = Bill.objects.filter(congress=CURRENT_CONGRESS, senate_floor_schedule_postdate__gt=datetime.datetime.now() - datetime.timedelta(days=5)).filter(senate_floor_schedule_postdate__gt=F('current_status_date'))
coming_up = list((dhg_bills | sfs_bills).order_by('scheduled_consideration_date'))
# top tracked bills
top_bills = Feed.objects\
.filter(feedname__startswith='bill:')\
.filter(feedname__regex='^bill:[hs][jcr]?%d-' % CURRENT_CONGRESS)
top_bills = top_bills\
.annotate(count=Count('tracked_in_lists'))\
.order_by('-count')\
.values('feedname', 'count')\
[0:25]
top_bills = [(Bill.from_feed(Feed.from_name(bf["feedname"])), bf["count"]) for bf in top_bills]
# trending bills
trf = Feed.get_trending_feeds()
trf = [Feed.objects.get(id=f) for f in trf]
trending_bill_feeds = [f for f in trf if f.feedname.startswith("bill:")]
return {
"feeds": feeds,
"total": Bill.objects.filter(congress=CURRENT_CONGRESS).count(),
"current_congress": CURRENT_CONGRESS,
"current_congress_dates": get_congress_dates(CURRENT_CONGRESS),
"groups": groups,
"coming_up": coming_up,
"top_tracked_bills": top_bills,
"trending_bill_feeds": trending_bill_feeds,
"subjects": subject_choices(),
"BILL_STATUS_INTRO": (BillStatus.introduced, BillStatus.reported),
}
def bill_text(request, congress, type_slug, number, version=None):
if version == "":
version = None
try:
bill_type = BillType.by_slug(type_slug)
except BillType.NotFound:
raise Http404("Invalid bill type: " + type_slug)
bill = get_object_or_404(Bill, congress=congress, bill_type=bill_type, number=number)
from billtext import load_bill_text, bill_gpo_status_codes
try:
textdata = load_bill_text(bill, version)
except IOError:
textdata = None
# Get a list of the alternate versions of this bill.
alternates = None
if textdata:
alternates = []
for v in bill_gpo_status_codes:
try:
alternates.append(load_bill_text(bill, v, mods_only=True))
except IOError:
pass
alternates.sort(key = lambda mods : mods["docdate"])
# Get a list of related bills.
from billtext import get_current_version
related_bills = []
for rb in list(bill.find_reintroductions()) + [r.related_bill for r in bill.get_related_bills()]:
try:
rbv = get_current_version(rb)
if not (rb, rbv) in related_bills: related_bills.append((rb, rbv))
except IOError:
pass # text not available
for btc in BillTextComparison.objects.filter(bill1=bill).exclude(bill2=bill):
if not (btc.bill2, btc.ver2) in related_bills: related_bills.append((btc.bill2, btc.ver2))
for btc in BillTextComparison.objects.filter(bill2=bill).exclude(bill1=bill):
if not (btc.bill1, btc.ver1) in related_bills: related_bills.append((btc.bill1, btc.ver1))
return {
'bill': bill,
"congressdates": get_congress_dates(bill.congress),
"textdata": textdata,
"version": version,
"alternates": alternates,
"related_bills": related_bills,
}
def bill_text(request, congress, type_slug, number, version=None):
if int(congress) < 103:
raise Http404("Bill text is not available before the 103rd congress.")
if version == "":
version = None
try:
bill_type = BillType.by_slug(type_slug)
except BillType.NotFound:
raise Http404("Invalid bill type: " + type_slug)
bill = get_object_or_404(Bill, congress=congress, bill_type=bill_type, number=number)
from billtext import load_bill_text, bill_gpo_status_codes
try:
textdata = load_bill_text(bill, version)
except IOError:
textdata = None
# Get a list of the alternate versions of this bill.
alternates = None
if textdata:
alternates = []
for v in bill_gpo_status_codes:
fn = "data/us/bills.text/%s/%s/%s%d%s.mods.xml" % (bill.congress, BillType.by_value(bill.bill_type).xml_code, BillType.by_value(bill.bill_type).xml_code, bill.number, v)
if os.path.exists(fn):
alternates.append(load_bill_text(bill, v, mods_only=True))
alternates.sort(key = lambda mods : mods["docdate"])
# Get a list of related bills.
related_bills = []
for rb in list(bill.find_reintroductions()) + [r.related_bill for r in bill.get_related_bills()]:
if not (rb, "") in related_bills: related_bills.append((rb, ""))
for btc in BillTextComparison.objects.filter(bill1=bill):
if not (btc.bill2, btc.ver2) in related_bills: related_bills.append((btc.bill2, btc.ver2))
for btc in BillTextComparison.objects.filter(bill2=bill):
if not (btc.bill1, btc.ver1) in related_bills: related_bills.append((btc.bill1, btc.ver1))
return {
'bill': bill,
"congressdates": get_congress_dates(bill.congress),
"textdata": textdata,
"version": version,
"alternates": alternates,
"related_bills": related_bills,
}
def bill_statistics(request):
# Get the count of bills by status and by Congress.
counts_by_congress = []
for c in xrange(93, CURRENT_CONGRESS+1):
total = Bill.objects.filter(congress=c).count()
if total == 0: continue # during transitions between Congresses
counts_by_congress.append({
"congress": c,
"dates": get_congress_dates(c),
"counts": [ ],
"total": total,
})
for g in bill_status_groups:
t = load_bill_status_qs(g[4], congress=c).count()
counts_by_congress[-1]["counts"].append(
{ "count": t,
"percent": "%0.0f" % float(100.0*t/total),
"link": "/congress/bills/browse?congress=%s&status=%s" % (c, ",".join(str(s) for s in g[4])),
} )
counts_by_congress.reverse()
# When does activity occur within the session cycle?
if settings.DATABASES['default']['ENGINE'] != 'django.db.backends.sqlite3':
from django.db import connection
def pull_time_stat(field, where, cursor):
historical = False
cursor.execute("SELECT YEAR(%s) - congress*2 - 1787, MONTH(%s), COUNT(*) FROM bill_bill WHERE congress>=93 AND congress%s%d AND %s GROUP BY YEAR(%s) - congress*2, MONTH(%s)" % (field, field, "<" if historical else "=", CURRENT_CONGRESS, where, field, field))
activity = [{ "x": r[0]*12 + (r[1]-1), "count": r[2], "year": r[0] } for r in cursor.fetchall()]
total = sum(m["count"] for m in activity)
for i, m in enumerate(activity): m["cumulative_count"] = m["count"]/float(total) + (0.0 if i==0 else activity[i-1]["cumulative_count"])
for m in activity: m["count"] = round(m["count"] / (CURRENT_CONGRESS-96), 1)
for m in activity: m["cumulative_count"] = round(m["cumulative_count"] * 100.0)
return activity
with connection.cursor() as cursor:
activity_introduced_by_month = pull_time_stat('introduced_date', "1", cursor)
activity_enacted_by_month = pull_time_stat('current_status_date', "current_status IN (%d,%d,%d)" % (int(BillStatus.enacted_signed), int(BillStatus.enacted_veto_override), int(BillStatus.enacted_tendayrule)), cursor)
else:
activity_introduced_by_month = []
activity_enacted_by_month = []
return {
"groups2": bill_status_groups,
"counts_by_congress": counts_by_congress,
"activity": (("Bills and Resolutions Introduced", activity_introduced_by_month),
("Bills and Joint Resolutions Enacted", activity_enacted_by_month) )
}
def proscore(self):
"""A modified prognosis score that omits factors associated with uninteresting bills, such as naming post offices. Only truly valid for current bills, and useless to compare across Congresses, but returns a value for all bills."""
# To aid search, especially for non-current bills, add in something to give most recently active bills a boost.
type_boost = {
BillType.senate_bill: 1.0, BillType.house_bill: 1.0,
BillType.senate_resolution: 0.2, BillType.house_resolution: 0.2,
BillType.senate_concurrent_resolution: 0.3, BillType.house_concurrent_resolution: 0.3,
BillType.senate_joint_resolution: 0.75, BillType.house_joint_resolution: 0.75,
}
cstart, cend = get_congress_dates(self.congress)
csd = self.current_status_date
if hasattr(csd, 'date'): csd = csd.date()
r = (csd - cstart).days / 365.0 # ranges from 0.0 to about 2.0.
if self.is_current:
from prognosis import compute_prognosis
r += compute_prognosis(self, proscore=True)["prediction"]
r *= type_boost[self.bill_type]
return r
def bill_details(request, congress, type_slug, number):
bill = load_bill_from_url(congress, type_slug, number)
# get related bills
related_bills = []
reintro_prev = None
reintro_next = None
for reintro in bill.find_reintroductions():
if reintro.congress < bill.congress: reintro_prev = reintro
if reintro.congress > bill.congress and not reintro_next: reintro_next = reintro
if reintro_prev: related_bills.append({ "bill": reintro_prev, "note": "was a previous version of this bill.", "show_title": False })
if reintro_next: related_bills.append({ "bill": reintro_next, "note": "was a re-introduction of this bill in a later Congress.", "show_title": False })
for rb in bill.get_related_bills():
if rb.relation in ("identical", "rule"):
related_bills.append({ "bill": rb.related_bill, "note": "(%s)" % rb.relation, "show_title": False })
elif rb.relation == "ruled-by":
related_bills.append({ "bill": rb.related_bill, "prenote": "Debate on", "note": " is governed by these rules.", "show_title": False })
else:
related_bills.append({ "bill": rb.related_bill, "note": ("(%s)" % (rb.relation.title() if rb.relation != "unknown" else "Related")), "show_title": True })
# bill text info and areas of law affected
from billtext import load_bill_text
try:
text_info = load_bill_text(bill, None, mods_only=True, with_citations=True)
except IOError:
text_info = None
return {
'bill': bill,
"congressdates": get_congress_dates(bill.congress),
"subtitle": get_secondary_bill_title(bill, bill.titles),
"current": bill.congress == CURRENT_CONGRESS,
"dead": bill.congress != CURRENT_CONGRESS and bill.current_status not in BillStatus.final_status_obvious,
"feed": bill.get_feed(),
"text_info": text_info,
"related": related_bills,
}
#.........这里部分代码省略.........
for reintro in bill.find_reintroductions():
if reintro.congress < bill.congress: reintro_prev = reintro
if reintro.congress > bill.congress and not reintro_next: reintro_next = reintro
return reintro_prev, reintro_next
def get_text_info():
from models import USCSection
from billtext import load_bill_text
from search import parse_slip_law_number
import re
try:
metadata = load_bill_text(bill, None, mods_only=True)
# do interesting stuff with citations
if "citations" in metadata:
slip_laws = []
statutes = []
usc = { }
other = []
usc_other = USCSection(name="Other Citations", ordering=99999)
for cite in metadata["citations"]:
if cite["type"] == "slip_law":
slip_laws.append(cite)
cite["bill"] = parse_slip_law_number(cite["text"])
elif cite["type"] == "statutes_at_large":
statutes.append(cite)
elif cite["type"] == "usc":
# build a normalized citation and a link to LII
cite_norm = "usc/" + cite["title"]
cite_link = "http://www.law.cornell.edu/uscode/text/" + cite["title"]
if cite["section"]:
cite_link += "/" + cite["section"]
cite_norm += "/" + cite["section"]
if cite["paragraph"]: cite_link += "#" + "_".join(re.findall(r"\(([^)]+)\)", cite["paragraph"]))
# Build a tree of title-chapter-...-section nodes so we can
# display the citations in context.
try:
sec_obj = USCSection.objects.get(citation=cite_norm)
except: # USCSection.DoesNotExist and MultipleObjectsReturned both possible
# the 'id' field is set to make these objects properly hashable
sec_obj = USCSection(id=cite["text"], name=cite["text"], parent_section=usc_other)
sec_obj.link = cite_link
if "range_to_section" in cite:
sec_obj.range_to_section = cite["range_to_section"]
# recursively go up to the title
path = [sec_obj]
while sec_obj.parent_section:
sec_obj = sec_obj.parent_section
path.append(sec_obj)
# now pop off from the path to put the node at the right point in a tree
container = usc
while path:
p = path.pop(-1)
if p not in container: container[p] = { }
container = container[p]
else:
other.append(cite)
slip_laws.sort(key = lambda x : (x["congress"], x["number"]))
# restructure data format
def ucfirst(s): return s[0].upper() + s[1:]
def rebuild_usc_sec(seclist, indent=0):
ret = []
seclist = sorted(seclist.items(), key=lambda x : x[0].ordering)
for sec, subparts in seclist:
ret.append({
"text": (ucfirst(sec.level_type + ((" " + sec.number) if sec.number else "") + (": " if sec.name else "")) if sec.level_type else "") + (sec.name if sec.name else ""),
"link": getattr(sec, "link", None),
"range_to_section": getattr(sec, "range_to_section", None),
"indent": indent,
})
ret.extend(rebuild_usc_sec(subparts, indent=indent+1))
return ret
usc = rebuild_usc_sec(usc)
metadata["citations"] = {
"slip_laws": slip_laws, "statutes": statutes, "usc": usc, "other": other,
"count": len(slip_laws)+len(statutes)+len(usc)+len(other) }
return metadata
except IOError:
return None
return {
'bill': bill,
"congressdates": get_congress_dates(bill.congress),
"subtitle": get_secondary_bill_title(bill, bill.titles),
"sponsor_name": sponsor_name,
"reintros": get_reintroductions, # defer so we can use template caching
"current": bill.congress == CURRENT_CONGRESS,
"dead": bill.congress != CURRENT_CONGRESS and bill.current_status not in BillStatus.final_status_obvious,
"feed": Feed.BillFeed(bill),
"text": get_text_info,
}
请发表评论