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