ویکیپدیا:انتخابات هیئت نظارت/پرسمان رأیمندان
اینجا نسخهای پشتیبان از الگوریتمی که برای فهرست کردن کاربران واجد شرایط رأیدادن به کار گرفته شده نگهداری میشود تا در سالهای بعد قابل دسترسی باشد.
پیشینه
ویرایشتا پیش از دورهٔ یازدهم، فهرست رأیمندان با کمک یک پرسمان از پایگاه داده قابل تهیه بود. برای دیدن پرسمان میتوانید به تاریخچهٔ همین صفحه مراجعه کنید.
از تاریخ ۳ ژوئن ۲۰۱۹ به این سو، به دلیل تغییراتی که در ساختار پایگاه دادهٔ ویکی در جریان است انجام پرسمانهای پیچیده زمان زیادی میبرد؛ از جمله، پرسمان مربوط به فهرست رأیمندان عملاً غیرقابل اجرا شد. لذا از این سال روال استخراج رأیمندان به دو مرحله شکسته شد. مرحلهٔ اول یک پرسمان است که فهرست کاربرانی که برخی از شرایط را دارا هستند استخراج میکند. مرحلهٔ دوم یک کد جاوااسکریپت است که با کمک خروجی مرحلهٔ اول، به بررسی باقی شرایط میپردازد. این کد را باید از طریق جاوااسکریپت کاربری به کار بست و خروجیاش در ویژه:صفحهٔ خالی قابل دیدن است.
پرسمان
ویرایشمرحلهٔ اول
ویرایشپرسمان زیر فهرستی از کاربرانی را تهیه میکند که شرطهای ۱ و ۳ از وپ:رگه را دارا هستند. شرط ۲ بعداً در مرحلهٔ دوم بررسی میشود.
در پرسمان زیر، تاریخها (که به صورت برچسب زمان آمدهاند) باید هر سال اصلاح شوند تا بازهٔ زمانی صحیح را منعکس کنند.
use fawiki_p;
select
user_id,
user_name
from user
join actor
on actor_user = user_id
join
(
select rev_actor
from revision_userindex
join page
on page_id = rev_page
where
page_namespace = 0
and rev_timestamp > '20221009000000' -- last 12 months leading to nomination start date
and rev_timestamp < '20231009000000'
group by rev_actor
having count(*) >= 100
) onehundred -- at least 100 edits in main namespace
on actor_id = onehundred.rev_actor
where
(
exists (
select 1
from logging_userindex
where log_actor = actor_id
and log_type = 'newusers'
and log_action in ('create', 'autocreate')
and log_timestamp < '20230709000000' -- occurred 3 or more months prior to nomination start date
)
or exists (
select 1
from revision_userindex
where rev_actor = actor_id
and rev_timestamp < '20230709000000' -- occurred 3 or more months prior to nomination start date
)
) and
not exists (
select 1
from user_groups
where ug_user = user_id
and ug_group = 'bot'
)
order by
user_id,
user_name
مرحلهٔ دوم
ویرایشکد جاوااسکریپت زیر باید اصلاح شود و مقدار متغیر users
به آرایهای تغییر یابد که عناصرش نامهای کاربریای هستند که از مرحلهٔ اول به دست آمدند. کد را میتوانید در ویژه:صفحه من/common.js قرار بدهید تا برای حساب شما اجرا شود. برای دیدن نتیجه باید به ویژه:صفحهٔ خالی بروید. توجه کنید که این کد صدها درخواست به سرور میفرستد در نتیجه بهتر است فقط وقتی که کاملاً ضرورت دارد از آن استفاده کنید (مثلاً اگر مجری انتخابات هستید، یا قرار است کار مجری را ارزیابی کنید).
(function($, mw) {
if (mw.config.get('wgCanonicalSpecialPageName') !== 'Blankpage') return;
mw.loader.using('mediawiki.api').then(function(){
var ucstart = '2020-10-12T00:00:00.000Z';
var ucend = '2019-10-12T00:00:00.000Z';
var threshold = 500;
var users = [
'Huji',
'ThisThat'
];
$('#mw-content-text').empty();
$('#mw-content-text').append($('<table>').addClass('wikitable'));
$('#mw-content-text table').append($('<tr>').append($('<th>').text('User')));
users.forEach(function(user){
var api = new mw.Api();
api.get({
action: 'query',
list: 'usercontribs',
ucuser: user,
ucnamespace: 0,
uclimit: threshold
}).done(function(data) {
if(data.query.usercontribs.length == threshold){
$('#mw-content-text table').append($('<tr>').append($('<td>').text(user)));
}
});
});
});
})(jQuery, mediaWiki);
کنترل نتایج
ویرایشبا کمک ابزاری که در https://huji.toolforge.org قرار داده شده، میتوان یک نام کاربری وارد کرد و واجد شرایط بودن آن کاربر برای رأی دادن را ارزیابی کرد. کد این ابزار در پایین آمدهاست و هر سال باید از نظر پرسمانهایی که به کار میبرد روزآمدسازی شود.
<!DOCTYPE html>
<?php
$username = '';
$error = '';
$ts_pw = posix_getpwuid(posix_getuid());
$ts_mycnf = parse_ini_file($ts_pw['dir'] . "/replica.my.cnf");
$nfi = new \NumberFormatter('fa-IR', \NumberFormatter::IGNORE);
$nfd = new \NumberFormatter('fa-IR', \NumberFormatter::DECIMAL);
if ( isset( $_POST['username'] ) ) {
$username = str_replace('"', '', $_POST['username']);
$prefix = '/^(User:|کاربر:)/';
$username = preg_replace($prefix, '', $username);
$username = ucfirst(trim($username));
$mysqli = new mysqli('fawiki.analytics.db.svc.eqiad.wmflabs', $ts_mycnf['user'], $ts_mycnf['password'], 'fawiki_p');
$q = $mysqli->prepare('SELECT actor_id, actor_name FROM actor WHERE actor_name=?');
$q->bind_param("s", $username);
$q->execute();
$q->bind_result($actor_id, $actor_name);
$q->fetch();
if($username === '') {
$error = 'No username provided';
}
elseif(!isset($actor_id)) {
$error = 'User does not exist!';
} else {
// Criterion 1
unset($q);
$q = $mysqli->prepare("SELECT MIN(log_timestamp) FROM logging_userindex WHERE log_type = 'newusers' AND log_action IN ('create', 'autocreate') AND log_actor=?");
$q->bind_param("i", $actor_id);
$q->execute();
$q->bind_result($mints);
$q->fetch();
if(!isset($mints)) {
// Try estimating account creation time using edits instead
unset($q);
$q = $mysqli->prepare('SELECT MIN(rev_timestamp) FROM revision_userindex WHERE rev_actor=?');
$q->bind_param("i", $actor_id);
$q->execute();
$q->bind_result($mints);
$q->fetch();
}
if(isset($mints) && strlen($mints) == 14){
$year = $nfi->format(substr($mints, 0, 4));
$month = $nfi->format(intval(substr($mints, 4, 2)));
$day = $nfi->format(intval(substr($mints, 6, 2)));
$mints = $year . '٫' . $month . '٫' . $day;
}
// Criterion 2
unset($q);
$q = $mysqli->prepare("SELECT COUNT(*) FROM revision_userindex JOIN page ON page_id = rev_page AND page_namespace = 0 WHERE rev_timestamp < 20201012000000 AND rev_actor=?");
$q->bind_param("i", $actor_id);
$q->execute();
$q->bind_result($edits);
$q->fetch();
$edits = $nfd->format($edits);
// Criterion 3
unset($q);
$q = $mysqli->prepare("SELECT COUNT(*) FROM revision_userindex JOIN page ON page_id = rev_page AND page_namespace = 0 WHERE rev_timestamp < 20201012000000 AND rev_timestamp > 20191012000000 AND rev_actor=?");
$q->bind_param("i", $actor_id);
$q->execute();
$q->bind_result($recentedits);
$q->fetch();
$recentedits = $nfd->format($recentedits);
}
}
?>
<html lang="fa">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
<meta content="" name="description">
<meta content="" name="author">
<link href="" rel="icon">
<title>Voter Eligibility Check</title>
<link href="https://cdn.rtlcss.com/bootstrap/v4.2.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body dir="rtl" style="direction:rtl">
<div id="wrapper">
<div id="page-content-wrapper">
<nav class="navbar navbar-expand-lg navbar-dark bg-secondary border-bottom">
<div class="container">
<a class="navbar-brand" href="./">ابزارهای حجت</a>
</div>
</nav>
<div class="container">
<h1 class="mt-4">ارزیابی شرایط رأیمندی</h1>
<p>این فرم به شما کمک میکند که وضعیت یک کاربر ویکیپدیای فارسی را از نظر برخورداری شرایط رأیمندی در <a href=
"https://fa.wikipedia.org/wiki/%D9%88%D9%BE:%D9%86%D8%A7%D8%B8%D8%B1%DB%B1%DB%B1">انتخابات دور یازدهم هیئت
نظارت</a> بررسی کنید.</p>
<p>شرایط لازم برای برخورداری از حق رأی (رأیمندی) در <a href=
"https://fa.wikipedia.org/wiki/%D9%88%D9%BE:%D8%B1%DA%AF%D9%87">اینجا</a> در دسترس هستند. این ابزار صرفاً برای
کمک به ارزیابی آن شرایط ساخته شدهاست و نباید به عنوان منبع اصلی تعریف شرایط رأیمندی در نظر گرفته شود. این
ابزار با راندن پرسمانهایی بر روی نسخهٔ کپی پایگاه دادهٔ ویکیمدیا (موسوم به Wikireplica Databases) اطلاعاتی را
که برای ارزیابی شرایط رأیمندی میتواند مفید باشد استخراج میکند. توجه کنید که هر پرسمان بین چند ثانیه تا چند
دقیقه طول میکشد و مدت آن برای کاربران قدیمیتر طولانیتر است.</p>
<form action="./" method="post">
<div class="form-group">
<label for="username">نام کاربری</label> <input aria-describedby="usernameHelp" class="form-control" id=
"username" name="username" placeholder="نام کاربری را وارد کنید" type="text" value=
"<?php echo $username; ?>"> <small class="form-text text-muted" id="usernameHelp">نیازی به پیشوند «کاربر:»
نیست.</small>
</div><button class="btn btn-primary" type="submit">ارسال</button>
</form>
<hr>
<?php if($error !== ''): ?>
<div class="card mb-12 bg-danger">
<div class="card-header text-white">
خطا
</div>
<div class="card-body bg-white">
<h5 class="card-title">درخواست شما شکست خورد</h5>
<div class="card-text">
<?php echo $error; ?>
</div>
</div>
</div><?php elseif(isset($mints)): ?>
<div class="card mb-12 bg-success">
<div class="card-header text-white">
نتایج
</div>
<div class="card-body bg-white">
<h5 class="card-title">ارزیابی شرایط رأیمندی</h5>
<div class="card-text">
<p>این اطلاعات برای حساب <bdi><?php echo $username; ?></bdi> به دست آمد:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>پرسمان</th>
<th>نتیجه</th>
<th>شرط لازم برای رأیمندان</th>
</tr>
</thead>
<tbody>
<tr>
<td>تاریخ ایجاد حساب</td>
<td><?php echo $mints; ?></td>
<td>پیش از ۲۰۲۰٫۷٫۱۲</td>
</tr>
<tr>
<td>ویرایش در مقالهها پیش از شروع انتخابات</td>
<td><?php echo $edits; ?></td>
<td>دست کم ۵۰۰</td>
</tr>
<tr>
<td>ویرایش در مقالهها در یک سال منتهی به انتخابات</td>
<td><?php echo $recentedits; ?></td>
<td>دست کم ۱۰۰</td>
</tr>
</tbody>
</table>
<p>برای دیدن سیاههٔ قطع دسترسی این کاربر <a href=
"https://fa.wikipedia.org/w/index.php?title=Special:Logs&page=User:%3C?php%20echo%20urlencode($username);%20?%3E&type=block">
اینجا</a> کلیک کنید.</p>
</div>
</div>
</div><?php endif; ?>
</div>
</div>
</div>
</body>
</html>
همچنین با کمک اسکریپتی مثل زیری میشود اطلاعات مربوط به رأیمندان را استخراج و در ویکی منتشر کرد:
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
voters.py - a script to fetch detailed data on fawiki election voters
"""
#
# (C) w:fa:User:Huji, 2020
#
# Distributed under the terms of the MIT license.
#
import MySQLdb
users = [
'User One',
'User Two'
]
getactor = "SELECT actor_id FROM actor WHERE actor_name = '%s'"
getcreation = """
SELECT MIN(log_timestamp)
FROM logging_userindex
WHERE
log_type = 'newusers'
AND log_action
IN (
'create',
'autocreate'
)
AND log_actor=%s
"""
getfirstedit = """
SELECT MIN(rev_timestamp)
FROM revision_userindex
WHERE rev_actor=%s
"""
getedits = """
SELECT COUNT(*)
FROM revision_userindex
JOIN page
ON page_id = rev_page
AND page_namespace = 0
WHERE
rev_timestamp < 20201012000000
AND rev_actor=%s
"""
getrecentedits = """
SELECT COUNT(*)
FROM revision_userindex
JOIN page
ON page_id = rev_page
AND page_namespace = 0
WHERE
rev_timestamp < 20201012000000
AND rev_timestamp > 20191012000000
AND rev_actor=%s
"""
conn = MySQLdb.connect(
host='fawiki.labsdb',
db='fawiki_p',
read_default_file='~/replica.my.cnf'
)
cursor = conn.cursor()
out = ''
for user in users:
print(' ', end='\r')
print('Processing %s' % user, end='\r')
sql = getactor % user
cursor.execute(sql.encode('utf-8'))
results = cursor.fetchall()
actor_id = results[0]
sql = getcreation % actor_id
cursor.execute(sql)
results = cursor.fetchall()
if results[0][0] is None:
sql = getfirstedit % actor_id
cursor.execute(sql)
results = cursor.fetchall()
mints = results[0][0].decode('utf-8')
mints = "%s-%s-%s" % (mints[0:4], mints[4:6], mints[6:8])
sql = getedits % actor_id
cursor.execute(sql)
results = cursor.fetchall()
edits = results[0][0]
sql = getrecentedits % actor_id
cursor.execute(sql)
results = cursor.fetchall()
recentedits = results[0][0]
out += '| [[User:%s|%s]] || %s || %s || %s\n|-\n' % (
user,
user,
mints,
edits,
recentedits
)
print(' ')
print(out)
سایر پرسمانها
ویرایشمطابق وپ:شعه، نامزدها باید دست کم ۱۰۰۰ ویرایش غیرجزئی در فضای نام اصلی داشته باشند. پرسمانی شبیه زیر را میتوان برای تأیید این مسئله استفاده کرد.
USE fawiki_p;
SELECT
actor_name,
COUNT(*)
FROM revision_userindex
JOIN page
ON rev_page = page_id
JOIN actor_revision
ON rev_actor = actor_id
WHERE
page_namespace = 0
AND rev_minor_edit = 0
AND rev_timestamp < '20201012000000'
AND actor_name IN (
'This User',
'That User'
)
GROUP BY rev_actor
ORDER BY COUNT(*)