أهلاً بكم، في الموسوعة القبطية الأرثوذكسية
الفرق بين المراجعتين لصفحة: «ميدياويكي:Gadget-page-authors-simple.js»
اذهب إلى التنقل
اذهب إلى البحث
ط |
(لا فرق)
|
المراجعة الحالية بتاريخ ٠٠:٢٥، ١٩ مارس ٢٠٢١
//[[fa:MediaWiki:Gadget-PageContributions.js]]
//[[no:MediaWiki:Gadget-page-authors-simple.js]]
(function(mw, $) {
var query = {
action: 'query',
prop: 'revisions',
titles: mw.config.get('wgPageName'),
rvlimit:10,
rvprop: 'ids|timestamp|user|size|content',
format: 'json'
};
var inProgress = false;
var isOpen = false;
var revisions = [];
var str = null;
var hidden = 0;
function toHex(n) {
if (n < 0) n = 0xFFFFFFFF + n + 1;
return n.toString(16);
};
function fnv(str) {
// this is an implementation of the Fowler-Noll-Vo hash algorithm
var hash = 2166136261; // the 32 bit offset
for (var i = 0, l = str.length; i < l; i++) {
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
hash = hash ^ str.charCodeAt(i);
}
return hash & 0x0ffffffff;
};
var perm = [ // permutations for the lsh algorithm
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172, 144,
176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54, 221,
102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185, 194,
193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232, 139,
6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196, 43,
249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231, 71,
230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47, 109,
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120, 209 ];
function lsh(str) {
// this is an implementation of a lsh algorithm, loosley similar to nilsimsa
var arr = Array();
for (var i = 0; i <= 0x0ff; i++) {
arr[i] = 0;
}
for (var i = 0, l = str.length-2; i < l; i++) {
// first we do a Pearson hash of trigram from the text
var hash = 0;
hash = perm[ (hash ^ str.charCodeAt(i)) & 0x0ff ];
hash = perm[ (hash ^ str.charCodeAt(i+1)) & 0x0ff ];
hash = perm[ (hash ^ str.charCodeAt(i+2)) & 0x0ff ];
// then we accumulate in the array at indices given by the hash
arr[hash]++;
}
// fold the array
for (var i = 0; i <= 0x01f; i++) {
arr[i] += arr[i+0x020] + arr[i+0x040] + arr[i+0x060] + arr[i+0x080] + arr[i+0x0a0] + arr[i+0x0c0] + arr[i+0x0e0];
}
var acc = 0;
var lim = arr.slice(0, 0x01f).sort(function(a,b){return a-b})[0x00f];
for (var i = 0; i <= 0x01f; i++) {
acc |= (((lim < arr[i]) ? 0 : 1) << i);
}
return acc & 0x0ffffffff;
};
function rvec(str) {
// this is an implementation of a subspace reduction algorithm based upon the Pearson hash
var arr = new Array();
for (var i = 0; i <= 0x0ff; i++) {
arr[i] = 0;
}
for (var i = 0, l = str.length-2; i < l; i++) {
// first we do a Pearson hash of trigram from the text
var hash = 0;
hash = perm[ (hash ^ str.charCodeAt(i)) & 0x0ff ];
hash = perm[ (hash ^ str.charCodeAt(i+1)) & 0x0ff ];
hash = perm[ (hash ^ str.charCodeAt(i+2)) & 0x0ff ];
// then we accumulate in the array at indices given by the hash
arr[hash]++;
}
return arr;
};
function beans(n) {
// implementation of a bean counter
// make an unsigned 32bits int
if (n < 0) n = 0xFFFFFFFF + n + 1;
// From Hacker's Delight, p. 66, Figure 5-2
n = n - ((n >> 1) & 0x55555555);
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
n = (n + (n >> 4)) & 0x0F0F0F0F;
n = n + (n >> 8);
n = n + (n >> 16);
return n & 0x0000003F;
};
function cosine(vec1, vec2) {
// really just a difference measure for the trigram vectors
var combined = Object();
for (var x in vec1)
combined[x] = vec1[x];
for (var x in vec2) {
if (combined[x] == null) combined[x] = 0;
combined[x] -= vec2[x];
}
var acc = 0;
for (var x in combined)
acc += combined[x] * combined[x];
return Math.sqrt(acc);
};
function rcos(vec1, vec2) {
// really just a difference measure for the trigram vectors
var acc = 0;
for (var i = 0; i <= 0x0ff; i++)
acc += Math.pow((vec1 ? vec1[i] : 0) - (vec2 ? vec2[i] : 0), 2);
return Math.sqrt(acc);
};
function onclick() {
// just an onclick handler to start processing
if (str === null) {
if (!inProgress) {
inProgress = true;
isOpen = true;
jsMsg('<h3>من ساهم في الصفحة</h3><small id="progress"></small>', 'page-authors' );
$('#mw-js-message.mw-js-message-page-authors h3').each(function(i, el) { injectSpinner( el, 'page-authors' ); });
getRevisions();
}
else {
alert('Already in progress!');
}
}
else {
if (!isOpen) {
isOpen = true;
jsMsg('<h3>من ساهم في الصفحة</h3>' + str, 'page-authors' );
$('#mw-js-message.mw-js-message-page-authors').show().find('ul').slideDown(1000);
}
else {
isOpen = false;
$('#mw-js-message.mw-js-message-page-authors').slideUp(1000);
}
}
return false;
};
function getRevisions() {
// ajax object
$.ajax({
url: mw.util.wikiScript( 'api' ),
dataType: 'json',
data: query,
context: document.body,
success: function(data, textStatus) {
if (textStatus != 'success') {
alert('Success, but with "' + textStatus + '"');
$('#mw-js-message.mw-js-message-page-authors').slideUp(1000);
}
var r = data['query'].pages[parseInt(mw.config.get('wgArticleId'))].revisions;
for (var x in r) {
if (typeof r[x]['*'] == 'undefined') {
hidden++;
continue;
}
r[x].lsh = lsh(r[x]['*']);
r[x].fnv = toHex(fnv(r[x]['*']));
if(r[x].size == 'undefined') r[x].size = r[x]['*'].length;
r[x].vec = rvec(r[x]['*']);
r[x]['*'] = null; // conserve space
revisions.push(r[x]);
}
if (data['query-continue']) {
$('#mw-js-message.mw-js-message-page-authors #progress').html( revisions.length + ' من المراجعات حملت…' );
query.rvstartid = data['query-continue'].revisions.rvstartid;
getRevisions();
}
else {
setResult();
}
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Error, but with "' + textStatus + '"');
$('#mw-js-message.mw-js-message-page-authors').slideUp(1000);
}
});
};
function setResult() {
// final handler after all ajax calls has completed
$('#mw-js-message.mw-js-message-page-authors #progress').html( 'جميع المراجعات حملت…' );
// variables
var digests = Object();
var users = Object();
var revids = Object();
// short form to get the revisions
var revs = revisions;
// get the individual revisions through a revid-key
for (var i = 0; i < revs.length; i++) revids[revs[i].revid] = revs[i];
// get the individual revisions through the fnv-digest
$('#mw-js-message.mw-js-message-page-authors #progress').html( 'Calculate FNV-digests…' );
var shunted = 0;
for (var i = revs.length-1; 0<=i; i--) {
if (digests[revs[i].fnv]) {
revs[i].previousid = digests[revs[i].fnv].revid;
shunted++;
}
digests[revs[i].fnv] = revs[i];
}
// cache the cosine measure and set previousid to reflect the span
$('#mw-js-message.mw-js-message-page-authors #progress').html( 'Calculate cosine measure…' );
var i = 0;
while (i<revs.length) {
var j = i;
if (revs[i].previousid) {
revs[i].cosine = rcos(revs[i].vec, revids[revs[i].previousid].vec);
var previousid = revs[i].previousid;
while (revs[i].revid > previousid && i<revs.length) i++;
}
else if (revs[i].parentid) {
revs[i].cosine = rcos(revs[i].vec, revids[revs[i].parentid].vec);
var parentid = revs[i].parentid;
while (revs[i].revid > parentid && i<revs.length) i++;
}
else if (i+1<revs.length) {
revs[i].cosine = rcos(revs[i].vec, revs[i+1].vec);
i++;
}
else if (i+1==revs.length) {
revs[i].cosine = rcos(revs[i].vec);
revs[j].previousid = 0;
break;
}
if (i != j) revs[j].previousid = revs[i].revid;
}
// adjust the cosine measure if lsh is to far off
$('#mw-js-message.mw-js-message-page-authors #progress').html( 'Adjust cosine measure…' );
var similar = 0;
var revision = revs[0];
while (revision) {
var previous = revids[revision.previousid];
if (previous /* && revision.size > 100 */ && 64<revision.cosine) {
var p=previous;
var lsh=2147483647;
var keep = null;
for (var j = 0; j < 16; j++) {
if (p) {
var tmp = rcos(revision.vec, p.vec);
if (lsh > tmp) {
lsh = tmp;
keep = p;
}
p = revids[p.previousid];
}
else {
break;
}
}
if (keep && keep != previous) {
previous = keep;
similar++;
}
}
if (previous) {
revision.previousid = previous.revid;
revision.cosine = rcos(revision.vec, previous.vec);
}
revision = previous;
}
// accumulate the cosine measure for each user
$('#mw-js-message.mw-js-message-page-authors #progress').html( 'Accumulate cosine measure…' );
var revision = revs[0];
var num = 0;
while (revision) {
if (!users[revision.user]) users[revision.user] = { cosine: 0 };
users[revision.user].cosine += revision.cosine;
revision = revids[revision.previousid];
num++;
}
// accumulate the total cosine measure
var acc = { cosine: 0 };
for (var x in users) acc.cosine += users[x].cosine;
// sort out the main contributors
$('#mw-js-message.mw-js-message-page-authors #progress').html( 'Sort out main contributors…' );
var authors = Array();
var pseudonyms = Array();
var count = 0;
for (var x in users) pseudonyms.push(x);
for (var x in pseudonyms.sort(function(a, b){ return users[b].cosine - users[a].cosine })) {
var name = pseudonyms[x];
var cosine = Math.round(100*users[name].cosine/acc.cosine);
if (count++ < 5 && 0 < cosine) authors.push(name);
else if (5 <= cosine ) authors.push(name);
else if (revs[revs.length-1].user == name) authors.push(name);
}
// print the cosine measure for each user
$('#mw-js-message.mw-js-message-page-authors #progress').html( 'Create presentation…' );
str = '<p>هذه قائمة بأسماء الذين ساهموا في كتابة هذه الصفحة والنسبة المئوية لمساهمة كل منهم. ';
str += 'أخذ بالحسبان ' + num + ' مما مجموعه ' + revisions.length + ' من المراجعات. ';
if (0<hidden)
str += 'منها ' + hidden + ' من المراجعات المخفية. ';
if (0<shunted || 0<similar)
str += 'منها ' + shunted + ' من المراجعات غير المؤثرة، و' + similar + ' من المراجعات المشابهة لنسخ سابقة من الصفحة. ';
else
str += 'أخذت جميع المراجعات بالحسبان. ';
str += '<ul style="display:none">';
var part = 0;
for (var x in authors) {
var name = authors[x];
part += users[name].cosine;
str += '<li>';
str += '<a href="' + mw.util.getUrl('User:' + name) + '">' + name + '</a>';
str += ' (';
str += '<a href="' + mw.util.getUrl('User_talk:' + name) + '">نقاش</a>';
str += ' | ';
str += '<a href="' + mw.util.getUrl('Special:Contributions/' + name) + '">مساهمات</a>';
str += ') ';
// str += ' <em>';
str += 'بنسبة ' + String((0.1<users[name].cosine/acc.cosine ? Math.round(100*users[name].cosine/acc.cosine) : Math.round(1000*users[name].cosine/acc.cosine)/10)).replace(/\./, ',') + ' %' + ' من المساهمات';
if (revs[revs.length-1].user == name) str += '، <b>وأول المساهمين</b>';
// str += '.</em>';
str += '</li>';
}
str += '<li>بقية المساهمات بنسبة ' + String(Math.round(100*(acc.cosine-part)/acc.cosine)).replace(/\./, ',') + ' % من الصفحة.</li>';
str += '</ul>';
str += '<p><small>الحساب قد يكون غير مضبوط. انظر <a href="/wiki/مساعدة:مساهمات المستخدم">صفحة المساعدة</a> للمزيد.</small></p>';
$('#mw-js-message.mw-js-message-page-authors #progress').remove();
$('#mw-js-message.mw-js-message-page-authors h3').each(function(i, el) { removeSpinner( 'page-authors' ); });
$('#mw-js-message.mw-js-message-page-authors').append(str);
$('#mw-js-message.mw-js-message-page-authors ul').slideDown(1000);
inProgress = false;
};
// the strange test (2147483647 <= -1 >>> 1) is to verify that we have at least 32 bit ints
// note that 32 bit ints are according to standard, while it can be longer but not shorter to respect the standard
var nsnum = parseInt(mw.config.get('wgNamespaceNumber'));
if (0 <= nsnum && 0 == nsnum%2 && mw.config.get('wgIsArticle') && (2147483647 <= -1 >>> 1)) {
$( function() {
mw.util.addPortletLink(
"p-cactions",
'#',
"مساهمات الصفحة",
"t-article-authors",
"حساب من كتب في هذه الصفحة ونسب المساهمة",
null,
null
);
$('#t-article-authors').click(onclick);
});
}
})(mediaWiki, jQuery);