InstaGov/SMW

About
Instead of having separate tables for questions and answers, each question or answer could be a wiki page with SMW data. No edit logging would be necessary, as that will be handled automatically by the wiki's edit-logging features.


 * Advantages:
 * easier to set up (no database mods needed)
 * no special software needed for basic functionality (especially if only trusted users have edit access)
 * ability to leverage SMW features for analysis and reporting.
 * Disadvantages:
 * doesn't come with a user-friendly interface; will probably need some coding or at least advanced SMW (semantic forms, perhaps?)
 * platform-dependent (need MW and SMW)
 * may be difficult to prevent voter fraud (nothing to stop one user from voting multiple times or editing votes of other users)
 * probably more CPU-intensive
 * If users want to keep votes on any page other than their main user page, some tweaking (and possibly coding) will be needed in order to show votes-by-user in a nice format.

Page Types
In each case, the remainder of the page (and the talk page) could be used for longer exposition and discussion that doesn't fit within the voting system's formal structure.

Questions
This corresponds to the table.
 * Summary would be a short summary of the given question, suitable for displaying in lists.
 * Details would be a longer explanation, possibly for printing in reports

See /questions for an archive of my notes when I was thinking about replacing only the question table with SMW.

Answers
This corresponds to the table.
 * Summary would be a short summary of the given answer, suitable for displaying in lists.
 * Details would be a longer explanation, possibly for printing in reports
 * Archival notes (extracted from page):
 * 2011-06-06 This table may end up not being used, since I've found I can use SMW to store answer data. Also, I'm thinking it should be "choice" rather than "answer", but since it's no longer hard-coded, this is just a matter of updating documentation (and one field name in the  table).

Ratings
This is the tricky part. We need to tie together three things: a user, an answer, and the user's rating for that answer. SMW also lets us tie together three things (a page, a property name, and a property value) -- but how do we reliably map one to the other?

A solution:
 * Any rating within a user's space means that the user has made that rating.
 * The property name is the answer's page name.
 * The property value is the user's rating (presumably -10 to +10 or similar).

The main issue here is that other users could edit a given user's vote. We will need to prevent or monitor this. We will also need to do something about out-of-range votes and invalid vote values.

Displaying Lists

 * answers:
 * this is only somewhat useful, as there is no way of formatting the results based on w3tpl content; more useful output will need coding
 * this is only somewhat useful, as there is no way of formatting the results based on w3tpl content; more useful output will need coding

Code
This code was originally in smw-base.php. /* 2012-08-13 This function was actually written for InstaGov, but appears to represent a significant amount of time-investment in figuring out how to access SMW data. I don't need it for IG anymore (for now) because I'm doing things differently there now, but it could well be useful for creating functions here in smw-base. /*- TAG: PARAMS: list=answers target=(name of page) name=(name of output array for each row) vpage=[name of var in which to store each page name] function efIGov( $input, $args, $parser ) { global $iggProperty_forResponses,$iggProperty_namespace;

$objArgs = new W3HookArgs($args);

if ($objArgs->Exists('list')) { if ($objArgs->Exists('name')) { $strNameRaw = $objArgs->GetArgVal('name'); $strName = trim($strNameRaw); $objVar = new clsW3VarName; $objVar->ParseName($strName);	// resolve any indirection (e.g. $var) } else { $out = '[must set output array name using name=]'; return; }	$dbr =& wfGetDB( DB_SLAVE );	// read-only db object

// this SQL (when finished) gets a list of pages with the SMW properties we're looking for $sqlSMW = 'SELECT s.smw_title AS s_t, s.smw_namespace AS s_ns, pg.page_id FROM (((smw_rels2 AS x  LEFT JOIN smw_ids AS s ON x.s_id=s.smw_id) LEFT JOIN smw_ids as p ON x.p_id=p.smw_id) LEFT JOIN smw_ids AS o ON x.o_id=o.smw_id) LEFT JOIN page AS pg ON ((s.smw_namespace=pg.page_namespace) AND (s.smw_title=pg.page_title)) WHERE (p.smw_title="'.$iggProperty_forResponses.'") AND (p.smw_namespace='.$iggProperty_namespace.') AND ';	$strType = $objArgs->GetVal('list'); $strTarg = $objArgs->GetVal('target'); $strPgVar = $objArgs->GetVal('vpage'); $doHide = isset($args['hide']);	// TRUE = only output sections $objTarg = Title::newFromText($strTarg); $sqlTarg = SQLValue($objTarg->getDBkey); $intNS = $objTarg->mNamespace; // is there not a function for this? switch($strType) { case 'answers': $sqlFiltAdd = '(o.smw_title='.$sqlTarg.') AND (o.smw_namespace='.$intNS.')'; break; default: $out = '[unknown list type]'; }	$sqlFull = $sqlSMW.$sqlFiltAdd; try { $res = $dbr->query($sqlFull); }	catch (Exception $e) { $out = "W3TPL encountered a database error - ".$dbr->lastError." - from this SQL: $sqlFull "; return $parser->recursiveTagParse($out); }	$fPerRow = function($iRow) use($parser,$strName,$dbr,$objVar,$strPgVar) { global $wgW3_data;

$idPage = $iRow->page_id;

$sqlMW = 'SELECT pp_propname, pp_value FROM page_props WHERE pp_page='; $sqlFull = $sqlMW.$idPage;

$out = NULL; try { $res = $dbr->query($sqlFull); }	   catch (Exception $e) { $out = "W3TPL encountered a database error - ".$dbr->lastError." - from this SQL: $sqlFull "; return $parser->recursiveTagParse($out); }	   $objPage = Title::newFromID($idPage); $objVar->Name = $strPgVar; $objVar->Value = $objPage->getPrefixedText; $objVar->Store; while( $row = $dbr->fetchObject ( $res ) ) { $strKey = $row->pp_propname; $txtVal = $row->pp_value; $objVar->Name = $strKey; $objVar->Value = $txtVal; $objVar->Store; }

return $out; };	$out = ProcessRows($dbr,$res,$strName,$parser,$input,$doHide,$fPerRow); } /* probably not using this after all if (isset($args['type'])) { $strType = $args['type']; switch($strType) { case 'question': $out = '[question is {'.$input.'}]'; break; case 'answer': $out = '[rnsr is {'.$input.'}]'; break; default: $out = '[unknown type]'; }	} else { $out = '[type not specified]'; }   return $out; }