Adjucted sizes

Adjucted sizes

--
-- Copyright (C) 2017 DBot
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

PPM2.MIN_WEIGHT = 0.7
PPM2.MAX_WEIGHT = 1.3

PPM2.MIN_SCALE = 0.5
PPM2.MAX_SCALE = 1.3

PPM2.PONY_HEIGHT_MODIFIER = 0.64
PPM2.PONY_HEIGHT_MODIFIER_DUCK = 1.12

PPM2.PLAYER_VOFFSET = 64 * PPM2.PONY_HEIGHT_MODIFIER
PPM2.PLAYER_VOFFSET_DUCK = 28 * PPM2.PONY_HEIGHT_MODIFIER_DUCK

PPM2.PLAYER_VIEW_OFFSET = Vector(0, 0, PPM2.PLAYER_VOFFSET)
PPM2.PLAYER_VIEW_OFFSET_DUCK = Vector(0, 0, PPM2.PLAYER_VOFFSET_DUCK)

PPM2.PLAYER_VIEW_OFFSET_ORIGINAL = Vector(0, 0, 64)
PPM2.PLAYER_VIEW_OFFSET_DUCK_ORIGINAL = Vector(0, 0, 28)

PPM2.MIN_TAIL_SIZE = 0.6
PPM2.MAX_TAIL_SIZE = 1.7 -- i luv big tails

PPM2.MIN_IRIS = 0.4
PPM2.MAX_IRIS = 1.3

PPM2.MIN_HOLE = 0.1
PPM2.MAX_HOLE = .95

PPM2.MIN_HOLE_SHIFT = -0.5
PPM2.MAX_HOLE_SHIFT = 0.5

PPM2.MIN_PUPIL_SIZE = 0.2
PPM2.MAX_PUPIL_SIZE = 1

PPM2.MIN_EYE_ROTATION = -180
PPM2.MAX_EYE_ROTATION = 180

PPM2.AvaliableTails = {
    'MAILCALL'
    'FLOOFEH'
    'ADVENTUROUS'
    'SHOWBOAT'
    'ASSERTIVE'
    'BOLD'
    'STUMPY'
    'SPEEDSTER'
    'EDGY'
    'RADICAL'
    'BOOKWORM'
    'BUMPKIN'
    'POOFEH'
    'CURLY'
    'NONE'
}

PPM2.AvaliableUpperManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR', 'NONE'
}

PPM2.AvaliableLowerManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY', 'NONE'
}

PPM2.EyelashTypes = {
    'Default', 'Double', 'Coy', 'Full', 'Mess', 'None'
}

PPM2.BodyDetails = {
    'None', 'Leg gradient', 'Lines', 'Stripes', 'Head stripes'
    'Freckles', 'Hooves big', 'Hooves small', 'Head layer'
    'Hooves big rnd', 'Hooves small rnd', 'Spots 1', 'Robotic'
}

PPM2.BodyDetailsEnum = {
    'NONE', 'GRADIENT', 'LINES', 'STRIPES', 'HSTRIPES'
    'FRECKLES', 'HOOF_BIG', 'HOOF_SMALL', 'LAYER'
    'HOOF_BIG_ROUND', 'HOOF_SMALL_ROUND', 'SPOTS', 'ROBOTIC'
}

PPM2.SocksTypes = {
    'DEFAULT'
    'GEOMETRIC1'
    'GEOMETRIC2'
    'GEOMETRIC3'
    'GEOMETRIC4'
    'GEOMETRIC5'
    'GEOMETRIC6'
    'GEOMETRIC7'
    'GEOMETRIC8'
    'DARK1'
    'FLOWERS10'
    'FLOWERS11'
    'FLOWERS12'
    'FLOWERS13'
    'FLOWERS14'
    'FLOWERS15'
    'FLOWERS16'
    'FLOWERS17'
    'FLOWERS18'
    'FLOWERS19'
    'FLOWERS2'
    'FLOWERS20'
    'FLOWERS3'
    'FLOWERS4'
    'FLOWERS5'
    'FLOWERS6'
    'FLOWERS7'
    'FLOWERS8'
    'FLOWERS9'
    'GREY1'
    'GREY2'
    'GREY3'
    'HEARTS1'
    'HEARTS2'
    'SNOW1'
    'WALLPAPER1'
    'WALLPAPER2'
    'WALLPAPER3'
}

PPM2.DefaultCutiemarks = {
    '8ball', 'dice', 'magichat',
    'magichat02', 'record', 'microphone',
    'bits', 'checkered', 'lumps',
    'mirror', 'camera', 'magnifier',
    'padlock', 'binaryfile', 'floppydisk',
    'cube', 'bulb', 'battery',
    'deskfan', 'flames', 'alarm',
    'myon', 'beer', 'berryglass',
    'roadsign', 'greentree', 'seasons',
    'palette', 'palette02', 'palette03',
    'lightningstone', 'partiallycloudy', 'thunderstorm',
    'storm', 'stoppedwatch', 'twistedclock',
    'surfboard', 'surfboard02', 'star',
    'ussr', 'vault', 'anarchy',
    'suit', 'deathscythe', 'shoop',
    'smiley', 'dawsome', 'weegee'
    'applej', 'applem', 'bon_bon', 'carrots', 'celestia', 'cloudy', 'custom01', 'custom02', 'derpy', 'firezap',
    'fluttershy', 'fruits', 'island', 'lyra', 'mine', 'note', 'octavia', 'pankk', 'pinkie_pie', 'rainbow_dash',
    'rarity', 'rosen', 'sflowers', 'storm', 'time', 'time2', 'trixie', 'twilight', 'waters', 'weer', 'zecora'
}

PPM2.AvaliableUpperManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR', 'NONE'
}

PPM2.AvaliableLowerManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY', 'NONE'
}

PPM2.AvaliableTailsNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'SPEEDSTER', 'EDGY'
    'RADICAL', 'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'NONE'
}

PPM2.AvaliableEyeTypes = {
    'DEFAULT', 'APERTURE'
}

PPM2.AvaliablePonyWings = {'DEFAULT', 'BATPONY'}

PPM2.AvaliablePonySuits = {'NONE', 'ROYAL_GUARD', 'SHADOWBOLTS_FULL', 'SHADOWBOLTS_LIGHT', 'WONDERBOLTS_FULL', 'WONDERBOLTS_LIGHT'}

do
    i = -1
    for mark in *PPM2.DefaultCutiemarks
        i += 1
        PPM2["CMARK_#{mark\upper()}"] = i

PPM2.MIN_EYELASHES = 0
PPM2.MAX_EYELASHES = #PPM2.EyelashTypes - 1
PPM2.EYELASHES_NONE = #PPM2.EyelashTypes - 1

PPM2.MIN_TAILS = 0
PPM2.MAX_TAILS = #PPM2.AvaliableTails - 1

PPM2.MIN_TAILS_NEW = 0
PPM2.MAX_TAILS_NEW = #PPM2.AvaliableTailsNew - 1

PPM2.MIN_UPPER_MANES = 0
PPM2.MAX_UPPER_MANES = #PPM2.AvaliableUpperManes - 1

PPM2.MIN_LOWER_MANES = 0
PPM2.MAX_LOWER_MANES = #PPM2.AvaliableLowerManes - 1

PPM2.MIN_UPPER_MANES_NEW = 0
PPM2.MAX_UPPER_MANES_NEW = #PPM2.AvaliableUpperManesNew - 1

PPM2.MIN_LOWER_MANES_NEW = 0
PPM2.MAX_LOWER_MANES_NEW = #PPM2.AvaliableLowerManesNew - 1

PPM2.MIN_EYE_TYPE = 0
PPM2.MAX_EYE_TYPE = #PPM2.AvaliableEyeTypes - 1

PPM2.MIN_DETAIL = 0
PPM2.MAX_DETAIL = #PPM2.BodyDetails - 1

PPM2.MIN_CMARK = 0
PPM2.MAX_CMARK = #PPM2.DefaultCutiemarks - 1

PPM2.MIN_SUIT = 0
PPM2.MAX_SUIT = #PPM2.AvaliablePonySuits - 1

PPM2.MIN_WINGS = 0
PPM2.MAX_WINGS = #PPM2.AvaliablePonyWings - 1

PPM2.MIN_SOCKS = 0
PPM2.MAX_SOCKS = #PPM2.SocksTypes - 1

PPM2.GENDER_FEMALE = 0
PPM2.GENDER_MALE = 1

PPM2.MAX_BODY_DETAILS = 8

PPM2.RACE_EARTH = 0
PPM2.RACE_PEGASUS = 1
PPM2.RACE_UNICORN = 2
PPM2.RACE_ALICORN = 3
PPM2.RACE_ENUMS = {'EARTH', 'PEGASUS', 'UNICORN', 'ALICORN'}

PPM2.AGE_FILLY = 0
PPM2.AGE_ADULT = 1
PPM2.AGE_MATURE = 2
PPM2.AGE_ENUMS = {'FILLY', 'ADULT', 'MATURE'}

PPM2.MIN_DERP_STRENGTH = 0.1
PPM2.MAX_DERP_STRENGTH = 1.3

PPM2.MIN_MALE_BUFF = 0
PPM2.DEFAULT_MALE_BUFF = 1
PPM2.MAX_MALE_BUFF = 2

--
-- Copyright (C) 2017 DBot
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

PPM2.MIN_WEIGHT = 0.7
PPM2.MAX_WEIGHT = 1.3

PPM2.MIN_SCALE = 0.6
PPM2.MAX_SCALE = 1.2

PPM2.PONY_HEIGHT_MODIFIER = 0.64
PPM2.PONY_HEIGHT_MODIFIER_DUCK = 1.12

PPM2.PLAYER_VOFFSET = 64 * PPM2.PONY_HEIGHT_MODIFIER
PPM2.PLAYER_VOFFSET_DUCK = 28 * PPM2.PONY_HEIGHT_MODIFIER_DUCK

PPM2.PLAYER_VIEW_OFFSET = Vector(0, 0, PPM2.PLAYER_VOFFSET)
PPM2.PLAYER_VIEW_OFFSET_DUCK = Vector(0, 0, PPM2.PLAYER_VOFFSET_DUCK)

PPM2.PLAYER_VIEW_OFFSET_ORIGINAL = Vector(0, 0, 64)
PPM2.PLAYER_VIEW_OFFSET_DUCK_ORIGINAL = Vector(0, 0, 28)

