Skip to content

Commit

Permalink
Merge pull request #224 from orertrr/public-statistics
Browse files Browse the repository at this point in the history
Add public statistics page
  • Loading branch information
toomore authored Jul 31, 2024
2 parents eb955c1 + 9a6390d commit da2d363
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 1 deletion.
34 changes: 34 additions & 0 deletions module/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,27 @@ def all_clothes(pid: str) -> Generator[dict[str, Any], None, None]:
'''
yield from FormDB().find({'case': 'clothes', 'pid': pid})

@staticmethod
def get_clothes_statistics(pid: str) -> dict[str, int]:
''' Get clothes statistics by given pid '''
result = {
'XS': 0,
'S': 0,
'M': 0,
'L': 0,
'XL': 0,
'2XL': 0,
'3XL': 0,
'4XL': 0,
'5XL': 0,
'6XL': 0,
}

for form in Form.all_clothes(pid=pid):
result[form['data']['clothes']] += 1

return result

@staticmethod
def update_parking_card(pid: str, uid: str, data: dict[str, Any]) -> dict[str, Any]:
''' Update parking card
Expand Down Expand Up @@ -429,6 +450,19 @@ def get(pid: str) -> Generator[dict[str, Any], None, None]:
'''
yield from FormDB().find({'case': 'accommodation', 'pid': pid, 'data.key': {'$ne': 'no'}})

@staticmethod
def get_statistics(pid: str) -> dict[str, int]:
''' Get accommodation statistics by given pid '''
result = {
'yes': 0,
'yes-longtraffic': 0,
}

for form in FormAccommodation.get(pid=pid):
result[form['data']['key']] += 1

return result

@staticmethod
def update_room(pid: str, uid: str, room: str, change_key: bool = True) -> dict[str, Any]:
''' Update room no
Expand Down
22 changes: 21 additions & 1 deletion module/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from models.oauth_db import OAuthDB
from models.users_db import PolicySignedDB, TobeVolunteerDB, UsersDB
from module.dietary_habit import DietaryHabitItemsValue
from module.dietary_habit import DietaryHabitItemsName, DietaryHabitItemsValue
from module.mattermost_bot import MattermostTools
from module.skill import TobeVolunteerStruct
from structs.users import PolicyType
Expand Down Expand Up @@ -425,6 +425,26 @@ def marshal_dietary_habit(user_infos: dict[str, Any]) -> Generator[dict[str, Any

yield data

@staticmethod
def get_dietary_habit_statistics(uids: list[str]) -> dict[str, int]:
''' Get dietary habit statistics by given uids '''
result: dict[str, int] = { }

for item in DietaryHabitItemsName:
result[item.value] = 0

user_infos = User.get_info(uids=uids)
for user_info in user_infos.values():
if "profile_real" not in user_info or \
"dietary_habit" not in user_info["profile_real"]:
continue

for habit in user_info["profile_real"]["dietary_habit"]:
habit_enum_name = DietaryHabitItemsValue(habit).name
result[DietaryHabitItemsName[habit_enum_name].value] += 1

return result


class TobeVolunteer:
''' TobeVolunteer '''
Expand Down
91 changes: 91 additions & 0 deletions templates/project_statistics.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{% extends "base.html" %}
{% block head_title %}{{project.name}} 統計資訊{% endblock %}
{% block body %}
<section class="section">
<div class="container">
<h1 class="title">
{{project.name}}
</h1>
<div class="content">
<p>{{project.desc}}</p>
{% if editable %}
<div class="buttons is-right">
<a class="button is-info is-light" href="/project/{{project._id}}/edit">
<span class="icon"><i class="far fa-edit"></i></span> <span>Edit</span>
</a>
</div>
{% endif %}
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="tabs">
<ul>
<li><a href="/project/{{project._id}}">組別列表</a></li>
<li class="is-active"><a>統計資訊</a></li>
</ul>
</div>
<div class="columns">
<div class="column">
<h4 class="title is-4">飲食習慣人數分布</h4>
<table class="table">
<thead>
<th>習慣</th>
<th>人數</th>
</thead>
<tbody>
{% for habit, count in habit_statistics.items() %}
<tr>
<td>{{ habit }}</td>
<td>{{ count }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="column">
<h4 class="title is-4">衣服尺寸人數分布</h4>
<table class="table">
<thead>
<th>尺寸</th>
<th>人數</th>
</thead>
<tbody>
{% for clothes_size, count in clothes_statistics.items() %}
<tr>
<td>{{ clothes_size }}</td>
<td>{{ count }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="column">
<h4 class="title is-4">住宿人數</h4>
<table class="table">
<thead>
<th>住宿選項</th>
<th>人數</th>
</thead>
<tbody>
{% for accmmodation_option, count in accommodation_statictics.items() %}
{% if accmmodation_option == 'yes' %}
<tr>
<td>需要住宿</td>
<td>{{ count }}</td>
</tr>
{% elif accmmodation_option == 'yes-longtraffic' %}
<tr>
<td>需要住宿,且通勤時間大於一小時</td>
<td>{{ count }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</section>
{% endblock %}
6 changes: 6 additions & 0 deletions templates/project_teams_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ <h1 class="title">
</section>
<section class="section">
<div class="container">
<div class="tabs">
<ul>
<li class="is-active"><a>組別列表</a></li>
<li><a href="/project/{{project._id}}/statistics">統計資訊</a></li>
</ul>
</div>
<div class="content">
<p><span class="tag">總人數:{{total}}</span></p>
</div>
Expand Down
28 changes: 28 additions & 0 deletions view/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,34 @@ def team_page(pid: str) -> str | ResponseBase:
)


@VIEW_PROJECT.route('/<pid>/statistics', methods=('GET',))
def project_statictics(pid: str) -> str | ResponseBase:
''' Statistics page '''
project = Project.get(pid)
if not project:
return Response('no data', status=404)

editable = g.user['account']['_id'] in project.owners

all_users = set()
for team in Team.list_by_pid(pid=pid):
if team.chiefs:
all_users.update(team.chiefs)
if team.members:
all_users.update(team.members)

habit_statistics = User.get_dietary_habit_statistics(uids=list(all_users))
clothes_statistics = Form.get_clothes_statistics(pid=pid)
accommodation_statictics = FormAccommodation.get_statistics(pid=pid)

return render_template('./project_statistics.html',
project=project.dict(by_alias=True),
habit_statistics=habit_statistics,
clothes_statistics=clothes_statistics,
accommodation_statictics=accommodation_statictics,
editable=editable)


@VIEW_PROJECT.route('/<pid>/form_traffic_mapping', methods=('GET', 'POST'))
def project_form_traffic_mapping(pid: str) -> str | ResponseBase:
''' Project form traffic mapping '''
Expand Down

0 comments on commit da2d363

Please sign in to comment.