Module:AspectCodesTagCloud

From semantic-mediawiki.org

Documentation for this module may be created at Module:AspectCodesTagCloud/doc

-- DEVELOPMENT!!!

local p = {}

function p.show(frame)
  if not mw.smw then
    return "mw.smw module not found"
  end

  local conferenceContributionsQuery = mw.smw.getQueryResult(" \
    [[HasConferenceContributionAspectCode::+]] \
    |?HasConferenceContributionAspectCode \
    |?HasConferenceContributionType \
    |?HasConferenceContributionStatus \
    |?HasConferenceContributionAuthorName \
    |?HasConferenceContributionScheduleDay \
    |?HasConferenceContributionStartTime \
    |?HasEntityTitle \
    |?HasEntityBlurb \
    |?HasEntityKeyword \
  ")
  if conferenceContributionsQuery == nil then
    return "(no values)"
  end

  if type( conferenceContributionsQuery ) == "table" then

    local conferenceContributions = {}
    for k,v in pairs( conferenceContributionsQuery.results ) do
      table.insert(conferenceContributions, {
        conferenceContribution = v.fulltext,
        properties = v.printouts
      } )
    end

    -- Sort by AspectCode
    conferenceContributionsByAspectCode = {}
    keywords = {}
    contributionTypes = {}
    scheduleDays = {}
    for k,v in pairs(conferenceContributions) do
      page = mw.title.new(v.conferenceContribution)
      if tableHasKey(conferenceContributionsByAspectCode, v.properties.HasConferenceContributionAspectCode[1].fulltext) then
        table.insert(conferenceContributionsByAspectCode[v.properties.HasConferenceContributionAspectCode[1].fulltext], {
          conferenceContribution = v.conferenceContribution,
          properties = v.properties,
          content = page:getContent()
      })
      else
        conferenceContributionsByAspectCode[v.properties.HasConferenceContributionAspectCode[1].fulltext] = {{
          conferenceContribution = v.conferenceContribution,
          properties = v.properties,
          content = page:getContent()
        }}
      end
      -- KEYWORDS
      for kwk, kwv in pairs(v.properties.HasEntityKeyword) do
        if tableHasKey(keywords, kwv) then
          keywords[kwv]["vol"] = keywords[kwv]["vol"] + 1
        else
          keywords[kwv] = { vol = 1 }
        end
      end
      -- CONTRIBUTION TYPES
      if tableHasKey(contributionTypes, v.properties.HasConferenceContributionType[1]) then
        contributionTypes[v.properties.HasConferenceContributionType[1]]["vol"] = contributionTypes[v.properties.HasConferenceContributionType[1]]["vol"] + 1
      else
        contributionTypes[v.properties.HasConferenceContributionType[1]] = { vol = 1 }
      end
      -- SCHEDULE DAYS
      if v.properties.HasConferenceContributionScheduleDay[1] then
        if tableHasKey(scheduleDays, v.properties.HasConferenceContributionScheduleDay[1].raw) then
          scheduleDays[string.sub(v.properties.HasConferenceContributionScheduleDay[1].raw, 3)]["vol"] = scheduleDays[string.sub(v.properties.HasConferenceContributionScheduleDay[1].raw, 3)]["vol"] + 1
        else
          scheduleDays[string.sub(v.properties.HasConferenceContributionScheduleDay[1].raw, 3)] = { vol = 1 }
        end
      end

    end

    aspectCodesData = getAspectCodesData()

    -- Assemble tag cloud
    tagCloud = {}
    maxContributions = getMaxContributions(conferenceContributionsByAspectCode)
    minContributions = getMinContributions(conferenceContributionsByAspectCode)
    maxFontSize = 60
    minFontSize = 20
    for k,v in pairs(conferenceContributionsByAspectCode) do
      contributionTitlesList = getContributionTitlesList(v)
      if aspectCodesData[k] then
        aspectCodeGroup = aspectCodesData[k][1].properties.HasAspectCodeGroup[1]
        aspectCodeTitle = aspectCodesData[k][1].properties.HasEntityTitle[1]
        if aspectCodesData[k][1].properties.HasEntityBlurb[1] then
          aspectCodeBlurb = aspectCodesData[k][1].properties.HasEntityBlurb[1]
        else
          aspectCodeBlurb = ""
        end
      else
        aspectCodeGroup = ""
        aspectCodeTitle = ""
        aspectCodeBlurb = ""
      end
      tooltip = mw.getCurrentFrame():preprocess( "{{#info: " .. aspectCodeBlurb .. " |note }}" )
      fontSize = minFontSize + ((table.getn(v) - minContributions) / (maxContributions - minContributions) * (maxFontSize - minFontSize))
      table.insert(tagCloud, "<div style=' \
background-color:" .. getBackgroundColorForAspectCodeGroup(aspectCodeGroup) .. "; \
margin:3px; \
padding:3px; \
display:inline; \
float:left; \
border-radius:5px; \
border:1px solid gray;'> \
<div style='font-size:14px;'>" .. aspectCodeGroup .. "</div> \
<div style='font-size:" .. fontSize .. "px;'>[[" .. k .. "|" .. aspectCodeTitle .. "]]" .. tooltip .. "</div> \
<div style='font-size:14px;'>" .. contributionTitlesList .. "</div> \
</div>")
    end

