Skip to content

Commit

Permalink
更新tag、作弊者、性别等多项功能
Browse files Browse the repository at this point in the history
  • Loading branch information
Gingmzmzx committed Jun 9, 2024
1 parent 60958fe commit 5841d95
Show file tree
Hide file tree
Showing 25 changed files with 108 additions and 42 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
AKIOIOJ并无预构建的Docker镜像,不过您可以使用`vijos/vj4`,参见[vijos/vj4-docker](https://github.com/vijos/vj4-docker)
- 下载vj4-docker中的`docker-compose.yml`文件,将其放置于工作目录下;
- 然后创建`data/app/`目录,并将本仓库克隆。
- 修改`docker-compose.yml`中的`services.web.volumes`,添加一行`- "./data/app:/app"`
- 修改`docker-compose.yml`中的`services.web.volumes`,添加一行`- "./data/app:/app"`
**注意!您可能也需要将`services.mongodb.image`改为`mongo:4.4.0`,使用`mongo:latest`会出现错误!**
- 执行`docker-compose up -d`启动

Expand Down
20 changes: 19 additions & 1 deletion vj4/handler/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,30 @@ async def get(self, *, uid: int):
ddocs = []
vndict = {}
dcount = 0

set_cheat_perm = self.has_perm(builtin.PERM_USER_SET_CHEAT)

self.render('user_detail.html', is_self_profile=is_self_profile,
udoc=udoc, dudoc=dudoc, sdoc=sdoc,
rdocs=rdocs, pdict=pdict, pdocs=pdocs, pcount=pcount,
psdocs=psdocs, pscount=pscount, psdocs_hot=psdocs_hot,
ddocs=ddocs, dcount=dcount, vndict=vndict)
ddocs=ddocs, dcount=dcount, vndict=vndict,
set_cheat_perm=set_cheat_perm)


@app.route('/user/{uid:-?\d+}/set_cheat', 'user_set_cheat')
class UserCheatHandler(base.Handler, UserSettingsMixin):
@base.route_argument
@base.sanitize
@base.require_perm(builtin.PERM_USER_SET_CHEAT)
async def get(self, *, uid: int):
udoc = await user.get_by_uid(uid)
if not udoc:
raise error.UserNotFoundError(uid)
status = not udoc.get("cheater", False)
await user.set_cheat(uid, status)

self.json_or_redirect(self.reverse_url('user_detail', uid=uid))


