From 45ce42a7f2e0f63a8851fc4d512abcceb562137e Mon Sep 17 00:00:00 2001 From: tobiichi3227 Date: Sun, 15 Dec 2024 21:36:03 +0800 Subject: [PATCH 1/8] feat(proset): add problem name search --- src/handlers/pro.py | 27 ++++++++++++++++++++++----- src/static/templ/proset.html | 13 +++++++++++++ src/tests/e2e/proset.py | 10 ++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/handlers/pro.py b/src/handlers/pro.py index fe2e52bb..64898163 100644 --- a/src/handlers/pro.py +++ b/src/handlers/pro.py @@ -61,11 +61,17 @@ async def get(self): except tornado.web.HTTPError: order_reverse = False + try: + search_name = self.get_argument('name') + except tornado.web.HTTPError: + search_name = None + flt = { 'order': order, 'problem_show': problem_show, 'online': show_only_online_pro, 'reverse': order_reverse, + 'name': search_name, } try: @@ -76,7 +82,7 @@ async def get(self): err, prolist = await ProService.inst.list_pro(self.acct) proclass = None - if proclass_id is not None: + if proclass_id: err, proclass = await ProClassService.inst.get_proclass(proclass_id) if err: self.error(err) @@ -96,8 +102,18 @@ async def get(self): _, creator = await UserService.inst.info_acct(proclass['acct_id']) proclass['creator_name'] = creator.name + if search_name: + search_name = set(search_name.lower()) + def _find(name: str): + for ch in name.lower(): + if ch in search_name: + return True + + return False + prolist = filter(lambda pro: _find(pro['name']), prolist) + if show_only_online_pro: - prolist = list(filter(lambda pro: pro['status'] == ProConst.STATUS_ONLINE, prolist)) + prolist = filter(lambda pro: pro['status'] == ProConst.STATUS_ONLINE, prolist) _, acct_states = await RateService.inst.map_rate_acct(self.acct) ac_pro_cnt = 0 @@ -111,14 +127,15 @@ def _set_pro_state_and_tags(pro): return pro - prolist = list(map(lambda pro: _set_pro_state_and_tags(pro), prolist)) + prolist = map(lambda pro: _set_pro_state_and_tags(pro), prolist) if problem_show == "onlyac": - prolist = list(filter(lambda pro: pro['state'] == ChalConst.STATE_AC, prolist)) + prolist = filter(lambda pro: pro['state'] == ChalConst.STATE_AC, prolist) elif problem_show == "notac": - prolist = list(filter(lambda pro: pro['state'] != ChalConst.STATE_AC, prolist)) + prolist = filter(lambda pro: pro['state'] != ChalConst.STATE_AC, prolist) + prolist = list(prolist) for pro in prolist: _, rate = await RateService.inst.get_pro_ac_rate(pro['pro_id']) pro['rate_data'] = rate diff --git a/src/static/templ/proset.html b/src/static/templ/proset.html index 90caf0f7..e47d2b87 100644 --- a/src/static/templ/proset.html +++ b/src/static/templ/proset.html @@ -13,6 +13,7 @@ function get_goto_url(proclass_id) { let order = j_filter.find("#order").val(); let show = j_filter.find("#show").val(); + let search_name = j_filter.find("#name").val(); if (proclass_id == -1) proclass_id = $("#curProclassId").attr("proclass"); let is_online = j_filter.find("#online").is(":checked"); @@ -39,6 +40,10 @@ url += `&proclass_id=${proclass_id}`; } + if (search_name != '') { + url += `&name=${search_name}`; + } + return url; } @@ -308,6 +313,11 @@

Created By: Official

{% end %} +
+ + +
+
@@ -391,6 +401,9 @@

Created By: Official