PPM2.MIN_TAIL_SIZE = 0.6
PPM2.MAX_TAIL_SIZE = 1.7 -- i luv big tails

PPM2.MIN_IRIS = 0.4
PPM2.MAX_IRIS = 1.3

PPM2.MIN_HOLE = 0.1
PPM2.MAX_HOLE = .95

PPM2.MIN_HOLE_SHIFT = -0.5
PPM2.MAX_HOLE_SHIFT = 0.5

PPM2.MIN_PUPIL_SIZE = 0.2
PPM2.MAX_PUPIL_SIZE = 1

PPM2.MIN_EYE_ROTATION = -180
PPM2.MAX_EYE_ROTATION = 180

PPM2.AvaliableTails = {
    'MAILCALL'
    'FLOOFEH'
    'ADVENTUROUS'
    'SHOWBOAT'
    'ASSERTIVE'
    'BOLD'
    'STUMPY'
    'SPEEDSTER'
    'EDGY'
    'RADICAL'
    'BOOKWORM'
    'BUMPKIN'
    'POOFEH'
    'CURLY'
    'NONE'
}

PPM2.AvaliableUpperManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR', 'NONE'
}

PPM2.AvaliableLowerManes = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY', 'NONE'
}

PPM2.EyelashTypes = {
    'Default', 'Double', 'Coy', 'Full', 'Mess', 'None'
}

PPM2.BodyDetails = {
    'None', 'Leg gradient', 'Lines', 'Stripes', 'Head stripes'
    'Freckles', 'Hooves big', 'Hooves small', 'Head layer'
    'Hooves big rnd', 'Hooves small rnd', 'Spots 1', 'Robotic'
}

PPM2.BodyDetailsEnum = {
    'NONE', 'GRADIENT', 'LINES', 'STRIPES', 'HSTRIPES'
    'FRECKLES', 'HOOF_BIG', 'HOOF_SMALL', 'LAYER'
    'HOOF_BIG_ROUND', 'HOOF_SMALL_ROUND', 'SPOTS', 'ROBOTIC'
}

PPM2.SocksTypes = {
    'DEFAULT'
    'GEOMETRIC1'
    'GEOMETRIC2'
    'GEOMETRIC3'
    'GEOMETRIC4'
    'GEOMETRIC5'
    'GEOMETRIC6'
    'GEOMETRIC7'
    'GEOMETRIC8'
    'DARK1'
    'FLOWERS10'
    'FLOWERS11'
    'FLOWERS12'
    'FLOWERS13'
    'FLOWERS14'
    'FLOWERS15'
    'FLOWERS16'
    'FLOWERS17'
    'FLOWERS18'
    'FLOWERS19'
    'FLOWERS2'
    'FLOWERS20'
    'FLOWERS3'
    'FLOWERS4'
    'FLOWERS5'
    'FLOWERS6'
    'FLOWERS7'
    'FLOWERS8'
    'FLOWERS9'
    'GREY1'
    'GREY2'
    'GREY3'
    'HEARTS1'
    'HEARTS2'
    'SNOW1'
    'WALLPAPER1'
    'WALLPAPER2'
    'WALLPAPER3'
}

PPM2.DefaultCutiemarks = {
    '8ball', 'dice', 'magichat',
    'magichat02', 'record', 'microphone',
    'bits', 'checkered', 'lumps',
    'mirror', 'camera', 'magnifier',
    'padlock', 'binaryfile', 'floppydisk',
    'cube', 'bulb', 'battery',
    'deskfan', 'flames', 'alarm',
    'myon', 'beer', 'berryglass',
    'roadsign', 'greentree', 'seasons',
    'palette', 'palette02', 'palette03',
    'lightningstone', 'partiallycloudy', 'thunderstorm',
    'storm', 'stoppedwatch', 'twistedclock',
    'surfboard', 'surfboard02', 'star',
    'ussr', 'vault', 'anarchy',
    'suit', 'deathscythe', 'shoop',
    'smiley', 'dawsome', 'weegee'
    'applej', 'applem', 'bon_bon', 'carrots', 'celestia', 'cloudy', 'custom01', 'custom02', 'derpy', 'firezap',
    'fluttershy', 'fruits', 'island', 'lyra', 'mine', 'note', 'octavia', 'pankk', 'pinkie_pie', 'rainbow_dash',
    'rarity', 'rosen', 'sflowers', 'storm', 'time', 'time2', 'trixie', 'twilight', 'waters', 'weer', 'zecora'
}

PPM2.AvaliableUpperManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT', 'ASSERTIVE'
    'BOLD', 'STUMPY', 'SPEEDSTER', 'RADICAL', 'SPIKED'
    'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'INSTRUCTOR', 'NONE'
}

PPM2.AvaliableLowerManesNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'HIPPIE', 'SPEEDSTER'
    'BOOKWORM', 'BUMPKIN', 'CURLY', 'NONE'
}

PPM2.AvaliableTailsNew = {
    'MAILCALL', 'FLOOFEH', 'ADVENTUROUS', 'SHOWBOAT'
    'ASSERTIVE', 'BOLD', 'STUMPY', 'SPEEDSTER', 'EDGY'
    'RADICAL', 'BOOKWORM', 'BUMPKIN', 'POOFEH', 'CURLY', 'NONE'
}

PPM2.AvaliableEyeTypes = {
    'DEFAULT', 'APERTURE'
}

PPM2.AvaliablePonyWings = {'DEFAULT', 'BATPONY'}

PPM2.AvaliablePonySuits = {'NONE', 'ROYAL_GUARD', 'SHADOWBOLTS_FULL', 'SHADOWBOLTS_LIGHT', 'WONDERBOLTS_FULL', 'WONDERBOLTS_LIGHT'}

do
    i = -1
    for mark in *PPM2.DefaultCutiemarks
        i += 1
        PPM2["CMARK_#{mark\upper()}"] = i

PPM2.MIN_EYELASHES = 0
PPM2.MAX_EYELASHES = #PPM2.EyelashTypes - 1
PPM2.EYELASHES_NONE = #PPM2.EyelashTypes - 1

PPM2.MIN_TAILS = 0
PPM2.MAX_TAILS = #PPM2.AvaliableTails - 1

PPM2.MIN_TAILS_NEW = 0
PPM2.MAX_TAILS_NEW = #PPM2.AvaliableTailsNew - 1

PPM2.MIN_UPPER_MANES = 0
PPM2.MAX_UPPER_MANES = #PPM2.AvaliableUpperManes - 1

PPM2.MIN_LOWER_MANES = 0
PPM2.MAX_LOWER_MANES = #PPM2.AvaliableLowerManes - 1

PPM2.MIN_UPPER_MANES_NEW = 0
PPM2.MAX_UPPER_MANES_NEW = #PPM2.AvaliableUpperManesNew - 1

PPM2.MIN_LOWER_MANES_NEW = 0
PPM2.MAX_LOWER_MANES_NEW = #PPM2.AvaliableLowerManesNew - 1

PPM2.MIN_EYE_TYPE = 0
PPM2.MAX_EYE_TYPE = #PPM2.AvaliableEyeTypes - 1

PPM2.MIN_DETAIL = 0
PPM2.MAX_DETAIL = #PPM2.BodyDetails - 1

PPM2.MIN_CMARK = 0
PPM2.MAX_CMARK = #PPM2.DefaultCutiemarks - 1

PPM2.MIN_SUIT = 0
PPM2.MAX_SUIT = #PPM2.AvaliablePonySuits - 1

PPM2.MIN_WINGS = 0
PPM2.MAX_WINGS = #PPM2.AvaliablePonyWings - 1

PPM2.MIN_SOCKS = 0
PPM2.MAX_SOCKS = #PPM2.SocksTypes - 1

PPM2.GENDER_FEMALE = 0
PPM2.GENDER_MALE = 1

PPM2.MAX_BODY_DETAILS = 8

PPM2.RACE_EARTH = 0
PPM2.RACE_PEGASUS = 1
PPM2.RACE_UNICORN = 2
PPM2.RACE_ALICORN = 3
PPM2.RACE_ENUMS = {'EARTH', 'PEGASUS', 'UNICORN', 'ALICORN'}

PPM2.AGE_FILLY = 0
PPM2.AGE_ADULT = 1
PPM2.AGE_MATURE = 2
PPM2.AGE_ENUMS = {'FILLY', 'ADULT', 'MATURE'}

PPM2.MIN_DERP_STRENGTH = 0.1
PPM2.MAX_DERP_STRENGTH = 1.3

PPM2.MIN_MALE_BUFF = 0
PPM2.DEFAULT_MALE_BUFF = 1
PPM2.MAX_MALE_BUFF = 2


close #27 @window -> @area in window elements

import graphics, mouse from love
import insert, remove from table
import sub, len from string

path = sub ..., 1, len(...) - len "/window"
element = require "#{path}/element"
box = require "#{path}/box"
text = require "#{path}/text"

closeImage = graphics.newImage "#{path}/img/close.png"

-- version compatibility
left = 1                -- what is the left mouse button?
mousemoved_event = true -- is the mousemoved event available?

do
    major, minor, revision = love.getVersion!
    if (major == 0) and (minor == 10) and ((revision == 0) or (revision == 1))
        left = 1 -- redundant, but whatever
    elseif (major == 0) and (minor == 9)
        left = "l"
        if revision == 1
            mousemoved_event = false
    else
        print "elements/window: unrecognized LOVE version: #{major}.#{minor}.#{revision}"
        print "                 assuming LOVE version > 0.10.1  (there may be bugs)"

pop_ref = false -- reference to pop, loaded by pop.load!