legend = "<div style=''><span style='background-color:#BDE4A7;'>PROMOTE/USE/MONITOR</span> | <span style='background-color:#B5C8F6;'>CONFIGURE/INTEGRATE</span> | <span style='background-color:#FFD57C;'>SETUP/DEVELOP/MAINTAIN</span> | <span style='border:1px solid gray;'>COMMUNITY</span></div>"

    if frame.args[1] == "cloud" then
      return "<div style='float:left;clear:right;border:1px solid gray;border-radius:2px;'>" .. legend .. "<hr>" .. table.concat(tagCloud, '&#32;') .. "</div>"
    else
--      return table_print(aspectCodesData)
--      return table_print(contributionTypes)
--      return table_print(conferenceContributionsByAspectCode)
      return aspectsMap(conferenceContributionsByAspectCode)
    end
  end

  return conferenceContributionsQuery
end

-- HELPER FUNCTIONS

function aspectsMap(conferenceContributionsByAspectCode)
  -- KEYWORDS
  keywordNounList = {}
  keywordVerbList = {}
  for kwk, kwv in pairsByKeys(keywords) do
    fontSize = 13 + ( kwv["vol"] * 2 )
    firstCharIsUppercase = string.match(kwk, '^%u')
    if firstCharIsUppercase == nil then
      table.insert(keywordVerbList, "<span class='keywordCheckbox' title='" .. kwk .. "'>❏</span>&nbsp;<i><span class='keyword' style='font-size:" .. fontSize .. "px;'>" .. kwk .. "</span></i><sup>" .. kwv["vol"] .. "</sup>")
    else
      table.insert(keywordNounList, "<span class='keywordCheckbox' title='" .. kwk .. "'>❏</span>&nbsp;<span class='keyword' style='font-size:" .. fontSize .. "px;'>" .. kwk .. "</span><sup>" .. kwv["vol"] .. "</sup>")
    end
  end
  -- CONTRIBUTION TYPES
  contributionTypeList = {}
  for ctk, ctv in pairsByKeys(contributionTypes) do
    table.insert(contributionTypeList, "<span class='contributionTypeCheckbox' title='" .. ctk .. "'>❏</span>&nbsp;<span class='contributionType'>" .. 
ctk .. "</span><sup>" .. ctv["vol"] .. "</sup>")
  end
  -- SCHEDULE DAYS
  scheduleDayList = {}
  for ctk, ctv in pairsByKeys(scheduleDays) do
    table.insert(scheduleDayList, "<span class='scheduleDayCheckbox' title='" .. ctk .. "'>❏</span>&nbsp;<span class='scheduleDay'>" .. 
ctk .. "</span><sup>" .. ctv["vol"] .. "</sup>")
  end
  mytable = {
    "<table class='aspectMapMainTable'>",
      "<tr><td colspan='3'><b>NOUN KEYWORDS:</b> " .. table.concat(keywordNounList, ", ") .. "</td></tr>",
      "<tr><td colspan='3'><b>VERB KEYWORDS:</b> " .. table.concat(keywordVerbList, ", ") .. "</td></tr>",
      "<tr><td colspan='3'><b>TYPES:</b> " .. table.concat(contributionTypeList, ", ") .. "</td></tr>",
      "<tr><td colspan='3'><b>DAYS:</b> " .. table.concat(scheduleDayList, ", ") .. "</td></tr>",
      "<tr class='groups'>",
        "<td style='width:33%;'><b>TOGGLE ALL:</b> <span class='toggleAll'>❏</span></td>",
        "<td style='width:33%;'>",
          "<div class='aspectCodeGroupTitle'>COMMUNITY</div>",
            getAspectCodeHTML("COM-0"),
            getAspectCodeHTML("COM-1"),
            getAspectCodeHTML("COM-2"),
        "</td>",
        "<td>",
          "<div class='aspectCodeGroupTitle'>COMMUNITY</div>",
            getAspectCodeHTML("COM-3"),
            getAspectCodeHTML("COM-4"),
            getAspectCodeHTML("COM-5"),
        "</td>",
      "</tr>",
      "<tr style='background-color:#bde4a7;'>",
        "<td><div class='aspectCodeGroupTitle'>Operations: PROMOTE</div>",
          getAspectCodeHTML("PR-0"),
          getAspectCodeHTML("PR-1"),
        "</td>",
        "<td><div class='aspectCodeGroupTitle'>Operations: USE</div>",
          getAspectCodeHTML("US-0"),
          getAspectCodeHTML("US-1"),
          getAspectCodeHTML("US-2"),
        "</td>",
        "<td><div class='aspectCodeGroupTitle'>Operations: MONITOR</div>",
          getAspectCodeHTML("MO-0"),
          getAspectCodeHTML("MO-1"),
        "</td>",
      "</tr>",
      "<tr>",
        "<td colspan=3>",
          "<table  class='aspectMapSubTable'>",
            "<tr style='background-color:#b5c8f6;'>",
              "<td style='width:50%;'><div class='aspectCodeGroupTitle'>Customization: CONFIGURE</div>",
                getAspectCodeHTML("CONF-0"),
                getAspectCodeHTML("CONF-1"),
                getAspectCodeHTML("CONF-2"),
              "</td>",
              "<td style='width:50%;'><div class='aspectCodeGroupTitle'>Customization: INTEGRATE</div>",
                getAspectCodeHTML("IN-0"),
                getAspectCodeHTML("IN-1"),
              "</td>",
            "</tr>",
          "</table>",
        "</td></tr>",
      "<tr style='background-color:#ffd57c;'>",
        "<td><div class='aspectCodeGroupTitle'>Infrastructure: SETUP</div>",
          getAspectCodeHTML("SE-0"),
          getAspectCodeHTML("SE-1"),
          getAspectCodeHTML("SE-2"),
        "</td><td><div class='aspectCodeGroupTitle'>Infrastructure: MAINTAIN</div>",
          getAspectCodeHTML("MA-0"),
          getAspectCodeHTML("MA-1"),
          getAspectCodeHTML("MA-2"),
        "</td><td><div class='aspectCodeGroupTitle'>Infrastructure: DEVELOP</div>",
          getAspectCodeHTML("DE-0"),
          getAspectCodeHTML("DE-1"),
          getAspectCodeHTML("DE-2"),
        "</td>",
      "</tr></table>"
    }
  return table.concat(mytable, '')