@app.route('/user/search', 'user_search')
Expand Down
1 change: 1 addition & 0 deletions vj4/locale/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ perm_discussion: Discussions
perm_contest: Contests
perm_training: Trainings
perm_ranking: Ranking
perm_user: User
discussion_edit: Discussion Edit
wiki_help: Help
no_translation_warn: <blockquote class="warn">This part of content is under translation.</blockquote>
Expand Down
6 changes: 4 additions & 2 deletions vj4/locale/zh_CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Browser: 浏览器
? By signing up a Vijos universal account, you can submit code and join discussions in all online
judging services provided by us.
: 注册一个 AKIOI OJ 通用账户,您就可以在我们提供的所有在线评测服务上提交代码、参与讨论。
Cheater: 作弊者
CLOSE: 关闭
Cancel: 取消
Ok: 确定
Expand Down Expand Up @@ -80,7 +81,7 @@ Footer: 页脚
Forgot password or username?: 忘记密码或者用户名?
Gender: 性别
Gender Visibility: 性别可见性
Gravatar Email: Gravatar Email 地址
Gravatar Email: 头像图片地址
'Hello! You can click following link to sign up your Vijos account:': 您好!您可以点击以下链接来注册您的 AKIOI OJ 账户:
'Hello, {0}! You can click following link to reset the password of your Vijos account:': 您好,{0}!您可以点击以下链接来重置您
AKIOI OJ 账户的密码:
Expand Down Expand Up @@ -215,7 +216,6 @@ View or create discussion: 查看与发表讨论
View or submit solution: 查看与发表题解
Visible to registered users: 对注册用户可见
Vote: 投票
'We use <a href="https://en.gravatar.com/" target="_blank">Gravatar</a> to present your avatar icon.': '我们使用 <a href="https://cn.gravatar.com/" target="_blank">Gravatar</a> 服务来呈现您的头像。'
Whether to show tags in the problem list.: 是否在题目列表中显示题目的标签。
Write Your Comment: 发表您的评论
Write Your Solution: 发表您的题解
Expand Down Expand Up @@ -538,6 +538,7 @@ perm_contest: 比赛
perm_homework: 作业
perm_training: 训练
perm_ranking: 排名
perm_user: 用户
discussion_edit: 编辑讨论
At least 4 characters: 至少 4 个字符
Contact: 联系
Expand Down Expand Up @@ -743,6 +744,7 @@ Create homework: 创建作业
Claim homework: 认领作业
Edit any homework: 修改任意的作业
Edit own homework: 修改自己的作业
Set user as Cheater: 设置用户为作弊者
Can be Extended For: 可延期
Open Since: 开始时间
Hard Deadline: 最终截止时间
Expand Down
4 changes: 3 additions & 1 deletion vj4/locale/zh_TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Browser: 瀏覽器
? By signing up a Vijos universal account, you can submit code and join discussions in all online
judging services provided by us.
: 註冊一個 AKIOI OJ 通用賬戶,您就可以在我們提供的所有線上評測服務上提交程式碼、參與討論。
Cheater: 作弊者
CLOSE: 關閉
Cancel: 取消
Ok: 確定
Expand Down Expand Up @@ -83,7 +84,7 @@ Footer: 頁尾
Forgot password or username?: 忘記密碼或者使用者名?
Gender: 性別
Gender Visibility: 性別可見性
Gravatar Email: Gravatar Email 地址
Gravatar Email: 头像图片地址
'Hello! You can click following link to sign up your Vijos account:': 您好!您可以點選以下連結來註冊您的 AKIOI OJ 賬戶:
'Hello, {0}! You can click following link to reset the password of your Vijos account:': 您好,{0}!您可以點選以下連結來重置您
AKIOI OJ 賬戶的密碼:
Expand Down Expand Up @@ -570,6 +571,7 @@ Create homework: 創建功課
Claim homework: 認領功課
Edit any homework: 修改任意功課
Edit own homework: 修改自己的功課
Set user as Cheater: 设置用户为作弊者
Can be Extended For: 可延期
Open Since: 開始時間
Hard Deadline: 最終截止時間
Expand Down
2 changes: 1 addition & 1 deletion vj4/model/adaptor/setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
ACCOUNT_SETTINGS = [
Setting('setting_info', 'gravatar', str,
name='Gravatar Email',
desc='We use <a href="https://en.gravatar.com/" target="_blank">Gravatar</a> to present your avatar icon.'),
desc='We will display a picture of that address as your avatar.'),
Setting('setting_info', 'qq', str,
name='QQ'),
Setting('setting_info', 'wechat', str,
Expand Down
10 changes: 8 additions & 2 deletions vj4/model/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
# Ranking.
PERM_VIEW_RANKING = 1 << 59

# User.
PERM_USER_SET_CHEAT = 1 << 60

PERM_ALL = -1

Permission = collections.namedtuple('Permission',
Expand Down Expand Up @@ -156,6 +159,7 @@
Permission('perm_training', PERM_EDIT_TRAINING, 'Edit training plans'),
Permission('perm_training', PERM_EDIT_TRAINING_SELF, 'Edit own training plans'),
Permission('perm_ranking', PERM_VIEW_RANKING, 'View ranking'),
Permission('perm_user', PERM_USER_SET_CHEAT, 'Set user as Cheater'),
]

PERMS_BY_FAMILY = collections.OrderedDict(
Expand Down Expand Up @@ -245,6 +249,8 @@
PERM_VIEW_RANKING
)
ADMIN_PERMISSIONS = PERM_ALL
TCA_PERMISSIONS = PERM_ALL ^ PERM_EDIT_PERM


# Roles.
ROLE_ROOT = 'root'
Expand Down Expand Up @@ -278,7 +284,7 @@
'roles': {ROLE_GUEST: BASIC_PERMISSIONS,
ROLE_DEFAULT: DEFAULT_PERMISSIONS,
ROLE_MEMBER: DEFAULT_PERMISSIONS,
ROLE_ADMIN: ADMIN_PERMISSIONS},
ROLE_ADMIN: TCA_PERMISSIONS},
'gravatar': '',
'name': 'AKIOI OJ',
'bulletin': BUILTIN_DOMAIN_BULLETIN
Expand Down Expand Up @@ -348,7 +354,7 @@
(1, 100)])