class window extends element
    load: (pop) ->
        pop_ref = pop

    new: (parent, title="window", tBackground={25, 180, 230, 255}, tColor={255, 255, 255, 255}, wBackground={200, 200, 210, 255}) =>
        super parent

        -- NOTE @title having @head as its parent might break things horribly
        @head = box @, tBackground         -- title box at top
        @title = text @head, title, tColor -- text at top
        @area = box @, wBackground       -- main window area
        @close = box @, closeImage         -- close button

        -- correct placement / sizes of elements
        height = @title\getHeight!
        @head\setSize @w - height, height
        @area\move nil, height
        @close\align("right")\setSize height, height
        @setSize 100, 80

        -- our child elements are still child elements
        --TODO change title to be a child of head ?
        @child = {
            @head, @title, @area, @close
        }

        @titleOverflow = "trunicate" -- defaults to trunicating title to fit in window

        -- window area steals mouse events to keep them from propagating under it
        @area.mousepressed = ->
            return true
        @area.clicked = ->
            return true

        @close.clicked = ->
            @delete!
            return true

        @head.selected = false -- whether or not the window title (and thus, the window) has been selected

        if mousemoved_event
            @head.mousemoved = (x, y, dx, dy) =>
                if @selected
                    @parent\move dx, dy
                    return true
                return false

            @head.mousepressed = (x, y, button) =>
                if button == left
                    @selected = true
                    return true
                return false

        else
            @head.mx = 0           -- local mouse coordinates when selected
            @head.my = 0

            @head.update = =>
                x, y = mouse.getPosition!
                @setPosition x - mx, y - my
                --return false -- why?

            @head.mousepressed = (x, y, button) =>
                if button == left
                    @selected = true
                    @mx = x
                    @my = y
                    return true
                return false

        @head.mousereleased = (x, y, button) =>
            if button == left
                @selected = false
                pop_ref.focused = false -- clear our focus
                return true
            return false

    debugDraw: =>
        graphics.setLineWidth 0.5
        graphics.setColor 0, 0, 0, 100
        graphics.rectangle "fill", @x, @y, @w, @h
        graphics.setColor 200, 0, 200, 200
        graphics.rectangle "line", @x, @y, @w, @h
        graphics.setColor 255, 200, 255, 255
        graphics.print "w", @x, @y

        return @

    addChild: (child) =>
        @area\addChild child

        return @

    -- pass through to window, but return us if window returns itself
    removeChild: (child) =>
        result = @area\removeChild child
        if result == @area
            return @
        elseif type(result) == "string"
            for k,v in ipairs @child
                if v == child
                    remove @child, k
                    return @
            return "Element \"#{child}\" is not a child of window \"#{@}\". Cannot remove it."
        else
            return result

    getChildren: =>
        return @area.child

    align: (horizontal, vertical, toPixel) =>
        super horizontal, vertical, toPixel

        for i = 1, #@child
            @child[i]\align!

        @area\move nil, @head\getHeight!

        return @

    setSize: (w, h) =>
        x = 0
        y = 0

        if w
            switch @horizontal
                when "center"
                    x -= (w - @w)/2
                when "right"
                    x -= w - @w

            if @close
                @head\setWidth w - @head\getHeight!
            else
                @head\setWidth w

            @area\setWidth w
            @w = w
            @x += x

            @title\align!

            if @close
                @close\align!

        if h
            h = h - @head\getHeight!
            switch @vertical
                when "center"
                    y -= (h - @h)/2
                when "right"
                    y -= h - @h

            @area\setHeight h
            @h = h + @head\getHeight!
            @y += y

        @head\move x, y
        --@title\move x, y
        @area\move x, y

        return @

    setWidth: (w) =>
        x = 0

        switch @horizontal
            when "center"
                x -= (w - @w)/2
            when "right"
                x -= w - @w

        if @close
            @head\setWidth w - @head\getHeight!
        else
            @head\setWidth w

        @area\setWidth w
        @w = w
        @x += x

        @title\align!

        if @close
            @close\align!

        @head\move x
        --@title\move x
        @area\move x

        return @

    setHeight: (h) =>
        y = 0

        h = h - @head\getHeight!
        switch @vertical
            when "center"
                y -= (h - @h)/2
            when "right"
                y -= h - @h

        @area\setHeight h
        @h = h + @head\getHeight!
        @y += y

        @head\move nil, y
        @title\move nil, y
        @area\move nil, y

        return @

    setTitle: (title) =>
        @title\setText title

        if @titleOverflow == "trunicate"
            while @title\getWidth! > @head\getWidth!
                title = title\sub 1, -3
                @title\setText title .. "…"

        elseif @titleOverflow == "resize"
            if @title\getWidth! > @head\getWidth!
                @setWidth @title\getWidth!

        return @

    getTitle: =>
        return @title\getText!

    setTitleOverflow: (method) =>
        @titleOverflow = method

        return @

    getTitleOverflow: =>
        return @titleOverflow

    setClose: (enabled) =>
        if enabled
            @close = box @, closeImage
            @close.clicked = ->
                @delete!
                return true
            height = @head\getHeight!
            @close\align("right")\setSize height, height
            @head\setWidth @w - height
            @title\align!
            insert @child, @close
        else
            @close\delete!
            @head\setWidth @w
            @title\align!
            @close = false

        return @

    hasClose: =>
        if @close
            return true
        else
            return false

import graphics, mouse from love
import insert, remove from table
import sub, len from string

path = sub ..., 1, len(...) - len "/window"
element = require "#{path}/element"
box = require "#{path}/box"
text = require "#{path}/text"

closeImage = graphics.newImage "#{path}/img/close.png"

-- version compatibility
left = 1                -- what is the left mouse button?
mousemoved_event = true -- is the mousemoved event available?

do
    major, minor, revision = love.getVersion!
    if (major == 0) and (minor == 10) and ((revision == 0) or (revision == 1))
        left = 1 -- redundant, but whatever
    elseif (major == 0) and (minor == 9)
        left = "l"
        if revision == 1
            mousemoved_event = false
    else
        print "elements/window: unrecognized LOVE version: #{major}.#{minor}.#{revision}"
        print "                 assuming LOVE version > 0.10.1  (there may be bugs)"

pop_ref = false -- reference to pop, loaded by pop.load!

class window extends element
    load: (pop) ->
        pop_ref = pop

    new: (parent, title="window", tBackground={25, 180, 230, 255}, tColor={255, 255, 255, 255}, wBackground={200, 200, 210, 255}) =>
        super parent

        -- NOTE @title having @head as its parent might break things horribly
        @head = box @, tBackground         -- title box at top
        @title = text @head, title, tColor -- text at top
        @window = box @, wBackground       -- main window area
        @close = box @, closeImage         -- close button

        -- correct placement / sizes of elements
        height = @title\getHeight!
        @head\setSize @w - height, height
        @window\move nil, height
        @close\align("right")\setSize height, height
        @setSize 100, 80

        -- our child elements are still child elements
        --TODO change title to be a child of head ?
        @child = {
            @head, @title, @window, @close
        }

        @titleOverflow = "trunicate" -- defaults to trunicating title to fit in window

        -- window area steals mouse events to keep them from propagating under it
        @window.mousepressed = ->
            return true
        @window.clicked = ->
            return true

        @close.clicked = ->
            @delete!
            return true

        @head.selected = false -- whether or not the window title (and thus, the window) has been selected

        if mousemoved_event
            @head.mousemoved = (x, y, dx, dy) =>
                if @selected
                    @parent\move dx, dy
                    return true
                return false

            @head.mousepressed = (x, y, button) =>
                if button == left
                    @selected = true
                    return true
                return false

        else
            @head.mx = 0           -- local mouse coordinates when selected
            @head.my = 0

            @head.update = =>
                x, y = mouse.getPosition!
                @setPosition x - mx, y - my
                --return false -- why?

            @head.mousepressed = (x, y, button) =>
                if button == left
                    @selected = true
                    @mx = x
                    @my = y
                    return true
                return false

        @head.mousereleased = (x, y, button) =>
            if button == left
                @selected = false
                pop_ref.focused = false -- clear our focus
                return true
            return false

    debugDraw: =>
        graphics.setLineWidth 0.5
        graphics.setColor 0, 0, 0, 100
        graphics.rectangle "fill", @x, @y, @w, @h
        graphics.setColor 200, 0, 200, 200
        graphics.rectangle "line", @x, @y, @w, @h
        graphics.setColor 255, 200, 255, 255
        graphics.print "w", @x, @y

        return @

    addChild: (child) =>
        @window\addChild child

        return @

    -- pass through to window, but return us if window returns itself
    removeChild: (child) =>
        result = @window\removeChild child
        if result == @window
            return @
        elseif type(result) == "string"
            for k,v in ipairs @child
                if v == child
                    remove @child, k
                    return @
            return "Element \"#{child}\" is not a child of window \"#{@}\". Cannot remove it."
        else
            return result

    getChildren: =>
        return @window.child

    align: (horizontal, vertical, toPixel) =>
        super horizontal, vertical, toPixel

        for i = 1, #@child
            @child[i]\align!

        @window\move nil, @head\getHeight!

        return @

    setSize: (w, h) =>
        x = 0
        y = 0

        if w
            switch @horizontal
                when "center"
                    x -= (w - @w)/2
                when "right"
                    x -= w - @w

            if @close
                @head\setWidth w - @head\getHeight!
            else
                @head\setWidth w

            @window\setWidth w
            @w = w
            @x += x

            @title\align!

            if @close
                @close\align!

        if h
            h = h - @head\getHeight!
            switch @vertical
                when "center"
                    y -= (h - @h)/2
                when "right"
                    y -= h - @h

            @window\setHeight h
            @h = h + @head\getHeight!
            @y += y

        @head\move x, y
        --@title\move x, y
        @window\move x, y

        return @

    setWidth: (w) =>
        x = 0

        switch @horizontal
            when "center"
                x -= (w - @w)/2
            when "right"
                x -= w - @w

        if @close
            @head\setWidth w - @head\getHeight!
        else
            @head\setWidth w

        @window\setWidth w
        @w = w
        @x += x

        @title\align!

        if @close
            @close\align!

        @head\move x
        --@title\move x
        @window\move x

        return @

    setHeight: (h) =>
        y = 0

        h = h - @head\getHeight!
        switch @vertical
            when "center"
                y -= (h - @h)/2
            when "right"
                y -= h - @h

        @window\setHeight h
        @h = h + @head\getHeight!
        @y += y

        @head\move nil, y
        @title\move nil, y
        @window\move nil, y

        return @

    setTitle: (title) =>
        @title\setText title

        if @titleOverflow == "trunicate"
            while @title\getWidth! > @head\getWidth!
                title = title\sub 1, -3
                @title\setText title .. "…"

        elseif @titleOverflow == "resize"
            if @title\getWidth! > @head\getWidth!
                @setWidth @title\getWidth!

        return @

    getTitle: =>
        return @title\getText!

    setTitleOverflow: (method) =>
        @titleOverflow = method

        return @

    getTitleOverflow: =>
        return @titleOverflow

    setClose: (enabled) =>
        if enabled
            @close = box @, closeImage
            @close.clicked = ->
                @delete!
                return true
            height = @head\getHeight!
            @close\align("right")\setSize height, height
            @head\setWidth @w - height
            @title\align!
            insert @child, @close
        else
            @close\delete!
            @head\setWidth @w
            @title\align!
            @close = false

        return @

    hasClose: =>
        if @close
            return true
        else
            return false