{% if flt['reverse'] != False %} {% set postfix = postfix + f"&reverse={flt['reverse']}" %} {% end %} + {% if flt['name'] != None %} + {% set postfix = postfix + f"&name={flt['name']}" %} + {% end %}
diff --git a/src/tests/e2e/proset.py b/src/tests/e2e/proset.py index 0875f4ae..7c7f0ebd 100644 --- a/src/tests/e2e/proset.py +++ b/src/tests/e2e/proset.py @@ -57,3 +57,13 @@ async def main(self): self.assertEqual(trs[2].select('td')[3].text.strip().replace('\n', ''), '0.00%(0/ 0)') self.assertEqual(trs[2].select('td')[4].text.strip().replace('\n', ''), '0.00%(0/0)') self.assertEqual(trs[2].select('td')[5].text, '') + + html = self.get_html('proset?name=猜數字', admin_session) + trs = html.select('#prolist > tbody > tr') + self.assertEqual(len(trs), 1) + self.assertEqual(trs[0].select('td')[0].text, '2') + self.assertEqual(trs[0].select('td')[1].text, ChalConst.STATE_LONG_STR[ChalConst.STATE_AC]) + self.assertEqual(trs[0].select('td')[2].text.strip().replace('\n', ''), '猜數字') + self.assertEqual(trs[0].select('td')[3].text.strip().replace('\n', ''), '100.00%(1/ 1)') + self.assertEqual(trs[0].select('td')[4].text.strip().replace('\n', ''), '100.00%(1/1)') + self.assertEqual(trs[0].select('td')[5].text, '') From 10d98229d31b063f4bfe5765a8e105056fcf2069 Mon Sep 17 00:00:00 2001 From: tobiichi3227 Date: Sun, 15 Dec 2024 21:37:13 +0800 Subject: [PATCH 2/8] feat(board): highlight the current column of the user --- src/static/templ/board.html | 2 +- src/tests/e2e/board.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/static/templ/board.html b/src/static/templ/board.html index 65540409..e566365d 100644 --- a/src/static/templ/board.html +++ b/src/static/templ/board.html @@ -150,7 +150,7 @@

{% for acct in acctlist %} {% set acct_id = acct.acct_id %} - + {{ acct.rank }}  {{ acct.name }} {{ acct.rate }} / {{ acct_submit[acct_id] }} diff --git a/src/tests/e2e/board.py b/src/tests/e2e/board.py index e1456eeb..ae980ffa 100644 --- a/src/tests/e2e/board.py +++ b/src/tests/e2e/board.py @@ -38,6 +38,7 @@ async def main(self): self.assertEqual(html.select('th._pro')[0].text, '1') self.assertEqual(html.select('th._pro')[1].text, '2') tr0 = html.select('tbody > tr')[0] + self.assertEqual(tr0.attrs['style'], '--bs-table-bg: #123456;') self.assertEqual(tr0.select_one('td._rank').text.strip(), '1') self.assertEqual(tr0.select_one('td._acct').text.strip(), 'admin') self.assertEqual(tr0.select_one('td._score').text.strip(), '200 / 9') From c5ffe40805f3ba812d569eae1e46c999923821be Mon Sep 17 00:00:00 2001 From: tobiichi3227 Date: Sun, 15 Dec 2024 21:38:35 +0800 Subject: [PATCH 3/8] fix(board): do not use scores to determine if the problem is accepted --- src/services/rate.py | 7 ++++--- src/static/templ/board.html | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/services/rate.py b/src/services/rate.py index c356e9dc..9d4db5d0 100644 --- a/src/services/rate.py +++ b/src/services/rate.py @@ -194,7 +194,8 @@ async def map_rate(self, starttime='1970-01-01 00:00:00.000', endtime='2100-01-0 ''' SELECT "challenge"."acct_id", "challenge"."pro_id", ROUND(MAX("challenge_state"."rate"), (SELECT rate_precision FROM problem WHERE pro_id = challenge.pro_id)) AS "rate", - COUNT("challenge_state") AS "count" + COUNT("challenge_state") AS "count", + MIN("challenge_state"."state") AS "state" FROM "challenge" INNER JOIN "challenge_state" ON "challenge"."chal_id" = "challenge_state"."chal_id" @@ -208,7 +209,7 @@ async def map_rate(self, starttime='1970-01-01 00:00:00.000', endtime='2100-01-0 ) statemap = defaultdict(dict) - for acct_id, pro_id, rate, count in result: - statemap[acct_id][pro_id] = {'rate': rate, 'count': count} + for acct_id, pro_id, rate, count, state in result: + statemap[acct_id][pro_id] = {'rate': rate, 'count': count, 'state': state} return None, statemap diff --git a/src/static/templ/board.html b/src/static/templ/board.html index e566365d..035e9880 100644 --- a/src/static/templ/board.html +++ b/src/static/templ/board.html @@ -1,4 +1,5 @@ {% import math %} +{% from services.chal import ChalConst %}