# Footer extra HTMLs.
FOOTER_EXTRA_HTMLS = [2023 <a href="https://oj.xzynb.top">oj.xzynb.top</a>', "Powered by <a href='https://github.com/Gingmzmzx/AKIOIOJ'>AKIOIOJ</a> and <a href='https://github.com/vijos/vj4'>Vijos</a>"]
FOOTER_EXTRA_HTMLS = [2024 <a href="https://oj.xzynb.top">oj.xzynb.top</a>', "Powered by <a href='https://github.com/Gingmzmzx/AKIOIOJ'>AKIOIOJ</a> and <a href='https://github.com/vijos/vj4'>Vijos</a>"]

PROBLEM_CATEGORIES = collections.OrderedDict([
('动态规划', [
Expand Down
12 changes: 11 additions & 1 deletion vj4/model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async def add(uid: int, uname: str, password: str, mail: str, regip: str=''):
'priv': builtin.DEFAULT_PRIV,
'loginat': datetime.datetime.utcnow(),
'loginip': regip,
'gravatar': mail})
'gravatar': "https://old.xzynb.top/pic/1ico.png"})
except errors.DuplicateKeyError:
raise error.UserAlreadyExistError(uid, uname, mail) from None

Expand Down Expand Up @@ -144,6 +144,16 @@ async def set_mail(uid: int, mail: str):
return await set_by_uid(uid, mail=mail, mail_lower=mail.strip().lower())


@argmethod.wrap
async def set_cheat(uid: int, status: bool):
"""Set the user as Cheater or remove its Cheater tag"""
coll = db.coll('user')
doc = await coll.find_one_and_update(filter={'_id': uid},
update={'$set': {"cheater": status}},
return_document=ReturnDocument.AFTER)
return doc


@argmethod.wrap
async def change_password(uid: int, current_password: str, password: str):
"""Change password. Returns doc or None."""
Expand Down
Empty file modified vj4/ui/.eslintrc.js
100755 → 100644
Empty file.
Empty file modified vj4/ui/Entry.js
100755 → 100644
Empty file.
Empty file modified vj4/ui/README.md
100755 → 100644
Empty file.
Empty file modified vj4/ui/breakpoints.json
100755 → 100644
Empty file.
1 change: 1 addition & 0 deletions vj4/ui/common/variables.inc.styl
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ $notification-icon = {
}

// Badge
$cheater = #996600
$badge-text-color = {
'mod': #FFF,
'lv0': #727171,
Expand Down
7 changes: 7 additions & 0 deletions vj4/ui/components/profile/profile.page.styl
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ for n in (1..21)
&:hover
text-decoration: none

.cheater_bg
background-color: $cheater
color: white

.cheater
color: $cheater

for key, _ in $badge-bg-color
.badge--{key}
background-color: $badge-bg-color[key] !important
Expand Down
9 changes: 8 additions & 1 deletion vj4/ui/constant/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ import attachObjectMeta from './util/objectMeta';
export const USER_GENDER_MALE = 0;
export const USER_GENDER_FEMALE = 1;
export const USER_GENDER_OTHER = 2;
export const USER_GENDERS = [USER_GENDER_MALE, USER_GENDER_FEMALE, USER_GENDER_OTHER];
export const USER_GENDER_WALLMARTBAG = 3;
export const USER_GENDER_ATTACKHELICOPTER = 4;

export const USER_GENDERS = [USER_GENDER_MALE, USER_GENDER_FEMALE, USER_GENDER_OTHER, USER_GENDER_WALLMARTBAG, USER_GENDER_ATTACKHELICOPTER];
export const USER_GENDER_RANGE = {
[USER_GENDER_MALE]: 'Boy ♂',
[USER_GENDER_FEMALE]: 'Girl ♀',
[USER_GENDER_OTHER]: 'Other',
[USER_GENDER_WALLMARTBAG]: 'Wallmart Bag',
[USER_GENDER_ATTACKHELICOPTER]: 'Attack Helicopter',
};
attachObjectMeta(USER_GENDER_RANGE, 'intKey', true);
export const USER_GENDER_ICONS = {
[USER_GENDER_MALE]: '♂',
[USER_GENDER_FEMALE]: '♀',
[USER_GENDER_OTHER]: '?',
[USER_GENDER_WALLMARTBAG]: '?',
[USER_GENDER_ATTACKHELICOPTER]: '?',
};
attachObjectMeta(USER_GENDER_ICONS, 'intKey', true);
Empty file modified vj4/ui/jsconfig.json
100755 → 100644
Empty file.
Empty file modified vj4/ui/postcss.config.js
100755 → 100644
Empty file.
4 changes: 2 additions & 2 deletions vj4/ui/templates/components/comments_discussion.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<li class="dczcomments__reply{% if mode_create %} commentbox-container{% endif %}">
<div class="media">
<div class="media__left top">
<img src="{{ udoc['gravatar']|gravatar_url }}" width="50" height="50" class="medium user-profile-avatar">
<img src="{{ udoc['gravatar']|default('https://old.xzynb.top/pic/1ico.png') }}" width="50" height="50" class="medium user-profile-avatar">
</div>
<div class="media__body top no-heading">
{% if not mode_create %}
Expand All @@ -30,7 +30,7 @@
<li class="dczcomments__item">
<div class="media">
<div class="media__left top">
<img src="{{ udoc['gravatar']|gravatar_url }}" width="60" height="60" class="medium user-profile-avatar">
<img src="{{ udoc['gravatar']|default('https://old.xzynb.top/pic/1ico.png') }}" width="60" height="60" class="medium user-profile-avatar">
</div>
<div class="media__body top no-heading">
{% if not mode_create %}
Expand Down
12 changes: 10 additions & 2 deletions vj4/ui/templates/components/user.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,28 @@
) %}
<span class="user-profile-link">
{% if avatar %}
<img class="small user-profile-avatar v-center" src="{{ udoc['gravatar']|default('')|gravatar_url }}" width="20" height="20">
<img class="small user-profile-avatar v-center" src="{% if udoc['gravatar'] %} {{ udoc['gravatar'] }} {% else %} {{ _('https://old.xzynb.top/pic/1ico.png') }} {% endif %}" width="20" height="20">
{% endif %}
<a class="user-profile-name" href="{{ reverse_url('user_detail', uid=udoc['_id']|default(0)) }}">
<a class="user-profile-name{% if udoc['cheater'] %} cheater {% endif %}" href="{{ reverse_url('user_detail', uid=udoc['_id']|default(0)) }}">
{% if dudoc['display_name'] %}
{{ dudoc['display_name'] }} ({{ udoc['uname'] }})
{% else %}
{{ udoc['uname'] }}
{% endif %}
</a>
{% if udoc['cheater'] %}
<a class="user-profile-badge v-center cheater_bg">{{ _('Cheater') }}</a>
{% endif %}
{% if badge %}
<a class="user-profile-badge v-center badge--lv{{ dudoc['level']|default(0) }}" href="{{ reverse_url('user_detail', uid=udoc['_id']|default(0)) }}" title="LV {{ dudoc['level']|default(0) }}: Top {{ vj4.model.builtin.LEVELS[dudoc['level']|default(0)]|default('N/A') }}%">LV {{ dudoc['level']|default(0) }}</a>
{% if modbadge and handler.dudoc_has_perm(udoc, dudoc, vj4.model.builtin.PERM_MOD_BADGE) %}
<span class="user-profile-badge v-center badge--mod" title="Moderator">MOD</span>
{% endif %}
{% if udoc['tags'] %}
{% for tag in udoc['tags'] %}
<span class="user-profile-badge v-center badge--mod" title="{{ tag }}">{{ tag }}</span>
{% endfor %}
{% endif %}
{% endif %}
</span>
{% endmacro %}
2 changes: 1 addition & 1 deletion vj4/ui/templates/discussion_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ <h1 class="section__title">{{ _('{0} comments').format(drcount) }}</h1>
<div class="section__body">
<div class="media sidebar-user-profile">
<div class="media__left">
<img src="{{ udoc['gravatar']|gravatar_url }}" width="80" height="80" class="medium user-profile-avatar">
<img src="{{ udoc['gravatar']|default('https://old.xzynb.top/pic/1ico.png') }}" width="80" height="80" class="medium user-profile-avatar">
</div>
<div class="media__body">
<p>
Expand Down
13 changes: 0 additions & 13 deletions vj4/ui/templates/domain_main.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,13 @@
{% extends "layout/basic.html" %}
{% import "components/contest.html" as contest with context %}
{% block content %}
{% if handler.domain['bulletin'] and domain_id != vj4.model.builtin.DOMAIN_ID_SYSTEM %}
<div class="row">
<div class="large-12 columns">
<div class="section">
<div class="section__body typo">
{{ handler.domain['bulletin']|markdown }}
</div>
</div>
</div>
</div>
{% endif %}
<div class="row">
<div class="large-9 columns">
{% if domain_id == vj4.model.builtin.DOMAIN_ID_SYSTEM %}
<div class="section">
<div class="section__body typo">
{{ handler.domain['bulletin']|markdown }}
</div>
</div>
{% endif %}
{% if not tdocs %}
<!-- no contest -->
{% else %}
Expand Down
2 changes: 1 addition & 1 deletion vj4/ui/templates/partials/nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<li class="nav__list-item"><a href="{{ reverse_url('user_register') }}" class="nav__item--round">{{ _('Sign Up') }}</a></li>
{% else %}
<li class="nav__list-item" data-dropdown-pos="bottom right" data-dropdown-target="#menu-nav-user" data-dropdown-trigger-desktop-only>
<a href="{{ reverse_url('user_detail', uid=handler.user['_id']) }}" class="nav__item">{{ handler.domain_user['display_name']|default(handler.user['uname'], true) }} <span class="icon icon-expand_more nojs--hide"></span></a>
<a href="{{ reverse_url('user_detail', uid=handler.user['_id']) }}" class="nav__item"><img class="small user-profile-avatar v-center" src="{% if handler.user['gravatar'] %} {{ handler.user['gravatar'] }} {% else %} {{ _('https://old.xzynb.top/pic/1ico.png') }} {% endif %}" width="20" height="20"> {{ handler.domain_user['display_name']|default(handler.user['uname'], true) }} <span class="icon icon-expand_more nojs--hide"></span></a>
<ol class="dropdown-target menu" id="menu-nav-user">
<li class="menu__item">
<a href="{{ reverse_url('user_detail', uid=handler.user['_id']) }}" class="menu__link">
Expand Down
32 changes: 26 additions & 6 deletions vj4/ui/templates/user_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@
</div>
<div class="media__body profile-header__main">
<h1>
{% if dudoc['display_name'] %}
{{ dudoc['display_name'] }}
<small>{{ udoc['uname'] }}</small>
{% else %}
{{ udoc['uname'] }}
{% endif %}
<span class="{% if udoc['cheater'] %} cheater {% endif %}">
{% if dudoc['display_name'] %}
{{ dudoc['display_name'] }}
<small>{{ udoc['uname'] }}</small>
{% else %}
{{ udoc['uname'] }}
{% endif %}
</span>
<small>({{ _('UID') }}: {{ udoc['_id'] }})</small>
{% if udoc['cheater'] %}
<small><a class="user-profile-badge v-center cheater_bg">{{ _('Cheater') }}</a></small>
{% endif %}
</h1>
<p>
{{ _('Registered at') }} {{ datetime_span(udoc['regat']) }},
Expand All @@ -39,6 +44,11 @@ <h1>
<a class="profile-header__contact-item" href="{{ reverse_url('home_messages') }}?target_uid={{ udoc['_id'] }}" target="_blank" data-tooltip="{{ _('Send Message') }}">
<span class="icon icon-comment--multiple"></span>
</a>
{% if set_cheat_perm %}
<a class="profile-header__contact-item" href="{{ reverse_url('user_set_cheat', uid=udoc['_id']) }}" data-tooltip="{{ _('Set user as Cheater') }}">
<span class="icon icon-block"></span>
</a>
{% endif %}
{% if handler.can_view(udoc, 'mail') and udoc['mail'] %}
<a class="profile-header__contact-item" href="javascript:;" name="profile_contact_copy" data-content="{{ udoc['mail'] | base64_encode }}" data-tooltip="{{ _('Copy Email') }}">
<span class="icon icon-mail"></span>
Expand Down Expand Up @@ -74,6 +84,16 @@ <h1>
MOD
</span>
{% endif %}
{% if udoc['tags'] %}
{% for tag in udoc['tags'] %}
<span
class="profile-header__contact-item user-profile-badge badge--mod"
data-tooltip="{{ tag }}"
>
{{ tag }}
</span>
{% endfor %}
{% endif %}
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion vj4/ui/templates/wiki_help.html
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ <h1 class="section__title" id="upload" data-heading>{{ _('Dataset Format') }}</h
<p>第一行包含一个整数n,表示总共有n组数据(即Input目录中文件总数等于Output目录中文件总数等于n);</p>
<p>接下来n行,第k行代表第k个测试点,格式为:<pre>[输入文件名]|[输出文件名]|[时限(单位为秒)]|[得分]|[内存限制(单位为KiB)]</pre><br>
其中,输入和输出文件名为 Input 或者 Output 目录中的文件名(不包含Input或者Output目录),且所有数据点得分之和必须为100,如:<br>
<pre>input0.txt|output0.txt|1|10|</pre></blockquote>
<pre>input0.txt|output0.txt|1|10|114514</pre></blockquote>
</div>
</div>
<div class="section" data-heading-extract-to="#menu-item-wiki_help">
Expand Down
Loading

0 comments on commit 5841d95

Please sign in to comment.