liquid_feedback_frontend
view env/util/initiative_pie.lua @ 1048:58d703bb06e4
Fixed HTML headers in layout files
| author | bsw | 
|---|---|
| date | Thu Jul 10 02:27:01 2014 +0200 (2014-07-10) | 
| parents | 701a5cf6b067 | 
| children | 6f3e01b266b3 | 
 line source
     1 function util.initiative_pie(initiative, d, gap)
     2   if not initiative.issue.closed or not initiative.admitted then
     3     return
     4   end
     6   if initiative.issue.voter_count == 0 or initiative.positive_votes == nil or initiative.negative_votes == nil then
     7     return
     8   end
    10   local first_preference_votes = initiative.first_preference_votes
    11   if first_preference_votes == nil then
    12     first_preference_votes = 0
    13   end
    15   local d = d or 100
    16   local gap = gap or d / 20
    18   local r = d/2
    19   local r_circle = r - gap
    21   local function circle(p)
    22     return
    23       gap + 2 * r_circle * ( 1 + math.sin( 2 * math.pi * p ) ) / 2,
    24       gap + 2 * r_circle * ( 1 - math.cos( 2 * math.pi * p ) ) / 2
    25   end
    27   local function getpath(start, stop)
    28     local start_x, start_y = circle(start)
    29     local stop_x, stop_y = circle(stop)
    30     local large = stop - start > 0.5 and "1" or "0"
    31     return "M" .. r .. "," .. r .. " "
    32         .. "L" .. start_x .. ",".. start_y .. " " .. " "
    33         .. "A" .. r_circle .. "," .. r_circle .. " 0 " .. large .. ",1 " .. stop_x .. "," .. stop_y .. " "
    34         .. "z"
    35   end
    37   local function uniPie(color, content)
    38     ui.tag {
    39       tag = "svg",
    40       attr = {
    41         class = "initiative_pie",
    42         width = d .. "px",
    43         height = d .. "px",
    44       },
    45       content = function ()
    46         ui.tag { tag = "circle", attr = {
    47           cx=r, cy=r, r=r_circle, fill = color, stroke = "#fff", ["stroke-width"] = "2"
    48         }, content = function () ui.tag { tag = "title", content = content } end  }
    49       end
    50     }
    51   end
    53   local function piePiece(path, fill, content)
    54     ui.tag {
    55       tag = "path",
    56       attr = {
    57         d = path,
    58         fill = fill,
    59         stroke = "#fff",
    60         ["stroke-width"] = "2",
    61         ["stroke-linecap"] = "butt"
    62       }, 
    63       content = function ()
    64         ui.tag {
    65           tag = "title", 
    66           content = content
    67         }
    68       end  
    69     }
    70   end
    72   local function pie(args)
    73     local offset = args.offset or 0
    74     local list = {}
    75     local sum = 0
    76     for i, element in ipairs(args) do
    77       element.start = sum + offset
    78       list[#list+1] = element
    79       sum = sum + element.value
    80     end
    82     for i, element in ipairs(list) do
    83       if element.value == sum then
    84         uniPie(element.fill, _(element.label, { count = element.value } ))
    85         return
    86       end
    87     end
    88     ui.tag {
    89       tag = "svg",
    90       attr = {
    91         class = "initiative_pie",
    92         width = d .. "px",
    93         height = d .. "px"
    94       },
    95       content = function ()
    96         table.sort(list, function (a, b)
    97           return a.value < b.value
    98         end )
    99         for i, element in ipairs(list) do
   100           local path = getpath(element.start / sum, (element.start + element.value) / sum)
   101           local content = _(element.label, { count = element.value })
   102           piePiece(path, element.fill, content)
   103         end
   104       end
   105     }
   106   end
   108   local yes1 = first_preference_votes
   109   local yes = initiative.positive_votes - first_preference_votes
   110   local neutral = initiative.issue.voter_count - initiative.positive_votes - initiative.negative_votes
   111   local no = initiative.negative_votes
   113   local sum = yes1 + yes + neutral + no
   115   local q = initiative.issue.policy.direct_majority_num / initiative.issue.policy.direct_majority_den
   118   local maxrot = sum * 7 / 12 - no
   120   local offset = 0
   122   if maxrot > 0 then
   123     offset = math.min (
   124       maxrot, 
   125       no * ( 1 / ( 1 / q - 1 ) -1 ) / 2
   126     )
   127   end
   129   pie{
   130     { value = yes1,    fill = "#0a0", label = _"#{count} Yes, first choice" },
   131     { value = yes,     fill = "#6c6", label = _"#{count} Yes, alternative choice" },
   132     { value = neutral, fill = "#ccc", label = _"#{count} Neutral" },
   133     { value = no,      fill = "#c00", label = _"#{count} No" },
   134     offset = - offset
   135   }
   137 end