revert to current screen if the referenced one does not exist

require 'moonscript'

import floor from math
import match from string
screen = require 'mjolnir.screen'
window = require 'mjolnir.window'

round = (num) -> floor(num + 0.5)

find_windows = (appname) ->
  [win for win in *window.allwindows() when match(win\application!\title!, appname) != nil]

maximize = (win=window.focusedwindow!) -> win\maximize!
push_left_half = (win=window.focusedwindow!) -> win\movetounit({x: 0.0, y: 0.0, w: 0.5, h: 1.0})
push_right_half = (win=window.focusedwindow!) -> win\movetounit({x: 0.5, y: 0.0, w: 0.5, h: 1.0})

push_toscreen = (win, scr) ->
  win = win or window.focusedwindow!
  s = if type(scr) == 'number' then screen.allscreens![scr] else scr
  s = s or win\screen!
  id = win\id!

  fullscreen_change = win\isfullscreen! and s != win\screen!
  if fullscreen_change then
    win\setfullscreen(false)
    os.execute('sleep 3')
    win = window.windowforid(id)

  screenframe_old = win\screen!\frame!
  screenframe_new = s\frame!
  topleft = win\topleft!
  topleft = {
    x: topleft.x - screenframe_old.x + screenframe_new.x,
    y: topleft.y - screenframe_old.y + screenframe_new.y
  }

  win\settopleft(topleft)

  if fullscreen_change then win\setfullscreen(true)

push_nextscreen = (win=window.focusedwindow!) -> push_toscreen(win, win\screen!\next!)
push_prevscreen = (win=window.focusedwindow!) -> push_toscreen(win, win\screen!\previous!)

{
  :round, :find_windows,
  :maximize, :push_left_half, :push_right_half,
  :push_nextscreen, :push_prevscreen, :push_toscreen
}

require 'moonscript'

import floor from math
import match from string
screen = require 'mjolnir.screen'
window = require 'mjolnir.window'

round = (num) -> floor(num + 0.5)

find_windows = (appname) ->
  [win for win in *window.allwindows() when match(win\application!\title!, appname) != nil]

maximize = (win=window.focusedwindow!) -> win\maximize!
push_left_half = (win=window.focusedwindow!) -> win\movetounit({x: 0.0, y: 0.0, w: 0.5, h: 1.0})
push_right_half = (win=window.focusedwindow!) -> win\movetounit({x: 0.5, y: 0.0, w: 0.5, h: 1.0})

push_toscreen = (win, scr) ->
  win = win or window.focusedwindow!
  s = if type(scr) == 'number' then screen.allscreens![scr] else scr
  id = win\id!

  fullscreen_change = win\isfullscreen! and s != win\screen!
  if fullscreen_change then
    win\setfullscreen(false)
    os.execute('sleep 3')
    win = window.windowforid(id)

  screenframe_old = win\screen!\frame!
  screenframe_new = s\frame!
  topleft = win\topleft!
  topleft = {
    x: topleft.x - screenframe_old.x + screenframe_new.x,
    y: topleft.y - screenframe_old.y + screenframe_new.y
  }

  win\settopleft(topleft)

  if fullscreen_change then win\setfullscreen(true)

push_nextscreen = (win=window.focusedwindow!) -> push_toscreen(win, win\screen!\next!)
push_prevscreen = (win=window.focusedwindow!) -> push_toscreen(win, win\screen!\previous!)

{
  :round, :find_windows,
  :maximize, :push_left_half, :push_right_half,
  :push_nextscreen, :push_prevscreen, :push_toscreen
}


svada: fix typo

svada: fix typo

Former-commit-id: 696a7cb1f37756670f7b23585346abe72d8fd871 [formerly 94aa4cf6b3276ea4ec78815b0263031dbd5143cd]
Former-commit-id: 1dcea4fafffc03533f2b0c4aeb07d6117374ef3d

-- svadagenerator.no/data/svadagenerator.csv

