Skip to content

Commit

Permalink
Add PersonPolicy page
Browse files Browse the repository at this point in the history
- replicate info on similar view in twfy
- for each person and policy - see the relevant votes and alignment.
  • Loading branch information
ajparsons committed Dec 20, 2024
1 parent 88dbae7 commit bf61046
Show file tree
Hide file tree
Showing 7 changed files with 365 additions and 8 deletions.
8 changes: 8 additions & 0 deletions src/votes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,14 @@ def total_votes(self) -> float:
+ self.num_strong_votes_abstain
)

@property
def str_similarity_percentage(self) -> str:
return f"{round((1 - self.distance_score) * 100)}%"

@property
def str_distance_percentage(self) -> str:
return f"{round((self.distance_score) * 100)}%"

@property
def verbose_score(self) -> str:
match self.distance_score:
Expand Down
2 changes: 1 addition & 1 deletion src/votes/templates/votes/person_policies.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

{% block content.inner %}
<h1>{{ person.name }}</h1>
<p>Being compared with {{ party.name }} in {{ chamber.name }}</p>
<p>Compared with {{ party.name }} {{ chamber.member_plural }} in {{ chamber.name }}</p>
<p>This list contains candidate policies that have not been finalised for feeding into TheyWorkForYou.</p>
{% for group in collection %}
{% if group|length > 0 %}
Expand Down
74 changes: 74 additions & 0 deletions src/votes/templates/votes/person_policy.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{% extends "votes/base.html" %}

{% block title %}{{ settings.site_name }}{% endblock %}

{% block content.inner %}
<h1>{{ policy.name }}</h1>
<p>{{ policy.policy_description }}</p>
</p>
View <a href="{{ policy.url }}">policy details</a>.
</p>
<h2>Analysis for {{ person.name }}</h2>
{% if own_distribution %}
<p>
<b>{{ person.name }}</b> {{ own_distribution.verbose_score.lower }} ({{ own_distribution.str_similarity_percentage }} aligned) {{ policy.context_description|safe }}.
</p>
{% endif %}
{% if other_distribution %}
<p>
<b>Comparable {{ party.name }} {{ chamber.member_plural }}</b> {{ other_distribution.verbose_score.lower }} ({{ other_distribution.str_similarity_percentage }} aligned).
</p>
{% endif %}
{% for vote_group, df in decision_links_and_votes.items %}
{% if vote_group == "strong_votes" %}
<h2>Scoring Divisions</h2>
<div class = "group-desc">
{% markdown %}
Scoring divisions are used to calculate the headline alignment between a person and a policy.
{% endmarkdown %}
</div>
{% elif vote_group == "weak_votes" %}
<h2>Informative Divisions</h2>
<div class = "group-desc">
{% markdown %}
Informative votes are thematically related to a policy, but do not count towards the overall score.
{% endmarkdown %}
</div>
{% elif vote_group == "strong_agreements" %}
<h2>Scoring Agreements</h2>
<div class = "group-desc">
{% markdown %}
Scoring agreements contribute to the headline alignment between a person and a policy.
Agreements are when Parliament takes a decision [without holding a vote](https://www.theyworkforyou.com/voting-information/#agreements-and-divisions).
This does not necessarily mean universal approval, but does mean there were no (or few) objections made to the decision being made.
{% endmarkdown %}
</div>
{% elif vote_group == "weak_agreements" %}
<h2>Informative Agreements</h2>
<div class = "group-desc">
{% markdown %}
Scoring agreements are thematically related to a policy, but do not count towards the overall score.
Agreements are when Parliament takes a decision [without holding a vote](https://www.theyworkforyou.com/voting-information/#agreements-and-divisions).
This does not necessarily mean universal approval, but does mean there were no (or few) objections made to the decision being made.
{% endmarkdown %}
</div>
{% endif %}
{% style_df df %}
{% endfor %}
{% endblock content.inner %}

{% block extracss %}
<link rel="stylesheet"
href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.css" />
{% endblock extracss %}

{% block extrajs %}
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function() {
$('table').DataTable({
paging: false
});
});
</script>
{% endblock extrajs %}
3 changes: 3 additions & 0 deletions src/votes/templatetags/hub_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ def render(self, context):
[line[smallest_indent:] for line in markdown_text.splitlines()]
)

# add an extra line space between all new lines
markdown_text = markdown_text.replace("\n", "\n\n\n")

text = markdown.markdown(markdown_text, extensions=["toc"])
return text

Expand Down
64 changes: 63 additions & 1 deletion src/votes/views/api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import datetime
from typing import Literal
from typing import Any, Literal

