liquid_feedback_frontend
view env/util/initiative_pie.lua @ 1200:8e36f08eaac6
Added Moonbridge to about page
| author | bsw | 
|---|---|
| date | Tue Jun 23 19:57:10 2015 +0200 (2015-06-23) | 
| parents | 6f3e01b266b3 | 
| children | 32cc544d5a5b | 
 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
    12   local d = d or 100
    13   local gap = gap or d / 20
    15   local r = d/2
    16   local r_circle = r - gap
    18   local function circle(p)
    19     return
    20       gap + 2 * r_circle * ( 1 + math.sin( 2 * math.pi * p ) ) / 2,
    21       gap + 2 * r_circle * ( 1 - math.cos( 2 * math.pi * p ) ) / 2
    22   end
    24   local function getpath(start, stop)
    25     local start_x, start_y = circle(start)
    26     local stop_x, stop_y = circle(stop)
    27     local large = stop - start > 0.5 and "1" or "0"
    28     return "M" .. r .. "," .. r .. " "
    29         .. "L" .. start_x .. ",".. start_y .. " " .. " "
    30         .. "A" .. r_circle .. "," .. r_circle .. " 0 " .. large .. ",1 " .. stop_x .. "," .. stop_y .. " "
    31         .. "z"
    32   end
    34   local function uniPie(color, content)
    35     ui.tag {
    36       tag = "svg",
    37       attr = {
    38         class = "initiative_pie",
    39         width = d .. "px",
    40         height = d .. "px",
    41       },
    42       content = function ()
    43         ui.tag { tag = "circle", attr = {
    44           cx=r, cy=r, r=r_circle, fill = color, stroke = "#fff", ["stroke-width"] = "2"
    45         }, content = function () ui.tag { tag = "title", content = content } end  }
    46       end
    47     }
    48   end
    50   local function piePiece(path, fill, content)
    51     ui.tag {
    52       tag = "path",
    53       attr = {
    54         d = path,
    55         fill = fill,
    56         stroke = "#fff",
    57         ["stroke-width"] = "2",
    58         ["stroke-linecap"] = "butt"
    59       }, 
    60       content = function ()
    61         ui.tag {
    62           tag = "title", 
    63           content = content
    64         }
    65       end  
    66     }
    67   end
    69   local function pie(args)
    70     local offset = args.offset or 0
    71     local list = {}
    72     local sum = 0
    73     for i, element in ipairs(args) do
    74       element.start = sum + offset
    75       list[#list+1] = element
    76       sum = sum + element.value
    77     end
    79     for i, element in ipairs(list) do
    80       if element.value == sum then
    81         uniPie(element.fill, _(element.label, { count = element.value } ))
    82         return
    83       end
    84     end
    85     ui.tag {
    86       tag = "svg",
    87       attr = {
    88         class = "initiative_pie",
    89         width = d .. "px",
    90         height = d .. "px"
    91       },
    92       content = function ()
    93         table.sort(list, function (a, b)
    94           return a.value < b.value
    95         end )
    96         for i, element in ipairs(list) do
    97           local path = getpath(element.start / sum, (element.start + element.value) / sum)
    98           local content = _(element.label, { count = element.value })
    99           piePiece(path, element.fill, content)
   100         end
   101       end
   102     }
   103   end
   105   local yes1 = first_preference_votes
   106   local yes = initiative.positive_votes - first_preference_votes
   107   local neutral = initiative.issue.voter_count - initiative.positive_votes - initiative.negative_votes
   108   local no = initiative.negative_votes
   110   local sum = yes1 + yes + neutral + no
   112   local q = initiative.issue.policy.direct_majority_num / initiative.issue.policy.direct_majority_den
   115   local maxrot = sum * 7 / 12 - no
   117   local offset = 0
   119   if maxrot > 0 then
   120     offset = math.min (
   121       maxrot, 
   122       no * ( 1 / ( 1 / q - 1 ) -1 ) / 2
   123     )
   124   end
   126   pie{
   127     { value = yes1,    fill = "#0a0", label = _"#{count} Yes, first choice" },
   128     { value = yes,     fill = "#6c6", label = _"#{count} Yes, alternative choice" },
   129     { value = neutral, fill = "#ccc", label = _"#{count} Neutral" },
   130     { value = no,      fill = "#c00", label = _"#{count} No" },
   131     offset = - offset
   132   }
   134 end