svada = {
  {"Gitt","en integrert","målsetting","synliggjøres","potensialet","innenfor rammen av","en samlet vurdering"},
  {"Under hensyntagen til","en optimal","effekt","tas det høyde for","risikofaktorene","som en følge av","forholdene"},
  {"I lys av","en sømløs","struktur","iverksettes","fokus","for så vidt gjelder","konseptet"},
  {"Vedrørende","en implisitt","agenda","identifiseres","synergieffekten","med henblikk på","ressurssituasjonen"},
  {"Grunnet","en proaktiv","tidshorisont","initieres","incitamentet","i forhold til","tilgjengeliggjøringen"},
  {"I betraktning av","en betydelig","overveielse","lokaliseres","forankringen","hva angår","føringene"},
  {"Forutsatt","en økt","mobilitet","kommuniseres","insentivene","parallelt med","evalueringen"},
  {"Med utgangspunkt i","en vesentlig","treffsikkerhet","styrkes","innsatsen","i relasjon til","implementeringen"},
  {"I forhold til","en ikke ubetydelig","innsats","realiseres","erfaringsutvekslingen","i tilknytning til","kjernevirksomheten"},
  {"Sett hen til","en kostnadseffektiv","kvalitetssikring","effektueres","informasjonsflyten","på bakgrunn av","visjonen"},
  {"I henhold til","en avtagende","problematikk","forankres","kriteriene","avhengig av","satsingsområdet"},
  {"Med tanke på","en vedvarende","ressursbruk","maksimeres","strategien","hva gjelder","problemstillingen"},
  {"Uavhengig av","en tiltagende","avveining","konkretiseres","økningen","eller sagt på en annen måte:","beskaffenheten"},
  {"Sett på bakgrunn av","en gjeldende","avklaring","tilgjengeliggjøres","egenarten","på samme måte som","vesentligheten"},
  {"Sammenholdt med","en helhetlig","implementering","utvides","tilstedeværelsen","i motsetning til","egenarten"},
  {"På grunn av","en manglende","styringsinnsats","dokumenteres","oppfølgingen","innenfor","målområdet"},
  {"Med hensyn til","en særlig","innovasjon","spores","resultatene","i tillegg til","verdiene"},
  {"Under forutsetning av","en løpende","effektivisering","innhentes","kunnskapene","gjennom","realitetsorienteringen"},
  {"Etter en totalvurdering av","en langsiktig","kvalitetsheving","revitaliseres","betydningen","ut fra","resultatoppnåelsen"},
  {"Uten hensyn til","en bærekraftig","utvikling","stabiliseres","kompetansehevingen","med sikte på","behovene"},
  {"Avhengig av","en resultatorientert","måloppnåelse","genereres","instrumentet","på tvers av","løsningen"},
  {"På grunnlag av","en tverrfaglig","oppgaveløsning","stimuleres","scenarioet","på linje med","parametrene"},
  {"I og med","en kommunikativ","arbeidsmodell","balanseres","spisskompetansen","utenom","ressursinnsatsen"},
  {"Under henvisning til","en inkluderende","organisasjon","ivaretas","relasjonene","i forlengelsen av","konsekvensaspektet"},
  {"Gitt","en plutselig","fornyelse","omfattes","fornyelsen","innenfor rammen av","oppgjøret"},
  {"Under hensyntagen til","en uforutsett","risikovurdering","utstedes","forsikringsbehovet","som en følge av","husstanden"},
  {"I lys av","en erstatningsmessig","forsikringstaker","iverksettes","vilkårene","under forutsetning av","årsakssammenhengen"},
  {"Vedrørende","en kollektiv","egenandel","anvendes","oppsigelsen","med henblikk på","betingelsene"},
  {"Grunnet","en indirekte","tariff","kommuniseres","angrefristen","i forhold til","opplysningsplikten"},
  {"I betraktning av","en skadevoldende","sikkerhetsforskrift","Innebæres","tegningstidspunktet","hva angår","behovsgjennomgangen"},
  {"Forutsatt","en særskilt","regress","tegnes","oppgjørsreglene","parallelt med","evalueringen"},
  {"Med utgangspunkt i","en ansvarsbegrensende","reassuranse","styrkes","klagenemden","i relasjon til","utredningsforløpet"},
  {"I forhold til","en inntruffet","utløpsdato","realiseres","vilkårstolkningen","i tilknytning til","kjernevirksomheten"},
  {"Sett hen til","en forholdsmessig","begunstigelse","baseres","løsøre","på bakgrunn av","visjonen"},
  {"I henhold til","en avvikende","helseerklæring","forankres","personopplysningene","avhengig av","satsingsområdet"},
  {"Med tanke på","en prosentvis","dekningsgrad","optimaliseres","konsekvensendringen","hva gjelder","porteføljen"},
  {"Uavhengig av","en juridisk","samlefaktura","konkretiseres","sviket","eller sagt på en annen måte:","lønnsomhetsmodellene"},
  {"Sett på bakgrunn av","en årlig","premie","meldes","flytteretten","på samme måte som","distribusjonskanalene"},
  {"Sammenholdt med","en ervervsmessig","indeksjustering","utvides","erstatningsansvaret","i motsetning til","avkortningen"},
  {"På grunn av","en bindende","rabatt","dokumenteres","segmentene","innenfor","takstmennene"},
  {"Med hensyn til","en prosessorientert","forutsetning","utredes","skadeskjemaene","i tillegg til","kjerneverdiene"},
  {"Under forutsetning av","en systemmessig","panthaver","innhentes","forsikrede","gjennom","skadeprosenten"},
  {"Etter en totalvurdering av","en skriftlig","sikkerhetsrabatt","ivaretas","premieberegningsgrunnlaget","ut fra","tilleggsdekningen"},
  {"Uten hensyn til","en tilpasningsdyktig","skjønnsvurdering","utløses","bonusbestemmelsene","med sikte på","bransjestandarden"},
  {"Avhengig av","en sesongvariert","skadetakst","stabiliseres","hovedforfallet","på tvers av","løsningssporet"},
  {"På grunnlag av","en gjennomsnittlig","bygningsdel","påvirkes","rammebetingelsene","på linje med","tariffparametrene"},
  {"I og med","en skademessig","forsikringstaker","avtales","unntaksreglene","utenom","markedsandelene"},
  {"Under henvisning til","en trendsettende","purrerutine","synliggjøres","kompensasjonen","i forlengelsen av","konsekvensaspektet"},
  {"Under henvisning til","en effektbasert","avdelingskultur","realiseres","sluttilstanden","utenom","operasjonen"},
  {"På grunnlag av","en operativ","doktrine","omsettes","hensikten","i forlengelsen av","kommandonivået"},
  {"Med bakgrunn i","en fellesoperativ","kommando","implementeres","virkefeltet","innenfor","kampanjeplanen"},
  {"Gitt","en militærstrategisk","operasjonsdimensjon","reflekteres","samvirket","i utnyttelsen av","profesjonen"},
  {"Avhengig av","en taktisk","manøver","utvikles","kommandokjeden","ut fra","forsvarsgrenen"},
  {"Sett i lys av","en stridsteknisk","samhandling","kjennetegnes","avskrekkingseffekten","ut over","våpengrenen"},
  {"Uten hensyn til","en dynamisk","konflikt","sammenfattes","synergieffekten","på tvers av","alliansen"},
  {"I og med","en konvensjonell","krigføring","iverksettes","friksjonen","i tilknytning til","kjerneverdiene"},
  {"Etter en totalvurdering av","en ukonvensjonell","maktbruk","avgjøres","planverket","i forbindelse med","konseptutviklingen"},
  {"Under analysen av","en fredsbevarende","styrkemultiplikator","tilpasses","styrkebidraget","med hensyn til ","militærmakten"},
  {"I kontrollen av","en tverrsektoriell","interoperabilitet","operasjonaliseres","virkemiddelet","gjennom","krigens natur"},
  {"I arbeidet med","en overordnet","konfliktintensitet","påvirkes","lendevurderingen","med basis i ","handlingsrommet"},
  {"Under forutsetning av","en nødvendig","konflikthåndtering","identifiseres","fiendevurderingen","til støtte for","deployeringen"},
  {"Sammenholdt med","en offensiv","avskrekking","organiseres","stridsfeltet","ved bruk av","operasjonsområdet"},
  {"Sett hen til","en defensiv","myndighetsutøvelse","fastsettes","evnen","på linje med","styrkedisponeringen"},
  {"Etter etablering av","en desentralisert","prosessavhengighet","styrkes","stridsevnen","parallellt med","langtidsplanen"},
  {"Grunnet","en oppdragsbasert","beredskap","koordineres","innsatsmidlet","i relasjon til","sikkerhetspolitikken"},
  {"Vedrørende","en maritim","kraftsamling","bevisstgjøres","situasjonsforståelsen","i forhold til ","oppdragsorganiseringen"},
  {"Forutsatt","en spesialisert","ressursbruk","forsterkes","schwerpunktet","i motsetning til","totalforsvaret"},
  {"Etter planlegging av","en indirekte","beslutningsevne","fokuseres","trusselbildet","i tillegg til","feltfunksjonen"},
  {"Ved bruk av","en sentralisert","handlekraft","samordnes","uttaket","innenfor rammen av","brigadestrukturen"},
  {"Gitt","en forskningsbasert","målsetting","synliggjøres","forebyggingspotensialet","innenfor rammen av","sykehussammenslåingen"},
  {"Under hensyntagen til","en optimal","detaljering","overstyres","helserisikoen","som en følge av","DRG-produksjonen"},
  {"I lys av","en sømløs","struktur","iverksettes","helseministerens standpunkt","for så vidt gjelder","rehabiliteringsprosjekt"},
  {"Vedrørende","en pasientorientert","agenda","identifiseres","samhandlingsarenaene","med henblikk på","styringsmodellen"},
  {"Grunnet","en proaktiv","tidshorisont","initieres","brukerrepresentasjonen","i forhold til","leveransekonsept"},
  {"I betraktning av","en betydelig","optimalisering","lokaliseres","kunnskapsforankringen","hva angår","IA-arbeidet"},
  {"Forutsatt","en tverrfaglig","mobilitet","kommuniseres","statsekretærens vurdering","parallelt med","nasjonale helsemål"},
  {"Med utgangspunkt i","en vesentlig","treffsikkerhet","styrkes","HR-direktørens beslutning","i relasjon til","turnusforskriften"},
  {"I forhold til","en helsepolitisk","innsats","realiseres","brukertilfredsheten","i tilknytning til","utfordringsrommet"},
  {"Sett hen til","en kostnadseffektiv","kvalitetssikring","effektueres","helseinformasjonsflyten","på bakgrunn av","helsevisjonene"},
  {"I henhold til","en avtagende","problematikk","forankres","samhandlingspotensialet","avhengig av","rekrutteringsutfordringene"},
  {"Med tanke på","en vedvarende","ressursbruk","maksimeres","økonomisjefens målhorisont","hva gjelder","feilbehandlingen"},
  {"Uavhengig av","en tiltagende","omstilling","konkretiseres","sykehusdirektørens visjon","koordinert med","tilsynsrapporten"},
  {"Sett på bakgrunn av","en helsefaglig","avklaring","tilgjengeliggjøres","helsegevinsten","på samme måte som","omstillingsprosessen"},
  {"Sammenholdt med","en helhetlig","implementering","utvides","helseutfordringene","i motsetning til","leveransekonseptet"},
  {"På grunn av","en manglende","styringsinnsats","dokumenteres","helseproduksjonen","innenfor","innsatsfokuseringen"},
  {"Med hensyn til","en særlig","innovasjon","spores","fastlegenes produksjonsevne","i tillegg til","helseforetaket"},
  {"Under forutsetning av","en løpende","forventningsjustering","innhentes","rehabiliteringspotensialet","gjennom","ventelisteskandalene"},
  {"Etter en totalvurdering av","en langsiktig","orientering","adresseres","samhandlingskompetansen","ut fra","tjenesteintegreringen"},
  {"Uten hensyn til","en bærekraftig","utvikling","stabiliseres","forsvarlighetskravene","med sikte på","kjernevirksomheten"},
  {"Avhengig av","en resultatorientert","målhorisont","genereres","samhandlingskoordineringen","på tvers av","pasientsskadeerstatningen"},
  {"På grunnlag av","en tverrfaglig","arena","stimuleres","avviksmeldingene","på linje med","kvalitetsarbeidet"},
  {"I og med","en kunnskapsbasert","synergi","balanseres","fagkoordineringen","utenom","systemsvikten"},
  {"Under henvisning til","en inkluderende","avstemning","ivaretas","helseproblematikken","i forlengelsen av","helsereformene"},
  {"Gitt","en representativ","beskrivelse","dokumenteres","visualiseringen","innenfor rammen av","kommunepolitikken"},
  {"I lys av","en implisitt","gjengivelse","ivaretas","byggesøknaden","i motsetning til","samordningsplikten"},
  {"Med bakgrunn i","en konkret","søknad","utredes","materialiteten","i tillegg til","saksbehandlingstiden"},
  {"I forhold til","en feilaktig","skjemautfylling","fastslås","beskaffenheten","gjennom","tiltakshaveren"},
  {"Sett hen til","en faktisk","råderett","meldes","kontrollerklæringen","parallelt med","dispensasjonssøknaden"},
  {"I og med","en nødvendig","nabovarsling","konkluderes","søknadsprosessen","for så vidt gjelder","reguleringsplanen"},
  {"Ifølge","en transparent","klagebehandling","betviles","vedtaksbegrunnelsen","på basis av","kartgrunnlaget"},
  {"Sammenliknet med","en langsiktig","saksbehandling","oppleves","forføyningen","innenfor","hjemmelsgrunnlaget"},
  {"Ut fra","en bærekraftig","samhandling","betraktes","gjennomføringsplanen","i forhold til","planvedtaket"},
  {"Uavhengig av","en representativ","prosessavklaring","estimeres","ansvarsbelegningen","med henblikk på","ansvarsretten"},
  {"Basert på","en kvalitativ","konkretisering","bedømmes","tiltaket","ved hjelp av","prosjekteringen"},
  {"Vedrørende","en søknadspliktig","innvilgelse","anbefales","igangsettingstillatelsen","på linje med","planforslaget"},
  {"Under henvisning til","en klanderverdig","kvalitetsbedømming","forhåndsvurderes","ferdigattesten","på tvers av","grunnboken"},
  {"Grunnet","en arkitekturbasert","ulempebetraktning","avklares","kvaliteten","knyttet til","planbestemmelsen"},
  {"Tatt i betraktning","en systematisk","tillatelse","preaksepteres","dispensasjonen","som en følge av","arealbruken"},
  {"Forutsatt","(en ressursmessig)","realitetsbehandling","fastsettes","samsvarserklæringen","begrunnet i","statlig arealplan"},
  {"Uten hensyn til","en vesentlig","arealoverføring","forankres","oppføringen","i kraft av","tomtefestelova"},
  {"Med sikte på","en midlertidig","godkjennelse","utløses","rammetillatelsen","på tross av","strandsonen"},
  {"Sett ut fra","en kvalifisert","omregulering","samordnes","fasadeendringen","i relasjon til","ansvarsretten"},
  {"Med grunnlag i","en frittliggende","rammetillatelse","vurderes","terrenginngrepet","i overensstemmelse med","tvingende sikkerhetshensyn"},
}

