User:JonnyJD/consistency check.js

From Wikidata
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
// based on importScript( 'User:Magnus Manske/consistency_check.js' );
//
// Use with:
// importScript( 'User:JonnyJD/consistency_check.js' );
// in https://www.wikidata.org/wiki/Special:MyPage/common.js
//
// changes:
// Added P197 (adjacent station) and lots of other properties
// added Dependency checking for properties (values are not checked though)
// several fixes to make it work again


 
var consistency_check = {

	p_prefix : 'P' ,
	q_prefix : 'Q' ,
	
	running : false ,
 
	reciproke : {
		'P47' : [ 'P47' ] , // shares border with
		'P26' : [ 'P26' ] , // spouse
		'P40' : [ 'P22', 'P25', 'P43', 'P44' ] , // child / mother, father, stepfather, stepmother
		'P22' : [ 'P40' ] , // father / child
		'P25' : [ 'P40' ],  // mother / child
		'P43' : [ 'P40' ],  // stepfather / child
		'P44' : [ 'P40' ],  // stepmother / child
		'P7'  : [ 'P9', 'P7' ], // brother
		'P9'  : [ 'P9', 'P7' ], // sister
		'P150': [ 'P131' ], // contains administr. subdivision
		'P155': [ 'P156' ], // preceded by
		'P156': [ 'P155' ], // succeeded by
		'P184': [ 'P185' ], // doctoral advisor
		'P185': [ 'P184' ], // doctoral student
		'P190': [ 'P190' ], // twin city
		'P197': [ 'P197' ], // adjacent station
		'P200': [ 'P201' ], // lake inflow
		'P201': [ 'P200' ], // lake outflow
		'P358': [ 'P175' ], // discography -> artist
		'P398': [ 'P397' ], // child of astronomical body
		'P399': [ 'P399' ], // companion of (astronomical)
		'P451': [ 'P451' ], // cohabitant
		'P460': [ 'P460' ], // supposed to be the same as
		'P461': [ 'P461' ], // opposite of
		'P629': [ 'P747' ], // edition of
		'P747': [ 'P629' ], // edition
	} ,
	
	dependencies : {
		'P7'   : [ 'P21', 'P31' ], // brother -> sex
		'P9'   : [ 'P21', 'P31' ], // sister -> sex
		'P22'  : [ 'P21', 'P31' ], // father -> sex
		'P25'  : [ 'P21', 'P31' ], // mother -> sex
		'P26'  : [ 'P21', 'P31' ], // spouse -> sex
		'P40'  : [ 'P21', 'P31' ], // child -> sex
		'P43'  : [ 'P21', 'P31' ], // stepfather -> sex
		'P44'  : [ 'P21', 'P31' ], // stepmother -> sex
		'P131' : [ 'P17', 'P31' ], // administrative unit -> country
		'P132' : [ 'P17' ], // type of administrative unit -> country
		'P150' : [ 'P17', 'P31', 'P132' ], // contains administr. division -> country, type of division
		'P190' : [ 'P31' ], // twin city -> instance of
		'P197' : [ 'P17', 'P31', 'P131', 'P625' ], // adjacent station
		'P399' : [ 'P31', 'P60' ] // companion (astronomical)
	},

	init : function () {
		var self = this ;
		
		/* this wouldn't always be right, ex. stepfather -> child, but not child -> stepfather
		$.each ( self.reciproke , function ( k , v ) {
			$.each ( v , function ( k2 , v2 ) {
				if ( undefined === self.reciproke[v2] ) self.reciproke[v2] = [] ;
				if ( -1 == $.inArray ( k , self.reciproke[v2] ) ) self.reciproke[v2].push ( k ) ;
			} ) ;
		} ) ;
		*/
		
//		console.log ( self.reciproke ) ;
		
		var portletLink = mw.util.addPortletLink( 'p-tb', '#', 'Consistency','t-consistency_check');
		$(portletLink).click ( function () {
			self.run() ;
			return false ;
		} ) ;
	} ,
	
	run : function () {
		var self = this ;
		if ( self.running ) return ;
		self.running = true ;
		var q = mw.config.get('wgPageName') ;
//		console.log("q: " + q);

		$.getJSON ( '//www.wikidata.org/w/api.php?callback=?' , {
			action : 'wbgetentities' ,
			ids : q ,
			format : 'json' ,
			props : 'claims'
		} , function ( data ) {

			var check = [] ;
			var html_out = '' ;
			var something_to_check = false ;
			var dependencies;
			
			if ( undefined !== data.entities[q].claims ) {
				html_out += "<div>";
				html_out += "<div style='float:left; padding-right:25px;'>";
				html_out += "<h2 class='wb-section-heading'>Symmetry</h2><table border=0>" ;
				$.each ( data.entities[q].claims , function ( k , v ) {
					if ( undefined !== self.reciproke[k] ) {
						$.each ( v , function ( k2 , v2 ) {
							if ( undefined === v2.mainsnak.datavalue ) return ; // No value
							var q2 = self.q_prefix + v2.mainsnak.datavalue.value['numeric-id'] ;
							var id = 'consistency_' + k + '_' + q2 ;
							html_out += "<tr><th class='label_"+k+"'>" + k + "</th><td id='" + id + "_c' style='text-align:center'>?</td><td id='" + id + "_v'><a href='/wiki/" + q2.toUpperCase() + "'>" + q2.toUpperCase() + "</a></td></tr>" ;
							check.push ( { prop:k , orig:q , target:q2 , any:self.reciproke[k] , id:id, q_prefix: self.q_prefix } ) ;
							something_to_check = true ;
						} ) ;
					}
				} ) ;
				html_out += "</table></div>" ;
				
				html_out += "<div style='float:left; padding-right:25px;'>";
				html_out += "<h2 class='wb-section-heading'>Dependencies</h2><table border=0>" ;
				$.each(data.entities[q].claims , function (k, v) {
					dependencies = true;
					if (undefined !== self.dependencies[k]) {
						something_to_check = true;
						html_out += "<tr><th class='label_" + k + "'>" + k + "</th><td>"
						$.each(self.dependencies[k], function(k2, v2) {
							if (!(v2 in data.entities[q].claims)) {
								if (dependencies) {
									dependencies = false;
									html_out += " <span style='color:red;'>missing:</span> "
								}
								html_out += v2 + " ";
							}		
						});
						if (dependencies) {
							html_out += " <span style='color:green;'>fine</span>"
						}
						html_out += "</td></tr>"
					}
				});
				html_out += "</table></div>";
				
				html_out += "</div>";
			}
			
			if (!something_to_check) {
				html_out = "<div>No consistency checks for the claims of " + q + ".</div>";
			}
			
			// open dialog for summary
			// partly taken from labelLister
			
			mw.loader.using( ['jquery.ui'], function () {
				var summary;
				var dialogWidth = Math.min(document.body.clientWidth - 200, 800);
				var dialogHeight = Math.min(document.body.clientHeight - 60, 650);
 
				if ( document.getElementById( "content" ) ) {
					summary = $(html_out).appendTo('#content');
				} else {
					summary = $(html_out).appendTo('#mw_content');
				}
				
				summary.dialog( {
					title: 'Consistency Check',
					autoOpen: true,
					modal: true,
					width: dialogWidth,
					height: dialogHeight,
					show: "blind",
					hide: "blind",
					buttons: []
				} );
			} );
						
			$.each ( check , function ( k , v ) {
				self.checkReciproke ( v ) ;
			} ) ;
			
			
		} ) ;
	
	} ,
	
	checkReciproke : function ( d ) {

		$.getJSON ( '//www.wikidata.org/w/api.php?callback=?' , {
			action : 'wbgetentities' ,
			ids : d.target ,
			format : 'json' ,
			props : 'claims'
		} , function ( data ) {
		
			var oneway = "<span style='color:red;font-weight:bold'>&rarr;</span>" ;
			var bothways = "<span style='color:green'>&harr;</span>"

			var found = false ;

			if ( undefined !== data.entities[d.target].claims ) {
				$.each ( data.entities[d.target].claims , function ( k , v ) {
					if ( -1 == $.inArray ( k , d.any ) ) return ;
					$.each ( v , function ( k2 , v2 ) {
						if ( undefined === v2.mainsnak.datavalue ) return ; // No value
						var q2 = d.q_prefix + v2.mainsnak.datavalue.value['numeric-id'] ;
						if ( q2 == d.orig ) found = true ;
						
					} ) ;
				} ) ;
			}
			
			if ( found ) {
				$('#'+d.id+'_c').html ( bothways ) ;
			} else {
				$('#'+d.id+'_c').html ( oneway ) ;
			}
			
		} ) ;
		
	} ,
	
	the_end : ''
} ;

$( function() {
	consistency_check.init () ;
});