parent
0cc6728257
commit
5bf8e3fded
@ -0,0 +1,394 @@ |
|||||||
|
<?php if (!defined('PmWiki')) exit(); |
||||||
|
/* |
||||||
|
inspired by PageFeed by Daniel Roesler (diafygi) |
||||||
|
conversation array imported from it |
||||||
|
*/ |
||||||
|
|
||||||
|
## Recipe version information |
||||||
|
$RecipeInfo['BehaviorRecall']['Version'] = '2011-01-02'; |
||||||
|
|
||||||
|
## Add action for pagefeed |
||||||
|
SDV($HandleActions['recall'], 'BehaviorRecall'); |
||||||
|
|
||||||
|
function addDate_BehaviorRecall($date,$day)//add days |
||||||
|
{ |
||||||
|
$sum = strtotime(date("Y-m-d", strtotime("$date")) . " +$day days"); |
||||||
|
$dateTo=date('Y-m-d',$sum); |
||||||
|
return $dateTo; |
||||||
|
} |
||||||
|
function convertDate_BehaviorRecall($date) { |
||||||
|
return preg_replace("/(\d+)\/(\d+)\/(\d+)/",'$3-$2-$1',$date); |
||||||
|
} |
||||||
|
|
||||||
|
## Create feed from page history |
||||||
|
function BehaviorRecall($pagename, $auth = 'read') { |
||||||
|
global $FarmD, $WikiTitle, $ScriptUrl; |
||||||
|
$feedfile = $FarmD."/pub/recallfeed.xml"; #change to a pattern when support arguments |
||||||
|
|
||||||
|
// PATTERNS |
||||||
|
// TODO |
||||||
|
// * transform to math functions |
||||||
|
// * add some randomness |
||||||
|
// * add a bunded random recall |
||||||
|
$exponential_pattern = array(1,10,30,60,120,350,700,1500,3000,7000,15000,30000,100000); //exp |
||||||
|
// $datestorecall = array(1,10,30,60..,61,62..,80..); |
||||||
|
$monthly_pattern = array(1,30,60,90,120,150,180,210,240,270,300); //mod30 |
||||||
|
$weekly_pattern = array(1,7,14,21,28,35,43,50,57,64,71,78,85,93,100,101,107,114,121,128,135,143,150,157,164,171,178,185,193,100); //mod7 |
||||||
|
$daily_pattern = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30); //mod1 |
||||||
|
$datestorecall = $exponential_pattern; |
||||||
|
$varname='recall'; |
||||||
|
|
||||||
|
$pages = ListPages(); |
||||||
|
# open $feed as read |
||||||
|
if (!file_exists($feedfile)) |
||||||
|
if (!touch($feedfile)) |
||||||
|
print "Creation of the feed file fails, check write permissions for pmWiki and $feedfile."; |
||||||
|
|
||||||
|
$feed_oldcontent = file_get_contents($feedfile); |
||||||
|
|
||||||
|
$feed_newcontent = ''; |
||||||
|
|
||||||
|
# 2 loops can be probably optimized since they are ordered by date |
||||||
|
foreach ($pages as $page) { |
||||||
|
$recall = PageTextVar($page,$varname); |
||||||
|
if ( isset($recall) ) { |
||||||
|
$params = explode(" ",$recall); |
||||||
|
$patternrecall = $params[1]; |
||||||
|
$daterecall = $params[0]; |
||||||
|
switch($patternrecall){ |
||||||
|
case "daily": $datestorecall = $daily_pattern; break; |
||||||
|
case "weekly": $datestorecall = $weekly_pattern; break; |
||||||
|
case "monthly": $datestorecall = $monthly_pattern; break; |
||||||
|
case "exponentially": $datestorecall = $exponential_pattern; break; |
||||||
|
} |
||||||
|
foreach ($datestorecall as $day) { |
||||||
|
# print $page . " "; |
||||||
|
$checkdate = addDate_BehaviorRecall(convertDate_BehaviorRecall($daterecall),$day); |
||||||
|
# print $daterecall . " + " . $day . " (" . $checkdate . ") == " . date("d/m/Y"); |
||||||
|
if ($checkdate==convertDate_BehaviorRecall(date("d/m/Y"))) |
||||||
|
{ |
||||||
|
# print " recall time"; |
||||||
|
# generate GUID |
||||||
|
$item_GUID = $page.'_'.$checkdate; |
||||||
|
# if not present in file using a regex on the GUID |
||||||
|
if (preg_match("/$item_GUID/",$feed_oldcontent) == 0) |
||||||
|
{ |
||||||
|
|
||||||
|
# generate date |
||||||
|
$feed_newitemdate = date(DATE_RSS, time()); |
||||||
|
# transform line to XML format |
||||||
|
$cleaned_page_name = str_replace(".","/",$page); |
||||||
|
global $FmtV; |
||||||
|
$pagecontent = FmtPageName($FmtV, $page); |
||||||
|
$feed_newitem = " <item> |
||||||
|
<title>Day $day recall for page $page started at $daterecall</title> |
||||||
|
<link>$ScriptUrl/$cleaned_page_name#BehaviorRecallDay$day</link> |
||||||
|
<description>This is to improve behaviors you decided yourself were valuable. Also don't forget to improve those instructions to be more and more efficient!$pagecontent</description> |
||||||
|
<guid>$item_GUID</guid> |
||||||
|
<pubDate>$feed_newitemdate</pubDate> |
||||||
|
</item>"; |
||||||
|
# appending the item |
||||||
|
$feed_newcontent .= $feed_newitem; |
||||||
|
} |
||||||
|
break; #we can't have 2 days at the same time |
||||||
|
} |
||||||
|
# print "<br/>"; |
||||||
|
} # check if the next recall day is today |
||||||
|
} # check if the next page is tagged |
||||||
|
} |
||||||
|
# feed should be properly updated |
||||||
|
|
||||||
|
$feed_newdate = date(DATE_RSS, time()); |
||||||
|
|
||||||
|
$feed_header = "<?xml version=\"1.0\"?>
|
||||||
|
<rss version=\"2.0\"> |
||||||
|
<channel> |
||||||
|
<title>BehaviorRecall feed for $WikiTitle .</title> |
||||||
|
<link>$ScriptUrl</link> |
||||||
|
<description>Receive links as reminded to periodic behaviors you want to transform to habits.</description> |
||||||
|
<lastBuildDate>$feed_newdate</lastBuildDate>"; |
||||||
|
|
||||||
|
$feed_footer = " |
||||||
|
</channel> |
||||||
|
</rss>"; |
||||||
|
|
||||||
|
|
||||||
|
# print header |
||||||
|
print $feed_header; |
||||||
|
|
||||||
|
# print items |
||||||
|
print $feed_oldcontent; |
||||||
|
# $feed_newcontent = str_replace(array_keys($EntitiesTable), array_values($EntitiesTable), $feed_newcontent); |
||||||
|
print $feed_newcontent; |
||||||
|
|
||||||
|
# print footer |
||||||
|
print $feed_footer; |
||||||
|
|
||||||
|
$write_result = file_put_contents($feedfile,$feed_oldcontent.$feed_newcontent); |
||||||
|
if (!$write_result) |
||||||
|
if (strlen($feed_oldcontent.$feed_newcontent)>0) |
||||||
|
print "Creation of the feed file fails, check write permissions for pmWiki and $feedfile."; |
||||||
|
else |
||||||
|
print "No item to generate, did you correctly tag your pages?"; |
||||||
|
} |
||||||
|
|
||||||
|
## Since most feeds don't understand html character entities, we |
||||||
|
## convert the common ones to their numeric form here. |
||||||
|
## Taken from /scripts/feeds.php |
||||||
|
SDVA($EntitiesTable, array( |
||||||
|
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent" |
||||||
|
' ' => ' ', |
||||||
|
'¡' => '¡', |
||||||
|
'¢' => '¢', |
||||||
|
'£' => '£', |
||||||
|
'¤' => '¤', |
||||||
|
'¥' => '¥', |
||||||
|
'¦' => '¦', |
||||||
|
'§' => '§', |
||||||
|
'¨' => '¨', |
||||||
|
'©' => '©', |
||||||
|
'ª' => 'ª', |
||||||
|
'«' => '«', |
||||||
|
'¬' => '¬', |
||||||
|
'­' => '­', |
||||||
|
'®' => '®', |
||||||
|
'¯' => '¯', |
||||||
|
'°' => '°', |
||||||
|
'±' => '±', |
||||||
|
'²' => '²', |
||||||
|
'³' => '³', |
||||||
|
'´' => '´', |
||||||
|
'µ' => 'µ', |
||||||
|
'¶' => '¶', |
||||||
|
'·' => '·', |
||||||
|
'¸' => '¸', |
||||||
|
'¹' => '¹', |
||||||
|
'º' => 'º', |
||||||
|
'»' => '»', |
||||||
|
'¼' => '¼', |
||||||
|
'½' => '½', |
||||||
|
'¾' => '¾', |
||||||
|
'¿' => '¿', |
||||||
|
'À' => 'À', |
||||||
|
'Á' => 'Á', |
||||||
|
'Â' => 'Â', |
||||||
|
'Ã' => 'Ã', |
||||||
|
'Ä' => 'Ä', |
||||||
|
'Å' => 'Å', |
||||||
|
'Æ' => 'Æ', |
||||||
|
'Ç' => 'Ç', |
||||||
|
'È' => 'È', |
||||||
|
'É' => 'É', |
||||||
|
'Ê' => 'Ê', |
||||||
|
'Ë' => 'Ë', |
||||||
|
'Ì' => 'Ì', |
||||||
|
'Í' => 'Í', |
||||||
|
'Î' => 'Î', |
||||||
|
'Ï' => 'Ï', |
||||||
|
'Ð' => 'Ð', |
||||||
|
'Ñ' => 'Ñ', |
||||||
|
'Ò' => 'Ò', |
||||||
|
'Ó' => 'Ó', |
||||||
|
'Ô' => 'Ô', |
||||||
|
'Õ' => 'Õ', |
||||||
|
'Ö' => 'Ö', |
||||||
|
'×' => '×', |
||||||
|
'Ø' => 'Ø', |
||||||
|
'Ù' => 'Ù', |
||||||
|
'Ú' => 'Ú', |
||||||
|
'Û' => 'Û', |
||||||
|
'Ü' => 'Ü', |
||||||
|
'Ý' => 'Ý', |
||||||
|
'Þ' => 'Þ', |
||||||
|
'ß' => 'ß', |
||||||
|
'à' => 'à', |
||||||
|
'á' => 'á', |
||||||
|
'â' => 'â', |
||||||
|
'ã' => 'ã', |
||||||
|
'ä' => 'ä', |
||||||
|
'å' => 'å', |
||||||
|
'æ' => 'æ', |
||||||
|
'ç' => 'ç', |
||||||
|
'è' => 'è', |
||||||
|
'é' => 'é', |
||||||
|
'ê' => 'ê', |
||||||
|
'ë' => 'ë', |
||||||
|
'ì' => 'ì', |
||||||
|
'í' => 'í', |
||||||
|
'î' => 'î', |
||||||
|
'ï' => 'ï', |
||||||
|
'ð' => 'ð', |
||||||
|
'ñ' => 'ñ', |
||||||
|
'ò' => 'ò', |
||||||
|
'ó' => 'ó', |
||||||
|
'ô' => 'ô', |
||||||
|
'õ' => 'õ', |
||||||
|
'ö' => 'ö', |
||||||
|
'÷' => '÷', |
||||||
|
'ø' => 'ø', |
||||||
|
'ù' => 'ù', |
||||||
|
'ú' => 'ú', |
||||||
|
'û' => 'û', |
||||||
|
'ü' => 'ü', |
||||||
|
'ý' => 'ý', |
||||||
|
'þ' => 'þ', |
||||||
|
'ÿ' => 'ÿ', |
||||||
|
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent" |
||||||
|
'"' => '"', |
||||||
|
#'&' => '&#38;', |
||||||
|
#'<' => '&#60;', |
||||||
|
#'>' => '>', |
||||||
|
''' => ''', |
||||||
|
'Œ' => 'Œ', |
||||||
|
'œ' => 'œ', |
||||||
|
'Š' => 'Š', |
||||||
|
'š' => 'š', |
||||||
|
'Ÿ' => 'Ÿ', |
||||||
|
'ˆ' => 'ˆ', |
||||||
|
'˜' => '˜', |
||||||
|
' ' => ' ', |
||||||
|
' ' => ' ', |
||||||
|
' ' => ' ', |
||||||
|
'‌' => '‌', |
||||||
|
'‍' => '‍', |
||||||
|
'‎' => '‎', |
||||||
|
'‏' => '‏', |
||||||
|
'–' => '–', |
||||||
|
'—' => '—', |
||||||
|
'‘' => '‘', |
||||||
|
'’' => '’', |
||||||
|
'‚' => '‚', |
||||||
|
'“' => '“', |
||||||
|
'”' => '”', |
||||||
|
'„' => '„', |
||||||
|
'†' => '†', |
||||||
|
'‡' => '‡', |
||||||
|
'‰' => '‰', |
||||||
|
'‹' => '‹', |
||||||
|
'›' => '›', |
||||||
|
'€' => '€', |
||||||
|
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent" |
||||||
|
'ƒ' => 'ƒ', |
||||||
|
'Α' => 'Α', |
||||||
|
'Β' => 'Β', |
||||||
|
'Γ' => 'Γ', |
||||||
|
'Δ' => 'Δ', |
||||||
|
'Ε' => 'Ε', |
||||||
|
'Ζ' => 'Ζ', |
||||||
|
'Η' => 'Η', |
||||||
|
'Θ' => 'Θ', |
||||||
|
'Ι' => 'Ι', |
||||||
|
'Κ' => 'Κ', |
||||||
|
'Λ' => 'Λ', |
||||||
|
'Μ' => 'Μ', |
||||||
|
'Ν' => 'Ν', |
||||||
|
'Ξ' => 'Ξ', |
||||||
|
'Ο' => 'Ο', |
||||||
|
'Π' => 'Π', |
||||||
|
'Ρ' => 'Ρ', |
||||||
|
'Σ' => 'Σ', |
||||||
|
'Τ' => 'Τ', |
||||||
|
'Υ' => 'Υ', |
||||||
|
'Φ' => 'Φ', |
||||||
|
'Χ' => 'Χ', |
||||||
|
'Ψ' => 'Ψ', |
||||||
|
'Ω' => 'Ω', |
||||||
|
'α' => 'α', |
||||||
|
'β' => 'β', |
||||||
|
'γ' => 'γ', |
||||||
|
'δ' => 'δ', |
||||||
|
'ε' => 'ε', |
||||||
|
'ζ' => 'ζ', |
||||||
|
'η' => 'η', |
||||||
|
'θ' => 'θ', |
||||||
|
'ι' => 'ι', |
||||||
|
'κ' => 'κ', |
||||||
|
'λ' => 'λ', |
||||||
|
'μ' => 'μ', |
||||||
|
'ν' => 'ν', |
||||||
|
'ξ' => 'ξ', |
||||||
|
'ο' => 'ο', |
||||||
|
'π' => 'π', |
||||||
|
'ρ' => 'ρ', |
||||||
|
'ς' => 'ς', |
||||||
|
'σ' => 'σ', |
||||||
|
'τ' => 'τ', |
||||||
|
'υ' => 'υ', |
||||||
|
'φ' => 'φ', |
||||||
|
'χ' => 'χ', |
||||||
|
'ψ' => 'ψ', |
||||||
|
'ω' => 'ω', |
||||||
|
'ϑ' => 'ϑ', |
||||||
|
'ϒ' => 'ϒ', |
||||||
|
'ϖ' => 'ϖ', |
||||||
|
'•' => '•', |
||||||
|
'…' => '…', |
||||||
|
'′' => '′', |
||||||
|
'″' => '″', |
||||||
|
'‾' => '‾', |
||||||
|
'⁄' => '⁄', |
||||||
|
'℘' => '℘', |
||||||
|
'ℑ' => 'ℑ', |
||||||
|
'ℜ' => 'ℜ', |
||||||
|
'™' => '™', |
||||||
|
'ℵ' => 'ℵ', |
||||||
|
'←' => '←', |
||||||
|
'↑' => '↑', |
||||||
|
'→' => '→', |
||||||
|
'↓' => '↓', |
||||||
|
'↔' => '↔', |
||||||
|
'↵' => '↵', |
||||||
|
'⇐' => '⇐', |
||||||
|
'⇑' => '⇑', |
||||||
|
'⇒' => '⇒', |
||||||
|
'⇓' => '⇓', |
||||||
|
'⇔' => '⇔', |
||||||
|
'∀' => '∀', |
||||||
|
'∂' => '∂', |
||||||
|
'∃' => '∃', |
||||||
|
'∅' => '∅', |
||||||
|
'∇' => '∇', |
||||||
|
'∈' => '∈', |
||||||
|
'∉' => '∉', |
||||||
|
'∋' => '∋', |
||||||
|
'∏' => '∏', |
||||||
|
'∑' => '∑', |
||||||
|
'−' => '−', |
||||||
|
'∗' => '∗', |
||||||
|
'√' => '√', |
||||||
|
'∝' => '∝', |
||||||
|
'∞' => '∞', |
||||||
|
'∠' => '∠', |
||||||
|
'∧' => '∧', |
||||||
|
'∨' => '∨', |
||||||
|
'∩' => '∩', |
||||||
|
'∪' => '∪', |
||||||
|
'∫' => '∫', |
||||||
|
'∴' => '∴', |
||||||
|
'∼' => '∼', |
||||||
|
'≅' => '≅', |
||||||
|
'≈' => '≈', |
||||||
|
'≠' => '≠', |
||||||
|
'≡' => '≡', |
||||||
|
'≤' => '≤', |
||||||
|
'≥' => '≥', |
||||||
|
'⊂' => '⊂', |
||||||
|
'⊃' => '⊃', |
||||||
|
'⊄' => '⊄', |
||||||
|
'⊆' => '⊆', |
||||||
|
'⊇' => '⊇', |
||||||
|
'⊕' => '⊕', |
||||||
|
'⊗' => '⊗', |
||||||
|
'⊥' => '⊥', |
||||||
|
'⋅' => '⋅', |
||||||
|
'⌈' => '⌈', |
||||||
|
'⌉' => '⌉', |
||||||
|
'⌊' => '⌊', |
||||||
|
'⌋' => '⌋', |
||||||
|
'⟨' => '〈', |
||||||
|
'⟩' => '〉', |
||||||
|
'◊' => '◊', |
||||||
|
'♠' => '♠', |
||||||
|
'♣' => '♣', |
||||||
|
'♥' => '♥', |
||||||
|
'♦' => '♦')); |
@ -0,0 +1,75 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
# return coeditions for a wholewiki |
||||||
|
|
||||||
|
function Coeditions($groupname){ |
||||||
|
|
||||||
|
global $ScriptUrl, $PubDir, $FarmD; |
||||||
|
$cache_time = 0; # set to 0 to disable cache, practical for testing |
||||||
|
$cache_time = 3600; |
||||||
|
$cachefile = "/pub/coedits.txt"; |
||||||
|
$timewindow = 360; # in seconds |
||||||
|
$pagelist = ListPages("/$groupname\./e"); |
||||||
|
// consider removing structural pages (headers, PmWiki, Site, ...) |
||||||
|
// mostly case by default since those remains into wikilib.d unless modified |
||||||
|
|
||||||
|
//unset($pagelist[array_search("$groupname.Template",$pagelist)]); |
||||||
|
|
||||||
|
# cache since its costly |
||||||
|
if (!file_exists($FarmD.$cachefile)){ |
||||||
|
if (!touch($FarmD.$cachefile)) |
||||||
|
print "Creation of the cache file fails, check write permissions for pmWiki and $cachefile."; |
||||||
|
# if cache exist |
||||||
|
} else { |
||||||
|
# cache has been generated recently |
||||||
|
if (( (time() - filemtime($FarmD.$cachefile)) < $cache_time ) && $groupname == "") |
||||||
|
#return it |
||||||
|
return unserialize(file_get_contents($FarmD.$cachefile)); |
||||||
|
} |
||||||
|
|
||||||
|
foreach ($pagelist as $pagename){ |
||||||
|
$page = ReadPage($pagename); |
||||||
|
if (!$page) return; |
||||||
|
krsort($page); reset($page); |
||||||
|
|
||||||
|
foreach($page as $k=>$v) { |
||||||
|
if (!preg_match("/^diff:(\d+):(\d+):?([^:]*)/",$k,$match)) continue; |
||||||
|
$diff = intval($match[1]); |
||||||
|
$edits[] = array ("diff" => $diff, "name" => $pagename); |
||||||
|
$diffs[] = $diff; |
||||||
|
$names[] = $pagename; |
||||||
|
#automatic index since there might multiple edits with the same diff |
||||||
|
} |
||||||
|
} |
||||||
|
# numeric sort $edits by ascending diff (either regenerate or discard index) |
||||||
|
array_multisort($diffs,SORT_ASC,SORT_NUMERIC,$names); |
||||||
|
//var_dump($diffs,$names); |
||||||
|
$numberofedits = count($diffs); |
||||||
|
for ($j=0;$j<$numberofedits;$j++){ |
||||||
|
if (($diffs[$j+1]-$diffs[$j])<$timewindow){ |
||||||
|
$target = $names[$j]; |
||||||
|
$dest = $names[$j+1]; |
||||||
|
$coedits["$target"]["$dest"]++ ; |
||||||
|
# dirty since it's a string, not a proper table but will do for tests |
||||||
|
} |
||||||
|
} |
||||||
|
foreach ($coedits as &$ce){ |
||||||
|
arsort($ce,SORT_NUMERIC); |
||||||
|
//$scoedits[] = $ce; |
||||||
|
} |
||||||
|
//var_dump($coedits); |
||||||
|
|
||||||
|
# should highlight the highest coedition that is not self |
||||||
|
# also remove under a certain threshold, e.g. 1 or rather a sigma of the distribution |
||||||
|
# most result are... from the same page |
||||||
|
# it could thus be noted then filtered |
||||||
|
# also the timewindow gives only short-term result |
||||||
|
# a second processing could check over long-term editions between pages |
||||||
|
|
||||||
|
#write cache |
||||||
|
if ($groupname == "") |
||||||
|
$write_result = file_put_contents($FarmD.$cachefile,serialize($coedits)); |
||||||
|
return $coedits; |
||||||
|
} |
||||||
|
|
||||||
|
?> |
@ -0,0 +1,162 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
# return the "key pages" of a group |
||||||
|
# todo |
||||||
|
# http://phpir.com/pagerank-in-php |
||||||
|
# http://faculty.ucr.edu/~hanneman/nettext/C10_Centrality.html#Betweenness |
||||||
|
# check if isset() really is necessary, seems it was avoided in Coeditions |
||||||
|
|
||||||
|
function GroupKeyPages($groupname,$selectionmechanism=""){ |
||||||
|
$pages = ListPages("/$groupname\./e"); |
||||||
|
|
||||||
|
//note that this could be replaced by proper ListPages call |
||||||
|
$pages = CleanPageList($pages,$groupname); |
||||||
|
|
||||||
|
$b = GenerateNetworkFromList($pages); |
||||||
|
//var_dump($b); |
||||||
|
|
||||||
|
switch ($selectionmechanism) { |
||||||
|
case "NetworkLeverageCentrality": |
||||||
|
$keypages = $selectionmechanism($b,0.05); # value threshold |
||||||
|
break; |
||||||
|
case "NetworkOutgoingIncoming": |
||||||
|
$keypages = $selectionmechanism($b,4,5); # outgoing and incoming degree threshold |
||||||
|
break; |
||||||
|
default: |
||||||
|
$keypages = NetworkDegree($b,8); # degree threshold |
||||||
|
} |
||||||
|
return array_unique($keypages); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function GenerateNetworkFromList($pagelist){ |
||||||
|
foreach ($pagelist as $page) { |
||||||
|
$content = ReadPage($page,$since=0); |
||||||
|
$links = $content["targets"]; |
||||||
|
$links_array = explode(",",$links); |
||||||
|
foreach ($links_array as $link) { |
||||||
|
if (($linkindex = array_search($link,$pagelist)) !== false ){ |
||||||
|
if (isset($b["$page"]["outgoing"])) |
||||||
|
$b["$page"]["outgoing"]++; |
||||||
|
else |
||||||
|
{ $b["$page"]["outgoing"] = 1; $b["$page"]["name"]=$page; } |
||||||
|
if (isset( $b["$link"]["incoming"])) |
||||||
|
$b["$link"]["incoming"]++; |
||||||
|
else |
||||||
|
{ $b["$link"]["incoming"] = 1; $b["$link"]["name"]=$link; } |
||||||
|
if (isset($b["$page"]["degree"])) |
||||||
|
$b["$page"]["degree"]++; |
||||||
|
else |
||||||
|
{ $b["$page"]["degree"] = 1; $b["$page"]["name"]=$page; } |
||||||
|
if (isset($b["$link"]["degree"])) |
||||||
|
$b["$link"]["degree"]++; |
||||||
|
else |
||||||
|
{ $b["$link"]["degree"] = 1; $b["$link"]["name"]=$link; } |
||||||
|
$b["$page"]["neighboors"][] = $link; |
||||||
|
$b["$link"]["neighboors"][] = $page; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $b; |
||||||
|
} |
||||||
|
|
||||||
|
function CleanPageList($pagelist,$groupname){ |
||||||
|
// rather arbitrary, not necessarily a good choice |
||||||
|
unset($pagelist[array_search("$groupname.$groupname",$pagelist)]); |
||||||
|
unset($pagelist[array_search("$groupname.Template",$pagelist)]); |
||||||
|
unset($pagelist[array_search("$groupname.GroupHeader",$pagelist)]); |
||||||
|
unset($pagelist[array_search("$groupname.GroupFooter",$pagelist)]); |
||||||
|
return $pagelist; |
||||||
|
} |
||||||
|
|
||||||
|
function NetworkOutgoingIncoming($b,$IncomingThreshold=0,$OutgoingThreshold=0){ |
||||||
|
$keypages = array(); //done to avoid returning notthing if the theshold is too high |
||||||
|
foreach ($b as $bs){ |
||||||
|
if (isset($bs["incoming"])) |
||||||
|
if ($bs["incoming"] > $IncomingThreshold ) |
||||||
|
$keypages[] = $bs["name"]; |
||||||
|
if (isset($bs["outgoing"])) |
||||||
|
if ($bs["outgoing"] > $OutgoingThreshold ) |
||||||
|
$keypages[] = $bs["name"]; |
||||||
|
} |
||||||
|
return $keypages; |
||||||
|
} |
||||||
|
|
||||||
|
function NetworkDegree($b, $DegreeThreshold=0){ |
||||||
|
$keypages = array(); //done to avoid returning notthing if the theshold is too high |
||||||
|
foreach ($b as $bs){ |
||||||
|
if (isset($bs["degree"])) |
||||||
|
if ($bs["degree"] > $DegreeThreshold ) |
||||||
|
$keypages[] = $bs["name"]; |
||||||
|
} |
||||||
|
return $keypages; |
||||||
|
} |
||||||
|
|
||||||
|
function NetworkLeverageCentrality($b,$Threshold=0){ |
||||||
|
$keypages = array(); //done to avoid returning notthing if the theshold is too high |
||||||
|
foreach ($b as $bs){ |
||||||
|
if (isset($bs["neighboors"])){ |
||||||
|
$bs["leveragecentrality"] = 0; |
||||||
|
$sum = 0; $avg=0; |
||||||
|
foreach($bs["neighboors"] as $neighboor){ |
||||||
|
$sum += ($bs["degree"] - $b["$neighboor"]["degree"]) / ($bs["degree"] + $b["$neighboor"]["degree"]); |
||||||
|
$avg += $b["$neighboor"]["degree"]; |
||||||
|
} |
||||||
|
if ($bs["degree"] > 0){ |
||||||
|
$avg = $avg / $bs["degree"]; |
||||||
|
if ($avg > 0){ |
||||||
|
$bs["leveragecentrality"] = ($sum/$avg) / $bs["degree"]; |
||||||
|
} |
||||||
|
} |
||||||
|
if ($bs["leveragecentrality"] > $Threshold ) |
||||||
|
$keypages[] = $bs["name"]; |
||||||
|
} |
||||||
|
} |
||||||
|
return $keypages; |
||||||
|
} |
||||||
|
|
||||||
|
function GroupDegreeDistribution($groupname){ |
||||||
|
$pages = ListPages("/$groupname\./e"); |
||||||
|
|
||||||
|
//note that this could be replaced by proper ListPages call |
||||||
|
$pages = CleanPageList($pages,$groupname); |
||||||
|
|
||||||
|
$b = GenerateNetworkFromList($pages); |
||||||
|
|
||||||
|
$distribution = array_fill(1,10,0); |
||||||
|
// has no effect |
||||||
|
|
||||||
|
foreach ($b as $node){ |
||||||
|
$degree = $node["degree"]; |
||||||
|
if (isset($distribution[$degree])) |
||||||
|
$distribution[$degree]++; |
||||||
|
else |
||||||
|
$distribution[$degree]=1; |
||||||
|
$sumdeg += $node["degree"]; |
||||||
|
$sumin += $node["incoming"]; |
||||||
|
$sumout += $node["outgoing"]; |
||||||
|
} |
||||||
|
$avgdeg = $sumdeg / count($b); |
||||||
|
$avgin = $sumin / count($b); |
||||||
|
$avgout = $sumout / count($b); |
||||||
|
|
||||||
|
/* |
||||||
|
print "avgdeg = $avgdeg; "; |
||||||
|
print "avgin = $avgin; "; |
||||||
|
print "avgout = $avgout; "; |
||||||
|
strangely equal, probably a mistake there |
||||||
|
*/ |
||||||
|
ksort($distribution); |
||||||
|
|
||||||
|
/* fails to get the proper last key |
||||||
|
end($distribution); |
||||||
|
$last_key = key($distribution); |
||||||
|
print $last_key; |
||||||
|
for ($i=1;i<$last_key;$i++) |
||||||
|
if (!(isset($distribution[$i]))) |
||||||
|
$distribution[$i]=0; |
||||||
|
*/ |
||||||
|
return array_unique($distribution); |
||||||
|
} |
||||||
|
|
||||||
|
?> |
@ -0,0 +1,50 @@ |
|||||||
|
<?php
|
||||||
|
|
||||||
|
# give a visual representation of pages and group |
||||||
|
# |
||||||
|
# action for the whole wiki (equivalent to group="") done through AllPages fake group |
||||||
|
# add the GroupKeyPages function as a parameter |
||||||
|
|
||||||
|
$RecipeInfo['GroupStats']['Version'] = '2011-08-06'; |
||||||
|
|
||||||
|
$HandleActions['GroupStats'] = 'GroupStats'; # if url contains action=myaction call HandleMyAction timely |
||||||
|
$HandleAuth['GroupStats'] = 'read'; # authorization level $auth for HandleMyAction |
||||||
|
|
||||||
|
function GroupStats($pagename, $auth){ |
||||||
|
list($group,$page) = explode(".",$pagename); |
||||||
|
$distmax = 15; |
||||||
|
if ($group == "AllPages"){ |
||||||
|
// equivalent to getting ALL pages |
||||||
|
$group = ""; |
||||||
|
$distmax = 50; |
||||||
|
} |
||||||
|
$dist= GroupDegreeDistribution($group); |
||||||
|
for($i=1;$i<$distmax;$i++){ |
||||||
|
if (isset($dist[$i])) |
||||||
|
$distribution .= $dist[$i].","; |
||||||
|
else |
||||||
|
$distribution .= "0,"; |
||||||
|
} |
||||||
|
$max = max($dist); |
||||||
|
$upperbound = $dist[($distmax/5)]; |
||||||
|
$img = "http://sparklines.bitworking.info/spark.cgi?type=impulse" |
||||||
|
."&d=$distribution&height=100" |
||||||
|
."&limits=0,$max" |
||||||
|
."&upper=$upperbound&above-color=red&below-color=gray&width=15&.png"; |
||||||
|
$selectingalgo = "NetworkDegree"; |
||||||
|
# can also be NetworkOutgoingIncoming or NetworkLeverageCentrality or NetworkDegree |
||||||
|
# threshold are set later on |
||||||
|
$keypages = var_export(GroupKeyPages($group, $selectingalgo),true); |
||||||
|
$coeditions = var_export(Coeditions($group),true); |
||||||
|
# could be improvied by coloring |
||||||
|
# link to self |
||||||
|
# links that do not exist explicitely |
||||||
|
print "<h1>Group statistics for $group</h1>" |
||||||
|
."<hr/><h2>Degree distribution</h2>(from d(1) to d(max), d()=0 excluded, max(d())=2, avg(d())~=4):</br>" |
||||||
|
.$distribution."<br><img src=\"$img\" /><br>" |
||||||
|
."<hr/><h2><a name=\"Key pages\"></a>Keypages using $selectingalgo</h2><pre>".$keypages."</pre>" |
||||||
|
."<hr/><h2><a name=\"Coeditions\"></a>Coedition</h2><pre>".$coeditions."</pre>"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
?> |
@ -0,0 +1,386 @@ |
|||||||
|
<?php if (!defined('PmWiki')) exit(); |
||||||
|
/* |
||||||
|
inspired by PageFeed by Daniel Roesler (diafygi) |
||||||
|
conversation array imported from it |
||||||
|
*/ |
||||||
|
|
||||||
|
## Recipe version information |
||||||
|
$RecipeInfo['Memorization']['Version'] = '2010-04-02'; |
||||||
|
|
||||||
|
## Add action for pagefeed |
||||||
|
SDV($HandleActions['memorization'], 'Memorization'); |
||||||
|
|
||||||
|
# from http://www.pmwiki.org/wiki/PmWiki/Functions |
||||||
|
function FeedText($pagename, &$page, $tag) { |
||||||
|
$text = RetrieveAuthSection("ReadingNotes.GroupHeader",""); |
||||||
|
$content = MarkupToHTML($pagename, $text); |
||||||
|
$text = RetrieveAuthSection($pagename, '##Chapter2'); |
||||||
|
$content .= MarkupToHTML($pagename, $text); |
||||||
|
return "<$tag><![CDATA[$content]]></$tag>"; |
||||||
|
} |
||||||
|
|
||||||
|
function addDate($date,$day)//add days |
||||||
|
{ |
||||||
|
$sum = strtotime(date("Y-m-d", strtotime("$date")) . " +$day days"); |
||||||
|
$dateTo=date('Y-m-d',$sum); |
||||||
|
return $dateTo; |
||||||
|
} |
||||||
|
function convertdate($date) { |
||||||
|
return preg_replace("/(\d+)\/(\d+)\/(\d+)/",'$3-$2-$1',$date); |
||||||
|
} |
||||||
|
|
||||||
|
## Create feed from page history |
||||||
|
function Memorization($pagename, $auth = 'read') { |
||||||
|
global $FarmD, $WikiTitle, $ScriptUrl; |
||||||
|
$feedfile = $FarmD."/pub/memorizationfeed.xml"; #change to a pattern when support arguments |
||||||
|
$datestorecall = array(1,10,30,60,120,350,700,1500,3000,7000,15000,30000,100000); |
||||||
|
// $datestorecall = array(1,10,30,60..,61,62..,80..); |
||||||
|
$varname='startrecall'; |
||||||
|
|
||||||
|
$pages = ListPages(); |
||||||
|
# open $feed as read |
||||||
|
if (!file_exists($feedfile)) |
||||||
|
if (!touch($feedfile)) |
||||||
|
print "Creation of the feed file fails, check write permissions for pmWiki and $feedfile."; |
||||||
|
|
||||||
|
$feed_oldcontent = file_get_contents($feedfile); |
||||||
|
|
||||||
|
$feed_newcontent = ''; |
||||||
|
|
||||||
|
# 2 loops can be probably optimized since they are ordered by date |
||||||
|
foreach ($pages as $page) { |
||||||
|
$daterecall = PageTextVar($page,$varname); |
||||||
|
if ( isset($daterecall) ) { |
||||||
|
foreach ($datestorecall as $day) { |
||||||
|
# print $page . " "; |
||||||
|
$checkdate = addDate(convertdate($daterecall),$day); |
||||||
|
# print $daterecall . " + " . $day . " (" . $checkdate . ") == " . date("d/m/Y"); |
||||||
|
if ($checkdate==convertdate(date("d/m/Y"))) |
||||||
|
{ |
||||||
|
# print " recall time"; |
||||||
|
# generate GUID |
||||||
|
$item_GUID = $page.'_'.$checkdate; |
||||||
|
# if not present in file using a regex on the GUID |
||||||
|
if (preg_match("/$item_GUID/",$feed_oldcontent) == 0) |
||||||
|
{ |
||||||
|
|
||||||
|
# generate date |
||||||
|
$feed_newitemdate = date(DATE_RSS, time()); |
||||||
|
# transform line to XML format |
||||||
|
$cleaned_page_name = str_replace(".","/",$page); |
||||||
|
// function FeedText($pagename, &$page, $tag) { |
||||||
|
//"manually" add the cover by simulating the GroupHeadre (read page ISBN + if exist display image) |
||||||
|
$feed_newitem = " <item> |
||||||
|
<title>Day $day recall for page $page started at $daterecall</title> |
||||||
|
<link>$ScriptUrl/$cleaned_page_name#MemorizationDay$day</link>" |
||||||
|
.FeedText($page,$page,"description"). |
||||||
|
"<guid>$item_GUID</guid> |
||||||
|
<pubDate>$feed_newitemdate</pubDate> |
||||||
|
</item>"; |
||||||
|
# bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] ) |
||||||
|
# appending the item |
||||||
|
$feed_newcontent .= $feed_newitem; |
||||||
|
} |
||||||
|
break; #we can't have 2 days at the same time |
||||||
|
} |
||||||
|
# print "<br/>"; |
||||||
|
} # check if the next recall day is today |
||||||
|
} # check if the next page is tagged |
||||||
|
} |
||||||
|
# feed should be properly updated |
||||||
|
|
||||||
|
$feed_newdate = date(DATE_RSS, time()); |
||||||
|
|
||||||
|
$feed_header = "<?xml version=\"1.0\"?>
|
||||||
|
<rss version=\"2.0\"> |
||||||
|
<channel> |
||||||
|
<title>Memorization feed for $WikiTitle .</title> |
||||||
|
<link>$ScriptUrl</link> |
||||||
|
<description>Receive links to the page you tagged in order to have optimal memorization.</description> |
||||||
|
<generator>Generated by http://fabien.benetou.fr/Wiki/MemoryRecipe for PmWiki</generator> |
||||||
|
<lastBuildDate>$feed_newdate</lastBuildDate>"; |
||||||
|
|
||||||
|
$feed_footer = " |
||||||
|
</channel> |
||||||
|
</rss>"; |
||||||
|
|
||||||
|
|
||||||
|
# print header |
||||||
|
print $feed_header; |
||||||
|
|
||||||
|
# print items |
||||||
|
print $feed_oldcontent; |
||||||
|
# $feed_newcontent = str_replace(array_keys($EntitiesTable), array_values($EntitiesTable), $feed_newcontent); |
||||||
|
print $feed_newcontent; |
||||||
|
|
||||||
|
# print footer |
||||||
|
print $feed_footer; |
||||||
|
|
||||||
|
$write_result = file_put_contents($feedfile,$feed_oldcontent.$feed_newcontent); |
||||||
|
if (!$write_result) |
||||||
|
if (strlen($feed_oldcontent.$feed_newcontent)>0) |
||||||
|
print "Creation of the feed file fails, check write permissions for pmWiki and $feedfile."; |
||||||
|
else |
||||||
|
print "No item to generate, did you correctly tag your pages?"; |
||||||
|
} |
||||||
|
|
||||||
|
## Since most feeds don't understand html character entities, we |
||||||
|
## convert the common ones to their numeric form here. |
||||||
|
## Taken from /scripts/feeds.php |
||||||
|
SDVA($EntitiesTable, array( |
||||||
|
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent" |
||||||
|
' ' => ' ', |
||||||
|
'¡' => '¡', |
||||||
|
'¢' => '¢', |
||||||
|
'£' => '£', |
||||||
|
'¤' => '¤', |
||||||
|
'¥' => '¥', |
||||||
|
'¦' => '¦', |
||||||
|
'§' => '§', |
||||||
|
'¨' => '¨', |
||||||
|
'©' => '©', |
||||||
|
'ª' => 'ª', |
||||||
|
'«' => '«', |
||||||
|
'¬' => '¬', |
||||||
|
'­' => '­', |
||||||
|
'®' => '®', |
||||||
|
'¯' => '¯', |
||||||
|
'°' => '°', |
||||||
|
'±' => '±', |
||||||
|
'²' => '²', |
||||||
|
'³' => '³', |
||||||
|
'´' => '´', |
||||||
|
'µ' => 'µ', |
||||||
|
'¶' => '¶', |
||||||
|
'·' => '·', |
||||||
|
'¸' => '¸', |
||||||
|
'¹' => '¹', |
||||||
|
'º' => 'º', |
||||||
|
'»' => '»', |
||||||
|
'¼' => '¼', |
||||||
|
'½' => '½', |
||||||
|
'¾' => '¾', |
||||||
|
'¿' => '¿', |
||||||
|
'À' => 'À', |
||||||
|
'Á' => 'Á', |
||||||
|
'Â' => 'Â', |
||||||
|
'Ã' => 'Ã', |
||||||
|
'Ä' => 'Ä', |
||||||
|
'Å' => 'Å', |
||||||
|
'Æ' => 'Æ', |
||||||
|
'Ç' => 'Ç', |
||||||
|
'È' => 'È', |
||||||
|
'É' => 'É', |
||||||
|
'Ê' => 'Ê', |
||||||
|
'Ë' => 'Ë', |
||||||
|
'Ì' => 'Ì', |
||||||
|
'Í' => 'Í', |
||||||
|
'Î' => 'Î', |
||||||
|
'Ï' => 'Ï', |
||||||
|
'Ð' => 'Ð', |
||||||
|
'Ñ' => 'Ñ', |
||||||
|
'Ò' => 'Ò', |
||||||
|
'Ó' => 'Ó', |
||||||
|
'Ô' => 'Ô', |
||||||
|
'Õ' => 'Õ', |
||||||
|
'Ö' => 'Ö', |
||||||
|
'×' => '×', |
||||||
|
'Ø' => 'Ø', |
||||||
|
'Ù' => 'Ù', |
||||||
|
'Ú' => 'Ú', |
||||||
|
'Û' => 'Û', |
||||||
|
'Ü' => 'Ü', |
||||||
|
'Ý' => 'Ý', |
||||||
|
'Þ' => 'Þ', |
||||||
|
'ß' => 'ß', |
||||||
|
'à' => 'à', |
||||||
|
'á' => 'á', |
||||||
|
'â' => 'â', |
||||||
|
'ã' => 'ã', |
||||||
|
'ä' => 'ä', |
||||||
|
'å' => 'å', |
||||||
|
'æ' => 'æ', |
||||||
|
'ç' => 'ç', |
||||||
|
'è' => 'è', |
||||||
|
'é' => 'é', |
||||||
|
'ê' => 'ê', |
||||||
|
'ë' => 'ë', |
||||||
|
'ì' => 'ì', |
||||||
|
'í' => 'í', |
||||||
|
'î' => 'î', |
||||||
|
'ï' => 'ï', |
||||||
|
'ð' => 'ð', |
||||||
|
'ñ' => 'ñ', |
||||||
|
'ò' => 'ò', |
||||||
|
'ó' => 'ó', |
||||||
|
'ô' => 'ô', |
||||||
|
'õ' => 'õ', |
||||||
|
'ö' => 'ö', |
||||||
|
'÷' => '÷', |
||||||
|
'ø' => 'ø', |
||||||
|
'ù' => 'ù', |
||||||
|
'ú' => 'ú', |
||||||
|
'û' => 'û', |
||||||
|
'ü' => 'ü', |
||||||
|
'ý' => 'ý', |
||||||
|
'þ' => 'þ', |
||||||
|
'ÿ' => 'ÿ', |
||||||
|
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent" |
||||||
|
'"' => '"', |
||||||
|
#'&' => '&#38;', |
||||||
|
#'<' => '&#60;', |
||||||
|
#'>' => '>', |
||||||
|
''' => ''', |
||||||
|
'Œ' => 'Œ', |
||||||
|
'œ' => 'œ', |
||||||
|
'Š' => 'Š', |
||||||
|
'š' => 'š', |
||||||
|
'Ÿ' => 'Ÿ', |
||||||
|
'ˆ' => 'ˆ', |
||||||
|
'˜' => '˜', |
||||||
|
' ' => ' ', |
||||||
|
' ' => ' ', |
||||||
|
' ' => ' ', |
||||||
|
'‌' => '‌', |
||||||
|
'‍' => '‍', |
||||||
|
'‎' => '‎', |
||||||
|
'‏' => '‏', |
||||||
|
'–' => '–', |
||||||
|
'—' => '—', |
||||||
|
'‘' => '‘', |
||||||
|
'’' => '’', |
||||||
|
'‚' => '‚', |
||||||
|
'“' => '“', |
||||||
|
'”' => '”', |
||||||
|
'„' => '„', |
||||||
|
'†' => '†', |
||||||
|
'‡' => '‡', |
||||||
|
'‰' => '‰', |
||||||
|
'‹' => '‹', |
||||||
|
'›' => '›', |
||||||
|
'€' => '€', |
||||||
|
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent" |
||||||
|
'ƒ' => 'ƒ', |
||||||
|
'Α' => 'Α', |
||||||
|
'Β' => 'Β', |
||||||
|
'Γ' => 'Γ', |
||||||
|
'Δ' => 'Δ', |
||||||
|
'Ε' => 'Ε', |
||||||
|
'Ζ' => 'Ζ', |
||||||
|
'Η' => 'Η', |
||||||
|
'Θ' => 'Θ', |
||||||
|
'Ι' => 'Ι', |
||||||
|
'Κ' => 'Κ', |
||||||
|
'Λ' => 'Λ', |
||||||
|
'Μ' => 'Μ', |
||||||
|
'Ν' => 'Ν', |
||||||
|
'Ξ' => 'Ξ', |
||||||
|
'Ο' => 'Ο', |
||||||
|
'Π' => 'Π', |
||||||
|
'Ρ' => 'Ρ', |
||||||
|
'Σ' => 'Σ', |
||||||
|
'Τ' => 'Τ', |
||||||
|
'Υ' => 'Υ', |
||||||
|
'Φ' => 'Φ', |
||||||
|
'Χ' => 'Χ', |
||||||
|
'Ψ' => 'Ψ', |
||||||
|
'Ω' => 'Ω', |
||||||
|
'α' => 'α', |
||||||
|
'β' => 'β', |
||||||
|
'γ' => 'γ', |
||||||
|
'δ' => 'δ', |
||||||
|
'ε' => 'ε', |
||||||
|
'ζ' => 'ζ', |
||||||
|
'η' => 'η', |
||||||
|
'θ' => 'θ', |
||||||
|
'ι' => 'ι', |
||||||
|
'κ' => 'κ', |
||||||
|
'λ' => 'λ', |
||||||
|
'μ' => 'μ', |
||||||
|
'ν' => 'ν', |
||||||
|
'ξ' => 'ξ', |
||||||
|
'ο' => 'ο', |
||||||
|
'π' => 'π', |
||||||
|
'ρ' => 'ρ', |
||||||
|
'ς' => 'ς', |
||||||
|
'σ' => 'σ', |
||||||
|
'τ' => 'τ', |
||||||
|
'υ' => 'υ', |
||||||
|
'φ' => 'φ', |
||||||
|
'χ' => 'χ', |
||||||
|
'ψ' => 'ψ', |
||||||
|
'ω' => 'ω', |
||||||
|
'ϑ' => 'ϑ', |
||||||
|
'ϒ' => 'ϒ', |
||||||
|
'ϖ' => 'ϖ', |
||||||
|
'•' => '•', |
||||||
|
'…' => '…', |
||||||
|
'′' => '′', |
||||||
|
'″' => '″', |
||||||
|
'‾' => '‾', |
||||||
|
'⁄' => '⁄', |
||||||
|
'℘' => '℘', |
||||||
|
'ℑ' => 'ℑ', |
||||||
|
'ℜ' => 'ℜ', |
||||||
|
'™' => '™', |
||||||
|
'ℵ' => 'ℵ', |
||||||
|
'←' => '←', |
||||||
|
'↑' => '↑', |
||||||
|
'→' => '→', |
||||||
|
'↓' => '↓', |
||||||
|
'↔' => '↔', |
||||||
|
'↵' => '↵', |
||||||
|
'⇐' => '⇐', |
||||||
|
'⇑' => '⇑', |
||||||
|
'⇒' => '⇒', |
||||||
|
'⇓' => '⇓', |
||||||
|
'⇔' => '⇔', |
||||||
|
'∀' => '∀', |
||||||
|
'∂' => '∂', |
||||||
|
'∃' => '∃', |
||||||
|
'∅' => '∅', |
||||||
|
'∇' => '∇', |
||||||
|
'∈' => '∈', |
||||||
|
'∉' => '∉', |
||||||
|
'∋' => '∋', |
||||||
|
'∏' => '∏', |
||||||
|
'∑' => '∑', |
||||||
|
'−' => '−', |
||||||
|
'∗' => '∗', |
||||||
|
'√' => '√', |
||||||
|
'∝' => '∝', |
||||||
|
'∞' => '∞', |
||||||
|
'∠' => '∠', |
||||||
|
'∧' => '∧', |
||||||
|
'∨' => '∨', |
||||||
|
'∩' => '∩', |
||||||
|
'∪' => '∪', |
||||||
|
'∫' => '∫', |
||||||
|
'∴' => '∴', |
||||||
|
'∼' => '∼', |
||||||
|
'≅' => '≅', |
||||||
|
'≈' => '≈', |
||||||
|
'≠' => '≠', |
||||||
|
'≡' => '≡', |
||||||
|
'≤' => '≤', |
||||||
|
'≥' => '≥', |
||||||
|
'⊂' => '⊂', |
||||||
|
'⊃' => '⊃', |
||||||
|
'⊄' => '⊄', |
||||||
|
'⊆' => '⊆', |
||||||
|
'⊇' => '⊇', |
||||||
|
'⊕' => '⊕', |
||||||
|
'⊗' => '⊗', |
||||||
|
'⊥' => '⊥', |
||||||
|
'⋅' => '⋅', |
||||||
|
'⌈' => '⌈', |
||||||
|
'⌉' => '⌉', |
||||||
|
'⌊' => '⌊', |
||||||
|
'⌋' => '⌋', |
||||||
|
'⟨' => '〈', |
||||||
|
'⟩' => '〉', |
||||||
|
'◊' => '◊', |
||||||
|
'♠' => '♠', |
||||||
|
'♣' => '♣', |
||||||
|
'♥' => '♥', |
||||||
|
'♦' => '♦')); |
@ -0,0 +1,218 @@ |
|||||||
|
<?php |
||||||
|
// PIM functions (for PmWiki) |
||||||
|
// consider adding other related scripts here too (e.g. MemoryRecipe, Recalls, GroupStats, Coeditions, ...) |
||||||
|
// http://fabien.benetou.fr/pub/graphformatexporter.php.txt |
||||||
|
// http://fabien.benetou.fr/pub/memorization.php.txt |
||||||
|
// note that the order is important though |
||||||
|
// e.g. currently MemoryRecipe is loaded after thus can't be called here |
||||||
|
// add to http://fabien.benetou.fr/repository/ |
||||||
|
// it would be particularly useful to refactor each properly |
||||||
|
// especially since they share variables (e.g. first edit) but also some have better function |
||||||
|
// e.g. caching in Coeditions |
||||||
|
// change ProcessingJS generation by first producing JSON |
||||||
|
// via http://www.php.net/manual/en/function.json-encode.php |
||||||
|
// cf http://fabien.benetou.fr/Tools/Processing and http://fabien.benetou.fr/Tools/JavaScript |
||||||
|
// this might be even faster on most computers since JS engines are improving |
||||||
|
|
||||||
|
//handle implicit linking |
||||||
|
/* |
||||||
|
cf http://fabien.benetou.fr/MemoryRecalls/ImprovingPIM#ImplicitLinking |
||||||
|
*/ |
||||||
|
function ImplicitLinking(){ |
||||||
|
return "list of pages generated on the fly"; |
||||||
|
} |
||||||
|
//$AutoCreate['/\\.GroupStats$/'] = array( 'ctime' => $Now, 'text' => ImplicitLinking()); |
||||||
|
//$AutoCreate['/^Categora\\./'] = array('ctime' => $Now); |
||||||
|
//doesn't work, AutoCreate present in pmwiki.php and example too |
||||||
|
// category works though |
||||||
|
// TODO try making it global $AutoCreate; |
||||||
|
|
||||||
|
//display working status |
||||||
|
// see http://fabien.benetou.fr/Tools/Greasemonkey#VirtualBlinders |
||||||
|
Markup("currenttask", "directives", "/\(:currenttask:\)/", GetCurrentTask()); |
||||||
|
function GetCurrentTask(){ |
||||||
|
$currenttask = trim(file_get_contents("/home/utopiah/web/benetou.fr/fabien/pub/currenttask")); |
||||||
|
if ($currenttask == "") |
||||||
|
return "(either available or asleep, Im usually on CET)"; |
||||||
|
return "[[CognitiveEnvironments/".$currenttask."]]"; |
||||||
|
} |
||||||
|
|
||||||
|
Markup("timetable", "fulltext", "/\(:timetable:\)/", |
||||||
|
"\n||border=1\n||!Time ||!Action ||\n" |
||||||
|
.preg_replace("/.* (\d+) (\d+).* \/(.*)/","||$1:$2||$3||",file_get_contents("/home/utopiah/.irssi/cron.save")) |
||||||
|
.""); |
||||||
|
|
||||||
|
//load a dedicated edition page for the admin (shouldn't be hard coded but I dont use Auth) |
||||||
|
//global $GLOBALS; |
||||||
|
if ($GLOBALS['action'] == 'edit' && ( $GLOBALS['Author'] == 'Fabien' || $GLOBALS['Author'] == 'Utopiah' ) ) |
||||||
|
{ |
||||||
|
//TODO fails since moved in cookbook directory, thus added back there |
||||||
|
global $SkinDir,$pagename; |
||||||
|
LoadPageTemplate($pagename, "$SkinDir/edit.tmpl"); |
||||||
|
} |
||||||
|
|
||||||
|
//display editions through an horizontal line |
||||||
|
/* |
||||||
|
fomally done via GnuPlot, cf http://fabien.benetou.fr/Wiki/Visualization#timeline |
||||||
|
http://www.scholarpedia.org/article/Spike-response_model is probably too complicated for the small resolution |
||||||
|
yet provide interesting non-linear properties |
||||||
|
|
||||||
|
*/ |
||||||
|
function DisplayVisualEdits($pagename){ |
||||||
|
global $ScriptUrl, $PubDir, $FarmD; |
||||||
|
|
||||||
|
$processingpath = '/pub/libraries/processing.js'; |
||||||
|
$processingfile = "/pub/visualization/edits_per_page/$pagename.pjs"; |
||||||
|
$processinglib = "<script src=\"$processingpath\" type=\"text/javascript\"></script>"; |
||||||
|
$first_edit = 1212192000; |
||||||
|
$now = time(); |
||||||
|
// draw the timeline from the first edit to now() |
||||||
|
// get the list of edits of the current page |
||||||
|
// "get inspired" by PrintDiff() in scripts/pagerev.php |
||||||
|
$canvaswidth = 600-2*10; |
||||||
|
$canvasheight = 10; |
||||||
|
$block_width = 4; |
||||||
|
$block_height = 8; |
||||||
|
$page = ReadPage($pagename); |
||||||
|
if (!$page) return; |
||||||
|
krsort($page); reset($page); |
||||||
|
// newest first |
||||||
|
// for each edit |
||||||
|
$canvas = " |
||||||
|
void setup() |
||||||
|
{ |
||||||
|
size($canvaswidth, $canvasheight); |
||||||
|
PFont font; |
||||||
|
font = loadFont(\"FFScala-Bold-12.vlw\"); |
||||||
|
textFont(font); |
||||||
|
} |
||||||
|
void mouseMoved() { |
||||||
|
checkButtons(); |
||||||
|
} |
||||||
|
|
||||||
|
void mouseDragged() { |
||||||
|
checkButtons(); |
||||||
|
} |
||||||
|
void draw() |
||||||
|
{ |
||||||
|
background(251); |
||||||
|
fill(0,0,255,20); |
||||||
|
noStroke(); |
||||||
|
"; |
||||||
|
$mousePressed = "void mousePressed() {"; |
||||||
|
$destination_link = "$ScriptUrl/".strtr($pagename,".","/")."?action=diff#diff"; |
||||||
|
$mousePressed .= "\t\tif (lastHovered>0) { link(\"$destination_link\"+lastHovered); }\n"; |
||||||
|
$checkButtons = "void checkButtons() {"; |
||||||
|
print $processinglib.'<canvas data-src="'.$processingfile.'" width="'.$canvaswidth.'" height="'.$canvasheight.'"></canvas>'; |
||||||
|
// set to false to de-activate cache (practical for tests) |
||||||
|
$newest_diff = true; |
||||||
|
//$newest_diff = false; |
||||||
|
//$first_diff = true; |
||||||
|
foreach($page as $k=>$v) { |
||||||
|
if (!preg_match("/^diff:(\d+):(\d+):?([^:]*)/",$k,$match)) continue; |
||||||
|
|
||||||
|
$diff = $match[1]; |
||||||
|
|
||||||
|
$diffclass = $match[3]; |
||||||
|
if ($diffclass=='minor') |
||||||
|
{ $canvas .= "\t\tfill(0,255,0,20);\n"; } |
||||||
|
else |
||||||
|
{ $canvas .= "\t\tfill(0,0,255,20);\n"; } |
||||||
|
//if ($first_diff) |
||||||
|
// { $canvas .= "\t\tfill(255,0,0,20);\n"; $first_diff = false;} |
||||||
|
|
||||||
|
$buttonname = "over".$diff."Button"; |
||||||
|
//$bools .= "boolean $buttonname = false;\n"; |
||||||
|
if (file_exists($FarmD.$processingfile) && $newest_diff) |
||||||
|
if ( filemtime($FarmD.$processingfile) > $diff) |
||||||
|
return; |
||||||
|
$newest_diff = false; |
||||||
|
// add a sightly transparent tick rectangle with its Unix timestamp link to the diff page |
||||||
|
// the mouse over a certain edit should change its color |
||||||
|
// see http://processingjs.org/learning/basic/embeddedlinks |
||||||
|
// or clicablerects.js via Pomax on :mozilla2/#processing.js (14/05/2011 ~11pm) |
||||||
|
$x = round ( ($canvaswidth - $block_width) * ( (($now - $first_edit)-($now-$diff)) / ($now - $first_edit))); |
||||||
|
$y = 1; |
||||||
|
$checkButtons .= "\t\tif ( mouseX > $x && mouseX < $x+$block_width) lastHovered = $diff; \n"; |
||||||
|
// if (mouseY > $y && mouseY < $y+$block_height) not really required |
||||||
|
// others should be set to false else one always jump to the olded diff mouved over |
||||||
|
$canvas .= "\t\trect($x,$y,$block_width,$block_height);\n"; |
||||||
|
} |
||||||
|
$canvas .= "\t\tstroke(0,155);\n"; |
||||||
|
$canvas .= "\t\tfill(0,0,255,80);\n"; |
||||||
|
$canvas .= "\t\ttext(\"Edits:\",2,10 );\n"; |
||||||
|
$canvas .= "\t\tfill(0,0,255,40);\n"; |
||||||
|
for ($year=2009;$year<2012;$year++){ //each year until now |
||||||
|
$unixyear = mktime(0,0,0,1,1,$year); |
||||||
|
$x = round ( ($canvaswidth - $block_width) * ( (($now - $first_edit)-($now-$unixyear)) / ($now - $first_edit))); |
||||||
|
$y = 0; |
||||||
|
$canvas .= "line($x,$y,$x,$y+$block_height+2); text(\"$year\",$x+2,$y+10 );\n"; |
||||||
|
} |
||||||
|
$canvas = $bools . $canvas ."}" . $mousePressed ."}" .$checkButtons . "}"; |
||||||
|
|
||||||
|
// load ProcessinJS |
||||||
|
|
||||||
|
$write_result = file_put_contents($FarmD.$processingfile,$canvas); |
||||||
|
|
||||||
|
// print resulting canvas |
||||||
|
|
||||||
|
$older_gnuplot_version = "<div><center><img src=\"/pub/visualization/edits_per_page/{$pagename}.png\" alt=\"/pub/visualization/edits_per_page/{$pagename}.png\"/></br>(<a href=\"$ScriptUrl/Wiki/Visualization#timeline\">visualization details</a>).</center></div><hr />"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//display images with transparancy invertionnaly proportional to last time of update |
||||||
|
// http://fabien.benetou.fr/MemoryRecalls/ImprovingPIM#VisualDecayOfInformation |
||||||
|
function DisplayDecay($pagename){ |
||||||
|
|
||||||
|
/* |
||||||
|
consider |
||||||
|
adding threshold |
||||||
|
not keeping it linear (e.g. log) |
||||||
|
but still constantly inscreasing between 0 and 1 |
||||||
|
use a factor when matches (e.g. regex changing $impeding_factor or $first_edit) |
||||||
|
regex would match groupname (e.g. "Person." with fast decay) or pagename or both (e.g. "Math" with slow decay) |
||||||
|
yellowish background, looking like old paper |
||||||
|
...rest got deleted by a dumb rm... |
||||||
|
*/ |
||||||
|
global $ScriptUrl; |
||||||
|
$first_edit = 1212192000; |
||||||
|
$now = time(); |
||||||
|
//load page |
||||||
|
$page = ReadPage($pagename); |
||||||
|
if (!$page) return; |
||||||
|
|
||||||
|
$last_edit = $page["time"]; |
||||||
|
//get last edit |
||||||
|
|
||||||
|
$destination_link = "$ScriptUrl/".strtr($pagename,".","/")."?action=edit"; |
||||||
|
|
||||||
|
//use the previous equation adding 1 - () |
||||||
|
$opacity = round ( 1 - ( (($now - $first_edit)-($now-$last_edit)) / ($now - $first_edit)) , 2 ); |
||||||
|
|
||||||
|
$opacitymsg = "opacity=$opacity"; |
||||||
|
if ($opacity > 0.8) |
||||||
|
$opacitymsg = "<font color=\"red\">".$opacitymsg."</font>"; |
||||||
|
|
||||||
|
//if user if admin |
||||||
|
if ( $GLOBALS['Author'] == 'Fabien' || $GLOBALS['Author'] == 'Utopiah' ) { |
||||||
|
//for 1 to a multiplier of value |
||||||
|
for ($i=0;$i<$opacity*10;$i++){ |
||||||
|
// display another visual problem with a link back to improvingwiki#visualdecay |
||||||
|
print "<div style=\"opacity:$opacity;position:absolute;top:".rand(60,800)."px;left:".rand(100,500)."px;\"><a href=\"$destination_link\">" |
||||||
|
.decbin(rand(0,10000))."</a></div>"; |
||||||
|
} |
||||||
|
// add a good practice msg |
||||||
|
print "<div style=\"opacity:$opacity;position:absolute;top:10px;left:450px;width:300px;background-color:gray;\"> |
||||||
|
$opacitymsg edits should be done to check if |
||||||
|
the informamtion presented is still relevant, |
||||||
|
links are working, |
||||||
|
opinion expressed still correct, etc. |
||||||
|
</div>"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//print img with opacity + warning message |
||||||
|
|
||||||
|
print "<div style=\"opacity:$opacity;\"><a name=\"Decay\"></a>If you can read this text ($opacitymsg) if means the page has not been edited for a long time. Consequently the information it holds might be deprecated or no longer represent the opinion of this author.</div>"; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,109 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
## give a visual representation of pages and group |
||||||
|
$RecipeInfo['WikiBrainMapping']['Version'] = '2011-05-15'; |
||||||
|
Markup('WikiBrainMapping', 'directives', '/\\(:WikiBrainMapping:\\)/e', Keep(WikiBrainMapping())); |
||||||
|
|
||||||
|
function WikiBrainMapping(){ |
||||||
|
$sourcepagename = $_SERVER["REQUEST_URI"]; |
||||||
|
// apply changes done to graphprocessing.php to insure proper URI format |
||||||
|
$sourcepagename = preg_replace("/(.*)\?.*/","$1",$sourcepagename); |
||||||
|
$sourcename = preg_replace("/.*[\.\/](.*)/","$1",$sourcepagename); |
||||||
|
$sourcegroup = preg_replace("/\/(.*)[\/\.].*/","$1",$sourcepagename); |
||||||
|
if ($sourcegroup == "/"){ |
||||||
|
$sourcegroup = "Main"; |
||||||
|
# consider instead filling the pages array with |
||||||
|
## groups names |
||||||
|
## "neighboors" wikis from InterWiki page |
||||||
|
# list page, remove pagenames, sort|uniq ... then what? maybe whole different process |
||||||
|
} |
||||||
|
|
||||||
|
global $FarmD, $WikiTitle, $ScriptUrl; |
||||||
|
$processingpath = '/pub/libraries/processing.js'; |
||||||
|
$processingfile = "/pub/visualization/wikibrainmapping.pjs"; |
||||||
|
$processinglib = "<script src=\"$processingpath\" type=\"text/javascript\"></script>"; |
||||||
|
|
||||||
|
# eventually modify to use a dedicated folder |
||||||
|
# generate a file per page |
||||||
|
if (!file_exists($FarmD.$processingfile)) |
||||||
|
if (!touch($FarmD.$processingfile)) |
||||||
|
print "Creation of the processing file fails, check write permissions for pmWiki and $processingfile."; |
||||||
|
|
||||||
|
# cached version (to comment during tests) |
||||||
|
#if ( (time() - filemtime($FarmD.$processingfile)) < 3600 ) return $processinglib.'<canvas data-src="'.$processingfile.'" width="'.$canvaswidth.'" height="'.$canvasheight.'"></canvas>'; |
||||||
|
|
||||||
|
$canvaswidth=500; |
||||||
|
$canvasheight=300; |
||||||
|
|
||||||
|
$groupname = $sourcegroup; |
||||||
|
$pages = ListPages("/$groupname\./e"); |
||||||
|
$pages = MatchPageNames($pages,array('-*.*RecentChanges,-*.GroupFooter,-*.GroupHeader')); |
||||||
|
$pagesnum = count($pages); |
||||||
|
$processingsetupcode = " |
||||||
|
PShape s; |
||||||
|
void setup(){ |
||||||
|
frameRate(15); |
||||||
|
size($canvaswidth,$canvasheight); |
||||||
|
strokeWeight(2); |
||||||
|
|
||||||
|
PFont font; |
||||||
|
font = loadFont(\"FFScala-32.vlw\"); |
||||||
|
textFont(font); |
||||||
|
|
||||||
|
sright = loadShape(\"/pub/illustrations/flat_brain_right.svg\"); |
||||||
|
sleft = loadShape(\"/pub/illustrations/flat_brain_left.svg\"); |
||||||
|
smooth(); |
||||||
|
"; |
||||||
|
$processingdrawcode .= " |
||||||
|
void draw(){ |
||||||
|
background(255); |
||||||
|
"; |
||||||
|
|
||||||
|
$processingdrawcode .= "shape(sright,300, 400);"; |
||||||
|
$processingdrawcode .= "shape(sleft,200, 400);"; |
||||||
|
$processingdrawcode .= "fill(0,0,255,255);\n"; |
||||||
|
$processingdrawcode .= "text(\"flattened left hemisphere\",300,10);\n;"; |
||||||
|
$processingdrawcode .= "text(\"flattened right hemisphere\",100,10);\n;"; |
||||||
|
|
||||||
|
$target_area["x"] = 150; |
||||||
|
$target_area["y"] = 100; |
||||||
|
$target_area["width"] = 50; |
||||||
|
$target_area["height"] = 60; |
||||||
|
|
||||||
|
//replace with actual list of pages |
||||||
|
for ($pagen=0;$pagen<10;$pagen++){ |
||||||
|
$x = rand($target_area["x"],$target_area["x"]+$target_area["width"]); |
||||||
|
$y = rand($target_area["y"],$target_area["y"]+$target_area["height"]); |
||||||
|
//draw cercle in the area |
||||||
|
$radius = 3; |
||||||
|
$processingdrawcode .= "fill(255,0,0,100);ellipse($x,$y,$radius,$radius);\n"; |
||||||
|
//draw diagonal line of edits |
||||||
|
$linelength=10; |
||||||
|
$processingdrawcode .= "strokeWeight(1); line($x,$y,$x+$linelength,$y-$linelength);\n"; |
||||||
|
//replace with actual list of edits |
||||||
|
$maxdiff = rand(0,10); |
||||||
|
for ($diff=0;$diff<$maxdiff;$diff++){ |
||||||
|
//draw points on the line of edits with smaller stroke weight |
||||||
|
$diff_pos = rand(0,$linelength); |
||||||
|
$processingdrawcode .= "strokeWeight(2); point($x+$diff_pos,$y-$diff_pos);\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
$processingdrawcode .= "fill(255,0,0,255);\n"; |
||||||
|
$processingdrawcode .= "text(\"Note that currently points are randomly generated\\nand randomly positionned on a designated area.\\nNo mapping has been done between function and position.\\nGyri and sulci are also not represented.\",10,200);\n;"; |
||||||
|
$processingsetupcode .= " }"; |
||||||
|
$processingdrawcode .= " }"; |
||||||
|
|
||||||
|
$result = $processinglib.'<canvas data-src="'.$processingfile.'" width="'.$canvaswidth.'" height="'.$canvasheight.'"></canvas>'; |
||||||
|
|
||||||
|
$write_result = file_put_contents($FarmD.$processingfile,$processingsetupcode.$processingdrawcode); |
||||||
|
if (!$write_result) |
||||||
|
if (strlen($processingcode)>0) |
||||||
|
print "Creation of the feed file fails, check write permissions for pmWiki and $processingfile."; |
||||||
|
else |
||||||
|
print "No code to generate, did you correctly generate your Processing code?"; |
||||||
|
|
||||||
|
// ----------------------- return the processed result ----------------------- |
||||||
|
return $result; |
||||||
|
} |
||||||
|
|
||||||
|
?> |
Loading…
Reference in new issue