PRIVMSG:
  '^%psvada$': (s, d, a) =>
    words = {}
    wordN = 1
    for i=1,7 do
      line = svada[math.random(1, #svada)]
      word = line[wordN]
      table.insert(words, word)
      wordN = wordN + 1

    say table.concat(words, ' ')

-- svadagenerator.no/data/svadagenerator.csv

svada = {
  {"Gitt","en integrert","målsetting","synliggjøres","potensialet","innenfor rammen av","en samlet vurdering"},
  {"Under hensyntagen til","en optimal","effekt","tas det høyde for","risikofaktorene","som en følge av","forholdene"},
  {"I lys av","en sømløs","struktur","iverksettes","fokus","for så vidt gjelder","konseptet"},
  {"Vedrørende","en implisitt","agenda","identifiseres","synergieffekten","med henblikk på","ressurssituasjonen"},
  {"Grunnet","en proaktiv","tidshorisont","initieres","incitamentet","i forhold til","tilgjengeliggjøringen"},
  {"I betraktning av","en betydelig","overveielse","lokaliseres","forankringen","hva angår","føringene"},
  {"Forutsatt","en økt","mobilitet","kommuniseres","insentivene","parallelt med","evalueringen"},
  {"Med utgangspunkt i","en vesentlig","treffsikkerhet","styrkes","innsatsen","i relasjon til","implementeringen"},
  {"I forhold til","en ikke ubetydelig","innsats","realiseres","erfaringsutvekslingen","i tilknytning til","kjernevirksomheten"},
  {"Sett hen til","en kostnadseffektiv","kvalitetssikring","effektueres","informasjonsflyten","på bakgrunn av","visjonen"},
  {"I henhold til","en avtagende","problematikk","forankres","kriteriene","avhengig av","satsingsområdet"},
  {"Med tanke på","en vedvarende","ressursbruk","maksimeres","strategien","hva gjelder","problemstillingen"},
  {"Uavhengig av","en tiltagende","avveining","konkretiseres","økningen","eller sagt på en annen måte:","beskaffenheten"},
  {"Sett på bakgrunn av","en gjeldende","avklaring","tilgjengeliggjøres","egenarten","på samme måte som","vesentligheten"},
  {"Sammenholdt med","en helhetlig","implementering","utvides","tilstedeværelsen","i motsetning til","egenarten"},
  {"På grunn av","en manglende","styringsinnsats","dokumenteres","oppfølgingen","innenfor","målområdet"},
  {"Med hensyn til","en særlig","innovasjon","spores","resultatene","i tillegg til","verdiene"},
  {"Under forutsetning av","en løpende","effektivisering","innhentes","kunnskapene","gjennom","realitetsorienteringen"},
  {"Etter en totalvurdering av","en langsiktig","kvalitetsheving","revitaliseres","betydningen","ut fra","resultatoppnåelsen"},
  {"Uten hensyn til","en bærekraftig","utvikling","stabiliseres","kompetansehevingen","med sikte på","behovene"},
  {"Avhengig av","en resultatorientert","måloppnåelse","genereres","instrumentet","på tvers av","løsningen"},
  {"På grunnlag av","en tverrfaglig","oppgaveløsning","stimuleres","scenarioet","på linje med","parametrene"},
  {"I og med","en kommunikativ","arbeidsmodell","balanseres","spisskompetansen","utenom","ressursinnsatsen"},
  {"Under henvisning til","en inkluderende","organisasjon","ivaretas","relasjonene","i forlengelsen av","konsekvensaspektet"},
  {"Gitt","en plutselig","fornyelse","omfattes","fornyelsen","innenfor rammen av","oppgjøret"},
  {"Under hensyntagen til","en uforutsett","risikovurdering","utstedes","forsikringsbehovet","som en følge av","husstanden"},
  {"I lys av","en erstatningsmessig","forsikringstaker","iverksettes","vilkårene","under forutsetning av","årsakssammenhengen"},
  {"Vedrørende","en kollektiv","egenandel","anvendes","oppsigelsen","med henblikk på","betingelsene"},
  {"Grunnet","en indirekte","tariff","kommuniseres","angrefristen","i forhold til","opplysningsplikten"},
  {"I betraktning av","en skadevoldende","sikkerhetsforskrift","Innebæres","tegningstidspunktet","hva angår","behovsgjennomgangen"},
  {"Forutsatt","en særskilt","regress","tegnes","oppgjørsreglene","parallelt med","evalueringen"},
  {"Med utgangspunkt i","en ansvarsbegrensende","reassuranse","styrkes","klagenemden","i relasjon til","utredningsforløpet"},
  {"I forhold til","en inntruffet","utløpsdato","realiseres","vilkårstolkningen","i tilknytning til","kjernevirksomheten"},
  {"Sett hen til","en forholdsmessig","begunstigelse","baseres","løsøre","på bakgrunn av","visjonen"},
  {"I henhold til","en avvikende","helseerklæring","forankres","personopplysningene","avhengig av","satsingsområdet"},
  {"Med tanke på","en prosentvis","dekningsgrad","optimaliseres","konsekvensendringen","hva gjelder","porteføljen"},
  {"Uavhengig av","en juridisk","samlefaktura","konkretiseres","sviket","eller sagt på en annen måte:","lønnsomhetsmodellene"},
  {"Sett på bakgrunn av","en årlig","premie","meldes","flytteretten","på samme måte som","distribusjonskanalene"},
  {"Sammenholdt med","en ervervsmessig","indeksjustering","utvides","erstatningsansvaret","i motsetning til","avkortningen"},
  {"På grunn av","en bindende","rabatt","dokumenteres","segmentene","innenfor","takstmennene"},
  {"Med hensyn til","en prosessorientert","forutsetning","utredes","skadeskjemaene","i tillegg til","kjerneverdiene"},
  {"Under forutsetning av","en systemmessig","panthaver","innhentes","forsikrede","gjennom","skadeprosenten"},
  {"Etter en totalvurdering av","en skriftlig","sikkerhetsrabatt","ivaretas","premieberegningsgrunnlaget","ut fra","tilleggsdekningen"},
  {"Uten hensyn til","en tilpasningsdyktig","skjønnsvurdering","utløses","bonusbestemmelsene","med sikte på","bransjestandarden"},
  {"Avhengig av","en sesongvariert","skadetakst","stabiliseres","hovedforfallet","på tvers av","løsningssporet"},
  {"På grunnlag av","en gjennomsnittlig","bygningsdel","påvirkes","rammebetingelsene","på linje med","tariffparametrene"},
  {"I og med","en skademessig","forsikringstaker","avtales","unntaksreglene","utenom","markedsandelene"},
  {"Under henvisning til","en trendsettende","purrerutine","synliggjøres","kompensasjonen","i forlengelsen av","konsekvensaspektet"},
  {"Under henvisning til","en effektbasert","avdelingskultur","realiseres","sluttilstanden","utenom","operasjonen"},
  {"På grunnlag av","en operativ","doktrine","omsettes","hensikten","i forlengelsen av","kommandonivået"},
  {"Med bakrunn i","en fellesoperativ","kommando","implementeres","virkefeltet","innenfor","kampanjeplanen"},
  {"Gitt","en militærstrategisk","operasjonsdimensjon","reflekteres","samvirket","i utnyttelsen av","profesjonen"},
  {"Avhengig av","en taktisk","manøver","utvikles","kommandokjeden","ut fra","forsvarsgrenen"},
  {"Sett i lys av","en stridsteknisk","samhandling","kjennetegnes","avskrekkingseffekten","ut over","våpengrenen"},
  {"Uten hensyn til","en dynamisk","konflikt","sammenfattes","synergieffekten","på tvers av","alliansen"},
  {"I og med","en konvensjonell","krigføring","iverksettes","friksjonen","i tilknytning til","kjerneverdiene"},
  {"Etter en totalvurdering av","en ukonvensjonell","maktbruk","avgjøres","planverket","i forbindelse med","konseptutviklingen"},
  {"Under analysen av","en fredsbevarende","styrkemultiplikator","tilpasses","styrkebidraget","med hensyn til ","militærmakten"},
  {"I kontrollen av","en tverrsektoriell","interoperabilitet","operasjonaliseres","virkemiddelet","gjennom","krigens natur"},
  {"I arbeidet med","en overordnet","konfliktintensitet","påvirkes","lendevurderingen","med basis i ","handlingsrommet"},
  {"Under forutsetning av","en nødvendig","konflikthåndtering","identifiseres","fiendevurderingen","til støtte for","deployeringen"},
  {"Sammenholdt med","en offensiv","avskrekking","organiseres","stridsfeltet","ved bruk av","operasjonsområdet"},
  {"Sett hen til","en defensiv","myndighetsutøvelse","fastsettes","evnen","på linje med","styrkedisponeringen"},
  {"Etter etablering av","en desentralisert","prosessavhengighet","styrkes","stridsevnen","parallellt med","langtidsplanen"},
  {"Grunnet","en oppdragsbasert","beredskap","koordineres","innsatsmidlet","i relasjon til","sikkerhetspolitikken"},
  {"Vedrørende","en maritim","kraftsamling","bevisstgjøres","situasjonsforståelsen","i forhold til ","oppdragsorganiseringen"},
  {"Forutsatt","en spesialisert","ressursbruk","forsterkes","schwerpunktet","i motsetning til","totalforsvaret"},
  {"Etter planlegging av","en indirekte","beslutningsevne","fokuseres","trusselbildet","i tillegg til","feltfunksjonen"},
  {"Ved bruk av","en sentralisert","handlekraft","samordnes","uttaket","innenfor rammen av","brigadestrukturen"},
  {"Gitt","en forskningsbasert","målsetting","synliggjøres","forebyggingspotensialet","innenfor rammen av","sykehussammenslåingen"},
  {"Under hensyntagen til","en optimal","detaljering","overstyres","helserisikoen","som en følge av","DRG-produksjonen"},
  {"I lys av","en sømløs","struktur","iverksettes","helseministerens standpunkt","for så vidt gjelder","rehabiliteringsprosjekt"},
  {"Vedrørende","en pasientorientert","agenda","identifiseres","samhandlingsarenaene","med henblikk på","styringsmodellen"},
  {"Grunnet","en proaktiv","tidshorisont","initieres","brukerrepresentasjonen","i forhold til","leveransekonsept"},
  {"I betraktning av","en betydelig","optimalisering","lokaliseres","kunnskapsforankringen","hva angår","IA-arbeidet"},
  {"Forutsatt","en tverrfaglig","mobilitet","kommuniseres","statsekretærens vurdering","parallelt med","nasjonale helsemål"},
  {"Med utgangspunkt i","en vesentlig","treffsikkerhet","styrkes","HR-direktørens beslutning","i relasjon til","turnusforskriften"},
  {"I forhold til","en helsepolitisk","innsats","realiseres","brukertilfredsheten","i tilknytning til","utfordringsrommet"},
  {"Sett hen til","en kostnadseffektiv","kvalitetssikring","effektueres","helseinformasjonsflyten","på bakgrunn av","helsevisjonene"},
  {"I henhold til","en avtagende","problematikk","forankres","samhandlingspotensialet","avhengig av","rekrutteringsutfordringene"},
  {"Med tanke på","en vedvarende","ressursbruk","maksimeres","økonomisjefens målhorisont","hva gjelder","feilbehandlingen"},
  {"Uavhengig av","en tiltagende","omstilling","konkretiseres","sykehusdirektørens visjon","koordinert med","tilsynsrapporten"},
  {"Sett på bakgrunn av","en helsefaglig","avklaring","tilgjengeliggjøres","helsegevinsten","på samme måte som","omstillingsprosessen"},
  {"Sammenholdt med","en helhetlig","implementering","utvides","helseutfordringene","i motsetning til","leveransekonseptet"},
  {"På grunn av","en manglende","styringsinnsats","dokumenteres","helseproduksjonen","innenfor","innsatsfokuseringen"},
  {"Med hensyn til","en særlig","innovasjon","spores","fastlegenes produksjonsevne","i tillegg til","helseforetaket"},
  {"Under forutsetning av","en løpende","forventningsjustering","innhentes","rehabiliteringspotensialet","gjennom","ventelisteskandalene"},
  {"Etter en totalvurdering av","en langsiktig","orientering","adresseres","samhandlingskompetansen","ut fra","tjenesteintegreringen"},
  {"Uten hensyn til","en bærekraftig","utvikling","stabiliseres","forsvarlighetskravene","med sikte på","kjernevirksomheten"},
  {"Avhengig av","en resultatorientert","målhorisont","genereres","samhandlingskoordineringen","på tvers av","pasientsskadeerstatningen"},
  {"På grunnlag av","en tverrfaglig","arena","stimuleres","avviksmeldingene","på linje med","kvalitetsarbeidet"},
  {"I og med","en kunnskapsbasert","synergi","balanseres","fagkoordineringen","utenom","systemsvikten"},
  {"Under henvisning til","en inkluderende","avstemning","ivaretas","helseproblematikken","i forlengelsen av","helsereformene"},
  {"Gitt","en representativ","beskrivelse","dokumenteres","visualiseringen","innenfor rammen av","kommunepolitikken"},
  {"I lys av","en implisitt","gjengivelse","ivaretas","byggesøknaden","i motsetning til","samordningsplikten"},
  {"Med bakgrunn i","en konkret","søknad","utredes","materialiteten","i tillegg til","saksbehandlingstiden"},
  {"I forhold til","en feilaktig","skjemautfylling","fastslås","beskaffenheten","gjennom","tiltakshaveren"},
  {"Sett hen til","en faktisk","råderett","meldes","kontrollerklæringen","parallelt med","dispensasjonssøknaden"},
  {"I og med","en nødvendig","nabovarsling","konkluderes","søknadsprosessen","for så vidt gjelder","reguleringsplanen"},
  {"Ifølge","en transparent","klagebehandling","betviles","vedtaksbegrunnelsen","på basis av","kartgrunnlaget"},
  {"Sammenliknet med","en langsiktig","saksbehandling","oppleves","forføyningen","innenfor","hjemmelsgrunnlaget"},
  {"Ut fra","en bærekraftig","samhandling","betraktes","gjennomføringsplanen","i forhold til","planvedtaket"},
  {"Uavhengig av","en representativ","prosessavklaring","estimeres","ansvarsbelegningen","med henblikk på","ansvarsretten"},
  {"Basert på","en kvalitativ","konkretisering","bedømmes","tiltaket","ved hjelp av","prosjekteringen"},
  {"Vedrørende","en søknadspliktig","innvilgelse","anbefales","igangsettingstillatelsen","på linje med","planforslaget"},
  {"Under henvisning til","en klanderverdig","kvalitetsbedømming","forhåndsvurderes","ferdigattesten","på tvers av","grunnboken"},
  {"Grunnet","en arkitekturbasert","ulempebetraktning","avklares","kvaliteten","knyttet til","planbestemmelsen"},
  {"Tatt i betraktning","en systematisk","tillatelse","preaksepteres","dispensasjonen","som en følge av","arealbruken"},
  {"Forutsatt","(en ressursmessig)","realitetsbehandling","fastsettes","samsvarserklæringen","begrunnet i","statlig arealplan"},
  {"Uten hensyn til","en vesentlig","arealoverføring","forankres","oppføringen","i kraft av","tomtefestelova"},
  {"Med sikte på","en midlertidig","godkjennelse","utløses","rammetillatelsen","på tross av","strandsonen"},
  {"Sett ut fra","en kvalifisert","omregulering","samordnes","fasadeendringen","i relasjon til","ansvarsretten"},
  {"Med grunnlag i","en frittliggende","rammetillatelse","vurderes","terrenginngrepet","i overensstemmelse med","tvingende sikkerhetshensyn"},
}

PRIVMSG:
  '^%psvada$': (s, d, a) =>
    words = {}
    wordN = 1
    for i=1,7 do
      line = svada[math.random(1, #svada)]
      word = line[wordN]
      table.insert(words, word)
      wordN = wordN + 1

    say table.concat(words, ' ')


textutils: more utils!

textutils: more utils!

PRIVMSG:
  '^%pupper (.+)$': (source, destination, arg) =>
    say arg\upper!
  '^%plower (.+)$': (source, destination, arg) =>
    say arg\lower!
  '^%preverse (.+)$': (source, destination, arg) =>
    say arg\reverse!
  '^%plen (.+)$': (source, destination, arg) =>
    say tostring(arg\len!)
  '^%pnicks$': (source, destination) =>
    say table.concat([n for n,k in pairs(ivar2.channels[destination].nicks)], ' ')
  '^%prandom (.+)$': (source, destination, arg) =>
    words = [word for word in arg\gmatch('%S+')]
    say words[math.random(1, #words)]
  '^%pbold (.+)$': (source, destination, arg) =>
    say ivar2.util.bold(arg)
  '^%punderline (.+)$': (source, destination, arg) =>
    say ivar2.util.underline(arg)
  '^%pitalic (.+)$': (source, destination, arg) =>
    say ivar2.util.italic(arg)
  '^%pinvert (.+)$': (source, destination, arg) =>
    say ivar2.util.reverse(arg)
  '^%ptrim (.+)$': (source, destination, arg) =>
    say ivar2.util.trim(arg)
  '^%pcolor ([0-9]+) (.+)$': (source, destination, color, arg) =>
    say ivar2.util.color(arg, color)
  '^%pfirst (.+)$': (source, destination, arg) =>
    say ivar2.util.split(arg, '%s')[1]
  '^%psplit (.-) (.*)$': (source, destination, arg, args) =>
    say table.concat(ivar2.util.split(args, arg), ' ')
  '^%preplace (.-) (.-) (.*)$': (source, destination, pat, repl, arg) =>
    new, n = string.gsub(arg, pat, repl)
    say(new)
  '^%pnocolor (.*)$': (source, destination, arg) =>
    new, n = string.gsub(arg, '\002', '')
    new, n = string.gsub(new, '\003[0-9]+(,[0-9]+)?', '')
    say(new)


acl logic fix

acl logic fix

import Model, enum from require "lapis.db.model"
import create_table, types, add_column from require "lapis.db.schema"

Users = require "lazuli.modules.user_management.models.users"
ACL_Entries = require "models.acl_entries"

class ACLs extends Model

  -- user is one of:
  --  * "lazuli.modules.user_management.models.users" instance
  --  * user id (number) to be found by that model
  --  * nil if no user is logged in/applicable
  matchUser: do
    _logic= (user)->
      entries=ACL_Entries\select "where acl_id = ? order by position asc nulls first, id", @id
      for entry in *entries
        ret, err=entry\matchUser user
        return nil, err if ret == nil and err
        return ret if type(ret)=="boolean"
    (user,return_default=true)=>
      if user
        if type(user)=="number"
          user=Users\find user
        return nil, "user not found" unless user
      cname=(user and tostring(user.id) or "[N]").."-"..@id
      cached=ngx.shared.acl_cache\get cname
      return @default_policy if cached == "[D]"
      return cached if cached ~= nil
      ret,err=_logic user
      if type(ret)=="boolean"
        ngx.shared.acl_cache\set cname, ret, 10
      if ret==nil and not err and return_default
        ngx.shared.acl_cache\set cname, "[D]", 10
        return @default_policy
      return ret, err

  @relations: {
    {"user", belongs_to: "Users"}
  }

  @get_relation_model: (name)=> switch name
    when "Users"
      require "lazuli.modules.user_management.models.users"
    when "ACLs"
      require "models.acls"

  @migrations: {
    ->
      create_table "acls", {
        {"id",             types.serial}
        {"user_id",        types.integer}
        {"name",           types.varchar}
        {"default_policy", types.boolean}
        "PRIMARY KEY (id)"
      }
  }

import Model, enum from require "lapis.db.model"
import create_table, types, add_column from require "lapis.db.schema"

Users = require "lazuli.modules.user_management.models.users"
ACL_Entries = require "models.acl_entries"

class ACLs extends Model

  -- user is one of:
  --  * "lazuli.modules.user_management.models.users" instance
  --  * user id (number) to be found by that model
  --  * nil if no user is logged in/applicable
  matchUser: do
    _logic= (user)->
      entries=ACL_Entries\select "where acl_id = ? order by position asc nulls first, id", @id
      for entry in *entries
        ret, err=entry\matchUser user
        return nil, err if ret == nil and err
        return ret if type(ret)=="boolean"
    (user,return_default=true)=>
      if user
        if type(user)=="number"
          user=Users\find user
        return nil, "user not found" unless user
      cname=(user and tostring(user.id) or "[N]").."-"..@id
      cached=ngx.shared.acl_cache\get cname
      return @default_policy if cached == "[D]"
      return cached if cached ~= nil
      ret,err=_logic user
      if type(ret)=="boolean"
        ngx.shared.acl_cache\set cname, ret, 10
      if not ret and not err and return_default
        ngx.shared.acl_cache\set cname, "[D]", 10
        return @default_policy
      return ret, err

  @relations: {
    {"user", belongs_to: "Users"}
  }

  @get_relation_model: (name)=> switch name
    when "Users"
      require "lazuli.modules.user_management.models.users"
    when "ACLs"
      require "models.acls"

  @migrations: {
    ->
      create_table "acls", {
        {"id",             types.serial}
        {"user_id",        types.integer}
        {"name",           types.varchar}
        {"default_policy", types.boolean}
        "PRIMARY KEY (id)"
      }
  }


btc: use new say command

btc: use new say command

Former-commit-id: e423d5ee6b087c1412d77d4bd379ca295fb6866b [formerly 65aced1eeb224d16a566fe8f421ac9af9361c2e5]
Former-commit-id: 7442c5f2fd48d2fb5b015b2f714f4b118666b849

simplehttp = require'simplehttp'
json = require'json'

PRIVMSG:
  '^.btc$': (source, destination, input) =>
    simplehttp 'https://blockchain.info/no/ticker', (data) ->
      if result = json.decode data
        say '\0021\002 BTC is worth \002%s\002 € (~15m)', result["EUR"]["15m"]

simplehttp = require'simplehttp'
json = require'json'

PRIVMSG:
  '^.btc$': (source, destination, input) =>
    simplehttp 'https://blockchain.info/no/ticker', (data) ->
      if result = json.decode data
        @Msg 'privmsg', destination, source, '\0021\002 BTC is worth \002%s\002 € (~15m)', result["EUR"]["15m"]


gay: add function gaywords

gay: add function gaywords

Former-commit-id: 0e16247164eb89119a83e350b69c8e82eee2a2a6 [formerly d3ebce31e82f1ddc493559d505c4a7a0a84a8fb1]
Former-commit-id: 7c08748b42ef181ea2aeb4ca5f6681bf7c0c2d16

FABULOUS_COLORS = {4, 7, 9, 10, 12, 13, 6}

i = 0

gayify = (s) ->
  if s == "" return ""
  s\gsub "[%z\1-\127\194-\244][\128-\191]*", (c) ->
    ret = string.format("\03%02d%s", FABULOUS_COLORS[i + 1], c)
    i = (i + 1) % #FABULOUS_COLORS
    return ret

gaywordify = (s) ->
  if s == "" return ""
  ivar2.util.translateWords s, (c) ->
    ret = string.format("\03%02d%s", FABULOUS_COLORS[i + 1], c)
    i = (i + 1) % #FABULOUS_COLORS
    return ret

PRIVMSG:
  '^%pgay (.+)$': (source, destination, arg) =>
      say gayify arg
  '^%pgaywords (.+)$': (source, destination, arg) =>
      say gaywordify arg

FABULOUS_COLORS = {4, 7, 9, 10, 12, 13, 6}

i = 0

gayify = (s) ->
  if s == "" return ""
  s\gsub "[%z\1-\127\194-\244][\128-\191]*", (c) ->
    ret = string.format("\03%02d%s", FABULOUS_COLORS[i + 1], c)
    i = (i + 1) % #FABULOUS_COLORS
    return ret

PRIVMSG:
  '^%pgay (.+)$': (source, destination, arg) =>
      say gayify arg


shuffle and truncate lists of endorsers

shuffle and truncate lists of endorsers

import Widget from require "lapis.html"

class Base extends Widget

  shuffled: (t) =>
    order = [{rnd: math.random(), idx: i} for i in ipairs t]
    table.sort(order, (a,b) -> a.rnd < b.rnd)
    [t[x.idx] for x in *order]

  render_endorse_button: (m) =>
    if @current_user
      button class: "module-endorse #{@current_user\endorses(m) and "endorsed" or ""}", ["data-module-id"]: m.id, ->
        span class: "regular", "endorse"
        span class: "endorsed", "endorsed"
        span class: "hover", "deendorse"

  render_users_txtlist: (users, prefix, max) =>
    len = #users
    max = max or len
    if len > 0
      last = users[len]
      users[len] = nil
      text prefix
      n = 0
      for u in *users
        a href: @url_for("main.user", id: u.id), u\get_fullname()
        text ", "
        n += 1
        if n >= max - 1
          break
      a href: @url_for("main.user", id: last.id), last\get_fullname()
      if len - n - 1 > 0
        text " and #{len - n - 1} other#{len - n - 1 > 1 and "s" or ""}"
      text "."

  render_endorsers: (endorsers, max_endorsers) =>
    p class: "module-endorsers", ->
      @render_users_txtlist(@shuffled(endorsers), "Endorsed by: ", max_endorsers)

  render_module_link: (m) =>
    url = @module\get_url()
    if url
      p -> a href: url, url

  render_modules_txtlist: (deps, prefix) =>
    len = #deps
    if len > 0
      last = deps[len]
      deps[len] = nil
      text prefix
      for u in *deps
        a href: @url_for("main.module", id: u.id), u\get_name()
        text ", "
      a href: @url_for("main.module", id: last.id), last\get_name()
      text "."

  render_dependencies: (deps) =>
    p class: "module-dependencies", ->
      @render_modules_txtlist(deps, "Depends on: ")

  render_reverse_dependencies: (deps) =>
    p class: "module-reverse-dependencies", ->
      @render_modules_txtlist(deps, "Depended on by: ")

  render_all_dependencies: (m) =>
    deps = m\dependencies()
    rev_deps = m\reverse_dependencies()
    if deps[1]
      @render_dependencies(deps)
    if rev_deps[1]
      @render_reverse_dependencies(rev_deps)

  render_labels: (labels) =>
    ul class: "labels-list", ->
      for l in *labels
        li ->
          a href: @url_for("main.label", id: l.id), l\get_name()

  render_endorsers_and_labels: (m, max_endorsers) =>
      endorsers = m\endorsers()
      labels = m\labels(sort: "get_name")
      if endorsers[1]
        @render_endorsers(endorsers, max_endorsers)
      if labels[1]
        div class: "labels-container", ->
          text "Labels: "
          @render_labels(labels)

  render_modules_list: (modules) =>
    ul class: "modules-list", ->
      for m in *modules
        li ->
          @render_endorse_button(m)
          a class: "module-name", href: @url_for("main.module", id: m.id), m\get_name()
          p class: "module-description", m\get_description()
          @render_endorsers_and_labels(m, 3)

  render_errors: () =>
    if @errors
      div id: "errors", ->
        for error in *@errors
          p ->
            em "ERROR"
            text " " .. error

Base

import Widget from require "lapis.html"

class Base extends Widget

  render_endorse_button: (m) =>
    if @current_user
      button class: "module-endorse #{@current_user\endorses(m) and "endorsed" or ""}", ["data-module-id"]: m.id, ->
        span class: "regular", "endorse"
        span class: "endorsed", "endorsed"
        span class: "hover", "deendorse"

  render_users_txtlist: (users, prefix) =>
    len = #users
    if len > 0
      last = users[len]
      users[len] = nil
      text prefix
      for u in *users
        a href: @url_for("main.user", id: u.id), u\get_fullname()
        text ", "
      a href: @url_for("main.user", id: last.id), last\get_fullname()
      text "."

  render_endorsers: (endorsers) =>
    p class: "module-endorsers", ->
      @render_users_txtlist(endorsers, "Endorsed by: ")

  render_module_link: (m) =>
    url = @module\get_url()
    if url
      p -> a href: url, url

  render_modules_txtlist: (deps, prefix) =>
    len = #deps
    if len > 0
      last = deps[len]
      deps[len] = nil
      text prefix
      for u in *deps
        a href: @url_for("main.module", id: u.id), u\get_name()
        text ", "
      a href: @url_for("main.module", id: last.id), last\get_name()
      text "."

  render_dependencies: (deps) =>
    p class: "module-dependencies", ->
      @render_modules_txtlist(deps, "Depends on: ")

  render_reverse_dependencies: (deps) =>
    p class: "module-reverse-dependencies", ->
      @render_modules_txtlist(deps, "Depended on by: ")

  render_all_dependencies: (m) =>
    deps = m\dependencies()
    rev_deps = m\reverse_dependencies()
    if deps[1]
      @render_dependencies(deps)
    if rev_deps[1]
      @render_reverse_dependencies(rev_deps)

  render_labels: (labels) =>
    ul class: "labels-list", ->
      for l in *labels
        li ->
          a href: @url_for("main.label", id: l.id), l\get_name()

  render_endorsers_and_labels: (m) =>
      endorsers = m\endorsers()
      labels = m\labels(sort: "get_name")
      if endorsers[1]
        @render_endorsers(endorsers)
      if labels[1]
        div class: "labels-container", ->
          text "Labels: "
          @render_labels(labels)

  render_modules_list: (modules) =>
    ul class: "modules-list", ->
      for m in *modules
        li ->
          @render_endorse_button(m)
          a class: "module-name", href: @url_for("main.module", id: m.id), m\get_name()
          p class: "module-description", m\get_description()
          @render_endorsers_and_labels(m)

  render_errors: () =>
    if @errors
      div id: "errors", ->
        for error in *@errors
          p ->
            em "ERROR"
            text " " .. error

Base


Change discount invocation

Change discount invocation

lyaml = require "lyaml"
discount = require "discount"
rex = require "rex_pcre"
config = (require "lapis.config").get!
io = require "io"

class Content
    markdown: (obj) =>
        if type(obj) == "boolean"
            obj
        elseif type(obj) != "table"
            obj = (tostring obj)\gsub "^%s+", ""
            if obj\len() > 0 and obj\sub(1,1) == '$'
                discount ((obj\sub 2)\gsub "^%s+", "")
            else
                obj\gsub "^\\\\$", "$"
        else
            {k, @markdown v for k, v in pairs obj}

    get: (name) =>
        ret, match = pcall -> rex.match name, "^[-0-9a-zA-Z_]+$"
        if not ret
            nil, "PCRE regex matching failed: #{err}"
        else if not match
            nil, "Invalid name: `#{name}`"
        else
            path = "#{config.content_prefix .. name}.yaml"
            file = io.open(path, "r")
            if file
                contents = file\read("*a")
                if contents
                    ret, yaml = pcall -> lyaml.load(contents)
                    if ret then
                        @markdown yaml
                    else
                        nil, "YAML reading failed in `#{path}`: #{yaml}"
                else
                    nil, "Error reading file `#{path}`"
            else
                nil, "File `#{path}` not found or could not be opened"

lyaml = require "lyaml"
discount = require "discount"
rex = require "rex_pcre"
config = (require "lapis.config").get!
io = require "io"

class Content
    markdown: (obj) =>
        if type(obj) == "boolean"
            obj
        elseif type(obj) != "table"
            obj = (tostring obj)\gsub "^%s+", ""
            if obj\len() > 0 and obj\sub(1,1) == '$'
                (discount.compile ((obj\sub 2)\gsub "^%s+", "")).body
            else
                obj\gsub "^\\\\$", "$"
        else
            {k, @markdown v for k, v in pairs obj}

    get: (name) =>
        ret, match = pcall -> rex.match name, "^[-0-9a-zA-Z_]+$"
        if not ret
            nil, "PCRE regex matching failed: #{err}"
        else if not match
            nil, "Invalid name: `#{name}`"
        else
            path = "#{config.content_prefix .. name}.yaml"
            file = io.open(path, "r")
            if file
                contents = file\read("*a")
                if contents
                    ret, yaml = pcall -> lyaml.load(contents)
                    if ret then
                        @markdown yaml
                    else
                        nil, "YAML reading failed in `#{path}`: #{yaml}"
                else
                    nil, "Error reading file `#{path}`"
            else
                nil, "File `#{path}` not found or could not be opened"


Add very basic graphics.atlas.AtlasRegion

export ^

class AtlasRegion
	new: (parent, tileindex, rect) =>
		@__parent = parent
		@__tileIndex = tileindex
		@rect = rect\clone!
		@rotated = false

	tileIndex: => @__tileIndex
	width: => @rect\width!
	height: => @rect\height!

	clip: =>