end

function getAspectCodeHTML(ac)
  if aspectCodesData[ac] then
    t = {
      "<div>",
        "<h4 class='aspectCodeCode'>" .. ac .. "&nbsp;<span class='aspectCodeTitle'>",
        aspectCodesData[ac][1].properties.HasEntityTitle[1] .. "</span> " .. getAspectCodeTooltip(ac) .. "</h4>",
        getContributionTitlesList(conferenceContributionsByAspectCode[ac]),
      "</div>"
    }
  else
    t = {}
  end
  return table.concat(t, '')
end

function table_print (tt, indent, done)
  done = done or {}
  indent = indent or 0
  if type(tt) == "table" then
    local sb = {}
    for key, value in pairs (tt) do
      table.insert(sb, string.rep (" ", indent)) -- indent it
      if type (value) == "table" and not done [value] then
        done [value] = true
        table.insert(sb, key .. " = {\n");
        table.insert(sb, table_print (value, indent + 2, done))
        table.insert(sb, string.rep (" ", indent)) -- indent it
        table.insert(sb, "}\n");
      elseif "number" == type(key) then
        table.insert(sb, string.format("\"%s\"\n", tostring(value)))
      else
        table.insert(sb, string.format(
            "%s = \"%s\"\n", tostring (key), tostring(value)))
       end
    end
    return table.concat(sb)
  else
    return tt .. "\n"
  end
end