from django.conf import settings
from django.http import HttpRequest
Expand All @@ -11,15 +11,18 @@
from ..consts import PolicyStatus, RebellionPeriodType
from ..models import (
Agreement,
Chamber,
Division,
DivisionBreakdown,
DivisionPartyBreakdown,
DivisionsIsGovBreakdown,
DivisionTag,
Motion,
Organization,
Person,
Policy,
PolicyAgreementLink,
PolicyComparisonPeriod,
PolicyDivisionLink,
PolicyGroup,
RebellionRate,
Expand All @@ -42,6 +45,24 @@ def authenticate(self, request, token):
api = NinjaAPI(docs_url="/api", title="TheyWorkForYou Votes API")


class OrganizationSchema(ModelSchema):
class Meta:
model = Organization
fields = "__all__"


class ChamberSchema(ModelSchema):
class Meta:
model = Chamber
fields = "__all__"


class PolicyComparisonPeriodSchema(ModelSchema):
class Meta:
model = PolicyComparisonPeriod
fields = "__all__"


class DivisionTagSchema(ModelSchema):
class Meta:
model = DivisionTag
Expand Down Expand Up @@ -215,6 +236,17 @@ class TriggerSchema(Schema):
shortcut: str


class PersonPolicySchema(BaseModel):
person: PersonSchema
chamber: ChamberSchema
period: PolicyComparisonPeriodSchema
party: OrganizationSchema
policy: PolicySchema
own_distribution: VoteDistributionSchema
other_distribution: VoteDistributionSchema
decision_links_and_votes: dict[str, list[dict[str, Any]]]


@api.post("/webhooks/refresh", include_in_schema=False, auth=AuthBearer())
def refresh_webhook(request: HttpRequest, item: TriggerSchema):
"""
Expand Down Expand Up @@ -280,6 +312,36 @@ def get_person_policies(
return [PolicyDisplayGroupSchema.from_basic(x) for x in data["collection"]]


@api.get(
"/person/{person_id}/policies/{chamber_slug}/{party_slug}/{period_slug}/{policy_id}.json",
response=PersonPolicySchema,
)
def get_person_policy(
request: HttpRequest,
person_id: int,
chamber_slug: str,
party_slug: str,
period_slug: str,
policy_id: int,
):
from .views import PersonPolicyView

data = PersonPolicyView().get_context_data(
person_id, chamber_slug, party_slug, period_slug, policy_id
)

data.pop("view")

data["decision_links_and_votes"] = {
x: y.to_dict(orient="records")
for x, y in data["decision_links_and_votes"].items()
}

print(data)

return data


@api.get(
"/decisions/agreement/{chamber_slug}/{date}/{decision_ref}.json",
response=AgreementSchema,
Expand Down
14 changes: 10 additions & 4 deletions src/votes/views/helper_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,14 @@ class ChamberPolicyGroup(BaseModel):

class PolicyCollection(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)

groups: list[PolicyDisplayGroup]

def __iter__(self):
return iter(self.groups)

@classmethod
def from_distributions(
cls, distributions: list[VoteDistribution]
cls, distributions: list[VoteDistribution], url_base: str
) -> list[PolicyDisplayGroup]:
def get_key(v: VoteDistribution) -> str:
return (
Expand Down Expand Up @@ -115,7 +114,11 @@ def get_key(v: VoteDistribution) -> str:

sig_links = [x for x in pp_list if x.significant_difference]
groups.append(
PolicyDisplayGroup(name="Significant Policies", paired_policies=sig_links)
PolicyDisplayGroup(
name="Significant Policies",
paired_policies=sig_links,
url_base=url_base,
)
)

slug_lookup = {x.slug: x for x in PolicyGroup.objects.all()}
Expand All @@ -131,6 +134,7 @@ def get_key(v: VoteDistribution) -> str:
PolicyDisplayGroup(
name=slug_lookup[group_slug].description,
paired_policies=grouped_items,
url_base=url_base,
)
)

Expand All @@ -141,6 +145,7 @@ class PolicyDisplayGroup(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)

name: str
url_base: str
paired_policies: list[PairedPolicy]

def model_dump(self):
Expand Down Expand Up @@ -170,7 +175,8 @@ class GroupTableItem(BaseModel):
item = GroupTableItem(
policy_name=str(
UrlColumn(
url=link.policy.url(),
# url=link.policy.url(), # link direct to policy item
url=self.url_base.replace("99999", str(link.policy.id)),
text=link.policy.context_description or link.policy.name,
)
),
Expand Down
Loading

0 comments on commit bf61046

Please sign in to comment.