function pairsByKeys(t, f)
  local a = {}
  for n in pairs(t) do a[#a + 1] = n end
  table.sort(a, f)
  local i = 0
  return function ()
    i = i + 1
    return a[i], t[a[i]]
  end
end

function to_string( tbl )
    if  "nil"       == type( tbl ) then
        return tostring(nil)
    elseif  "table" == type( tbl ) then
        return table_print(tbl)
    elseif  "string" == type( tbl ) then
        return tbl
    else
        return tostring(tbl)
    end
end

function tableHasKey(table,key)
    return table[key] ~= nil
end

function getMaxContributions(conferenceContributionsByAspectCode)
  -- Get max amount of contributions per aspect code
  max = 0
  for k,v in pairs(conferenceContributionsByAspectCode) do
    if table.getn(v) > max then
      max = table.getn(v)
    end
  end
  return max
end

function getMinContributions(aspectCodes)
  -- Get min amount of contributions per aspect code
  min = 0
  for k,v in pairs(aspectCodes) do
    if table.getn(v) < min then
      min = table.getn(v)
    elseif min == 0 then
      min = table.getn(v)
    end
  end
  return min
end

function getAspectCodesData()
  local aspectCodesDataQuery = mw.smw.getQueryResult(" \
    [[HasAspectCodeGroup::+]] \
    |?HasAspectCodeGroup \
    |?HasEntityTitle \
    |?HasEntityBlurb \
    |limit=50 \
  ")
  if aspectCodesDataQuery == nil then
    return "(no values)"
  end

  if type( aspectCodesDataQuery ) == "table" then
    aspectCodesData = {}
    for k,v in pairs( aspectCodesDataQuery.results ) do
      table.insert(aspectCodesData, {
        aspectCode = v.fulltext,
        properties = v.printouts
      } )
    end
  end

  -- Sort by AspectCode
  aspectCodes = {}
  for k,v in pairs(aspectCodesData) do
    if tableHasKey(aspectCodesData, v.aspectCode) then
      table.insert(aspectCodes[v.aspectCode], {
        properties = v.properties
    })
    else
      aspectCodes[v.aspectCode] = {{
        properties = v.properties
      }}
    end
  end

  return aspectCodes
end

function getBackgroundColorForAspectCodeGroup(aspectCode)
  green = { PROMOTE=true, USE=true, MONITOR=true }
  blue = { CONFIGURE=true, INTEGRATE=true }
  red = { SETUP=true, DEVELOP=true, MAINTAIN=true }
  if green[aspectCode] then
    return "#BDE4A7"
  elseif blue[aspectCode] then
    return "#B5C8F6"
  elseif red[aspectCode] then
    return "#FFD57C"
  else
    return "#E3EBEB"
  end
end

function getContributionTitlesList(conferenceContributions)
  if conferenceContributions == nil then
    return ""
  end
  ctl = {}
  for k,v in pairs(conferenceContributions) do
    if v.properties.HasEntityBlurb[1] then
      hasEntityBlurb = v.properties.HasEntityBlurb[1]
    else
      hasEntityBlurb = ""
    end
    if v.content[1] then
      volOfUpvotes = getVolOfUpvotes(v.content)
    else
      volOfUpvotes = 0
    end
    -- KEYWORDS
    theKeywords = {}
    if v.properties.HasEntityKeyword[1] then
      for kwk, kwv in pairs(v.properties.HasEntityKeyword) do
        table.insert(theKeywords, "<span class='keyword'>" .. kwv .. "</span>")
      end
    end
    -- AUTHORS
    theAuthors = {}
    if v.properties.HasConferenceContributionAuthorName[1] then
      for ak, av in pairs(v.properties.HasConferenceContributionAuthorName) do
        table.insert(theAuthors, "<span class='author'>[[" .. av.fulltext .. "]]</span>")
      end
    end
    -- DAYS
    if v.properties.HasConferenceContributionScheduleDay[1] then
      scheduleDay = string.sub(v.properties.HasConferenceContributionScheduleDay[1].raw, 3)
    else
      scheduleDay = ""
    end
    -- START TIME
    if v.properties.HasConferenceContributionStartTime[1] then
      startTime = v.properties.HasConferenceContributionStartTime[1]
    else
      startTime = ""
    end
    tooltip = mw.getCurrentFrame():preprocess( "{{#info: " .. hasEntityBlurb .. " |note }}" )
    table.insert(ctl, "<span class='contributionTitle'>[[" .. v.conferenceContribution .. "|" .. v.properties.HasEntityTitle[1] .. "]]</span> " .. tooltip .. " (<span class='contributionType'>" .. v.properties.HasConferenceContributionType[1] .. "</span>, " .. volOfUpvotes .. " upvotes)<br/>by " .. table.concat(theAuthors, "/") .. "<br/>" .. table.concat(theKeywords, " - ") .. "<br/><span class='scheduleDay'>" .. scheduleDay .. "</span> at " .. startTime)
  end
  return "<ul class='contributionTitlesList'><li class='contribution'>" .. table.concat(ctl, "</li><li class='contribution'>") .. "</li></ul>"
end

function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end

function getVolOfUpvotes(content)
  allUpvotes = split(content, "Upvotes")[2]
  if allUpvotes then
    volUpvotes = #split(allUpvotes, "*")
  else
    volUpvotes = 1
  end
  return volUpvotes - 1
end

function getAspectCodeTooltip(k)
  if aspectCodesData[k][1].properties.HasEntityBlurb[1] then
    aspectCodeBlurb = aspectCodesData[k][1].properties.HasEntityBlurb[1]
  else
    aspectCodeBlurb = ""
  end
  return mw.getCurrentFrame():preprocess( "{{#info: " .. aspectCodeBlurb .. " |note }}" )
end

return p