Fix some issues in commands.moon

Fix some issues in commands.moon

Update db command to simplify giving strings as values
Fix log color command not having enable/disable options
Fix some syntax ambiguities in log command
Add a command to reset db keys
Fix log color prefix command to handle prefix errors

-- Copyright (c) 2014 by Adam Hellberg <sharparam@sharparam.com>.
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.

NAME, T = ...

import Logger, log from T
import decorate, deserialize from T.misc

{database: db} = T

commands = {}

T.command_manager =
    handle: (message) =>
        name, arg = message\match '^([^%s]+)(.*)'
        return @help! unless name
        name = name\lower!
        local command

        for _, cmd in pairs commands
            for _, alias in pairs cmd[1]
                if name\match '^' .. alias
                    command = cmd
                    break

        return log\error 'Invalid command.' unless command

        args = {}

        if arg
            arg = arg\trim!
            if arg == ""
                arg = nil
            else
                for token in arg\gmatch '[^%s]+'
                    table.insert args, token

        command[2] arg, unpack args

    help: =>
        log\info 'TODO: Add help'

    register: (names, handler) =>
        names = {names} unless type(names) == 'table'
        entry = {names, handler}
        table.insert commands, entry

cm = T.command_manager
register = cm\register

register 'de', (arg) ->
    T\set_debug arg\match('^[ye]') and true or false if arg else T\toggle_debug!
    log\notice 'Debugging %s!', T\is_debug_enabled! and 'ENABLED' or 'DISABLED'

register 'db$', (arg, key, value) ->
    if not T\is_debug_enabled!
        return log\error 'For safety reasons, db command is only operable in debug mode'
    if not arg
        return log\error 'Usage: <key> [value]'

    if not value
        log\info 'Value of %s is %s (default: %s)', key, tostring(db key), tostring db\get_default key
    elseif value == '_RESET'
        db\reset key
        log\info 'Value of %s has been reset to %s', key, tostring db key
    else
        value = arg\match("^#{key} (.*)")
        -- This makes it easier to set strings in the db
        value = tostring value unless value\match '^%d+$' or value\match '^\{.*\}$'
        valid, result = deserialize value
        if not valid
            return log\error 'Invalid value given, Lua error: %s', result
        db\set key, result
        log\info 'Value of %s set to %s', key, tostring db key

register 'l', (arg, section, s_arg, ss_arg) ->
    if not arg
        return log\notice 'Logging is %s.', db('log') and 'enabled' or 'disabled'
    elseif arg\match '^[ts]' -- Log [t]oggle/[s]witch
        return db\set 'log', (not db 'log', true)
    elseif arg\match('^[ye]') or arg\match '^on' -- Log [y]es, [e]nable, [on]
        return db\set 'log', true
    elseif arg\match('^[nd]') or arg\match '^of' -- Log [n]o, [d]isable, [of]f
        return db\set 'log', false

    return unless section

    -- If user log level threshold is set high enough (notice)
    -- some log statements may not appear

    if section\match '^l' -- Log [l]evel
        if not s_arg
            level = db 'log.level', Logger.levels.INFO
            prefix = Logger\level_to_prefix level
            return log\notice 'Current log level is %s (%d)', prefix, level
        level = s_arg\match '^%d+'
        level = tonumber level
        if not level -- Attempt to parse a text value
            prefix = s_arg\match('^.')\upper!
            for pre, lvl in Logger.levels
                if prefix == pre\match '^%w'
                    level = lvl
                    break
        if type(level) == 'number'
            db\set 'log.level', level
    elseif section\match '^c' -- Log [c]olor
        if not s_arg
            name_color = Logger.colors.name!
            log\notice decorate('Current name color is %s', name_color), name_color
            for level, func in pairs Logger.colors.levels
                color = func!
                prefix = Logger\level_to_prefix level
                log\notice decorate('Current %s color is %s', color), prefix, color
        elseif s_arg\match('^[ye]') or s_arg\match '^on'
            db\set 'log.color', true
        elseif s_arg\match('^di') or s_arg\match('^of') or s_arg\match '^not'
            db\set 'log.color', false
        elseif not ss_arg
            log\error 'Usage: enable/disable / name/<level> <color>'
        elseif s_arg\match '^na' -- [na]me
            db\set 'log.color.name', ss_arg
        else
            prefix_letter = s_arg\match '^.'\upper!
            local level, prefix
            for lvl, pre in pairs Logger.prefixes
                if prefix_letter == pre\match '^%w'
                    level = lvl
                    prefix = pre\lower!
                    break
            return log\error 'Invalid prefix' unless prefix
            db\set 'log.color.level.' .. prefix, ss_arg

for i, v in ipairs {'sharexp', 'sxp'}
    _G['SLASH_' .. NAME\upper! .. i] = '/' .. v

SlashCmdList[NAME\upper!] = (msg, editBox) ->
    cm\handle msg

-- Copyright (c) 2014 by Adam Hellberg <sharparam@sharparam.com>.
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.

NAME, T = ...

import Logger, log from T
import decorate, deserialize from T.misc

{database: db} = T

commands = {}

T.command_manager =
    handle: (message) =>
        name, arg = message\match '^([^%s]+)(.*)'
        return @help! unless name
        name = name\lower!
        local command

        for _, cmd in pairs commands
            for _, alias in pairs cmd[1]
                if name\match '^' .. alias
                    command = cmd
                    break

        return log\error 'Invalid command.' unless command

        args = {}

        if arg
            arg = arg\trim!
            if arg == ""
                arg = nil
            else
                for token in arg\gmatch '[^%s]+'
                    table.insert args, token

        command[2] arg, unpack args

    help: =>
        log\info 'TODO: Add help'

    register: (names, handler) =>
        names = {names} unless type(names) == 'table'
        entry = {names, handler}
        table.insert commands, entry

cm = T.command_manager
register = cm\register

register 'de', (arg) ->
    if arg then T\set_debug arg\match '^[ye]' and true or false else T\toggle_debug!
    log\notice 'Debugging %s!', T\is_debug_enabled! and 'ENABLED' or 'DISABLED'

register 'db$', (arg, key, value) ->
    if not T\is_debug_enabled!
        return log\error 'For safety reasons, db command is only operable in debug mode'
    if not arg
        return log\error 'Usage: <key> [value]'

    if not value
        log\info 'Value of %s is %s (default: %s)', key, db key
    else
        valid, result = deserialize arg\match "^#{key} (.*)"
        if not valid
            return log\error 'Invalid value given, Lua error: %s', result
        db\set key, result
        log\info 'Value of %s set to %s', key, db key

register 'l', (arg, section, s_arg, ss_arg) ->
    if not arg
        return log\notice 'Logging is %s.', db('log') and 'enabled' or 'disabled'
    elseif arg\match '^[ts]' -- Log [t]oggle/[s]witch
        return db\set 'log', (not db 'log', true)
    elseif arg\match '^[ye]' or arg\match '^on' -- Log [y]es, [e]nable, [on]
        return db\set 'log', true
    elseif arg\match '^[nd]' or arg\match '^of' -- Log [n]o, [d]isable, [of]f
        return db\set 'log', false

    return unless section

    -- If user log level threshold is set high enough (notice)
    -- some log statements may not appear

    if section\match '^l' -- Log [l]evel
        if not s_arg
            level = db 'log.level', Logger.levels.INFO
            return log\notice 'Current log level is %s (%d)',
                Logger\level_to_prefix level, level
        level = s_arg\match '^%d+'
        level = tonumber level
        if not level -- Attempt to parse a text value
            prefix = s_arg\match('^.')\upper!
            for pre, lvl in Logger.levels
                if prefix == pre\match '^%w'
                    level = lvl
                    break
        if type(level) == 'number'
            db\set 'log.level', level
    elseif section\match '^c' -- Log [c]olor
        if not s_arg or not ss_arg
            name_color = Logger.colors.name!
            log\notice decorate('Current name color is %s', name_color), name_color
            for level, func in pairs Logger.colors.levels
                color = func!
                prefix = Logger\level_to_prefix level
                log\notice decorate('Current %s color is %s', color), prefix, color
        elseif s_arg\match '^na' -- [na]me
            db\set 'log.color.name', ss_arg
        else
            prefix_letter = s_arg\match '^.'\upper!
            local level, prefix
            for lvl, pre in pairs Logger.prefixes
                if prefix_letter == pre\match '^%w'
                    level = lvl
                    prefix = pre\lower!
                    break
            db\set 'log.color.level.' .. prefix, ss_arg

for i, v in ipairs {'sharexp', 'sxp'}
    _G['SLASH_' .. NAME\upper! .. i] = '/' .. v

SlashCmdList[NAME\upper!] = (msg, editBox) ->
    cm\handle msg


textutils: add functions to access the util lib

Former-commit-id: 62ca70d074e4988ae2580c9230e158688c546441 [formerly 8f4c5541430b3bf0c3642e9f292658b5af50fd14]
Former-commit-id: c4e3e4c06107285d53376765feb5bb920366068a

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)


Added Direction@isStandard.

Added Direction@isStandard.

moon = require('moon')
Enum = require('lib/utils/enum')
Vector = require('lib/geo/vector')

class Direction extends Vector

	@headings: { 'EAST', 'SOUTH_EAST', 'SOUTH', 'SOUTH_WEST', 'WEST', 'NORTH_WEST', 'NORTH', 'NORTH_EAST' }

	---
	-- Gets the closest heading for a vector
	--
	-- @method getHeading
	-- @static
	-- @param {Vector} vector
	-- @param {Boolean} [allowIntermediate=false] - Whether to return intermediate headings
	-- @return {StdDirection}
	--
	@getHeading: (vector, allowIntermediate = false) =>
		if not vector or vector.x == 0 and vector.y == 0 then return 'NONE'
		angle = math.atan2(vector.y, vector.x)
		octants = if allowIntermediate then 8 else 4
		octant = _.round(octants * angle / (2 * math.pi) + octants) % octants
		if octants == 4 then octant *= 2
		octant += 1
		return @headings[octant]

	---
	-- Aligns a vector to the closest standard heading
	--
	-- @method align
	-- @static
	-- @param {Vector} vector
	-- @param {Boolean} [allowIntermediate=false] - Whether to return intermediate headings
	-- @return {Vector} - A new vector with the same magnitude, but aligned to a standard direction
	--
	@align: (vector, allowIntermediate = false) =>
		heading = @getHeading(vector, allowIntermediate)
		return Vector(heading, vector\getLength())

	---
	-- Returns whether a vector is a standard direction
	--
	-- @method isStandard
	-- @static
	-- @param {Vector} vector
	-- @return {Boolean}
	--
	@isStandard: (vector) =>
		absX = math.abs(vector.x)
		absY = math.abs(vector.y)
		return (absX == 1 or absX == 0) and (absY == 1 or absY == 0)

	new: (x, y) =>
		-- @param {String}
		if _.isString(x)
			direction = @@[x]
			x = direction.x
			y = direction.y

		-- @param {Vector}
		if _.isTable(x) then y = 1

		super(x, y)
		-- @normalize()

	toVector: () => Vector(@x, @y)

moon.mixin(Direction, Enum, {
	NORTH: Direction(0, -1),
	SOUTH: Direction(0, 1),
	WEST: Direction(-1, 0),
	EAST: Direction(1, 0),
	NORTH_WEST: Direction(-1, -1),
	NORTH_EAST: Direction(1, -1),
	SOUTH_WEST: Direction(-1, 1),
	SOUTH_EAST: Direction(1, 1),
	NONE: Direction(0, 0)
})

return Direction

moon = require('moon')
Enum = require('lib/utils/enum')
Vector = require('lib/geo/vector')

class Direction extends Vector

	@headings: { 'EAST', 'SOUTH_EAST', 'SOUTH', 'SOUTH_WEST', 'WEST', 'NORTH_WEST', 'NORTH', 'NORTH_EAST' }

	---
	-- Gets the closest heading for a vector
	--
	-- @method getHeading
	-- @static
	-- @param {Vector} vector
	-- @param {Boolean} [allowIntermediate=false] - Whether to return intermediate headings
	-- @return {StdDirection}
	--
	@getHeading: (vector, allowIntermediate = false) =>
		if not vector or vector.x == 0 and vector.y == 0 then return 'NONE'
		angle = math.atan2(vector.y, vector.x)
		octants = if allowIntermediate then 8 else 4
		octant = _.round(octants * angle / (2 * math.pi) + octants) % octants
		if octants == 4 then octant *= 2
		octant += 1
		return @headings[octant]

	---
	-- Aligns a vector to the closest standard heading
	--
	-- @method align
	-- @static
	-- @param {Vector} vector
	-- @param {Boolean} [allowIntermediate=false] - Whether to return intermediate headings
	-- @return {Vector} - A new vector with the same magnitude, but aligned to a standard direction
	--
	@align: (vector, allowIntermediate = false) =>
		heading = @getHeading(vector, allowIntermediate)
		return Vector(heading, vector\getLength())

	new: (x, y) =>
		-- @param {String}
		if _.isString(x)
			direction = @@[x]
			x = direction.x
			y = direction.y

		-- @param {Vector}
		if _.isTable(x) then y = 1

		super(x, y)
		-- @normalize()

	toVector: () => Vector(@x, @y)

moon.mixin(Direction, Enum, {
	NORTH: Direction(0, -1),
	SOUTH: Direction(0, 1),
	WEST: Direction(-1, 0),
	EAST: Direction(1, 0),
	NORTH_WEST: Direction(-1, -1),
	NORTH_EAST: Direction(1, -1),
	SOUTH_WEST: Direction(-1, 1),
	SOUTH_EAST: Direction(1, 1),
	NONE: Direction(0, 0)
})

return Direction


github: support defining handlers for events.

Add two handlers, push and watch

Former-commit-id: 22cb54515f13c0566ed2431e302f4cb659a61860 [formerly 0641d5bd7ff4c751cbb39c21c8dc3cbe398384eb]
Former-commit-id: 59560b476b62ed28f3d45b7328e634ab16696553

util = require 'util'

hex_to_char = (x) ->
  string.char(tonumber(x, 16))

unescape = (url) ->
  url\gsub("%%(%x%x)", hex_to_char)

handlers = {
  push: (repo, destination, json) ->
    branch = json.ref\gsub 'refs/heads/', ''
    for i, c in pairs(json.commits)
      if i > 3
        break
      message = c.message\gsub '\n.*', ''
      ivar2\Msg 'privmsg', destination, nil, "#{repo}: #{branch}, #{c.author.username}: #{message} #{c.url}"
    if #json.commits > 3
      ivar2\Msg 'privmsg', destination, nil, "#{repo}: #{branch}, #{#json.commits-3} more commits not displayed."
  watch: (repo, destination, json) ->
    action = json.action
    ivar2\Msg 'privmsg', destination, nil, "#{repo}: #{json.sender.login}: #{action} watching"

}

ivar2.webserver.regUrl '/github/(.*)', (req, res) ->
  destination = req.url\match('/github/(.+)/?$')
  destination = unescape(destination)
  json = util.json.decode(req.body)

  repo = json.repository.full_name

  event = req.headers['X-GitHub-Event']
  handler = handlers[event]
  if handler
    handler(repo, destination, json)
  else
    ivar2\Log('error', 'Unknown github event: %s', event)

  res\set_status(200)
  res\set_header('Content-Type', 'text/plain')
  res\set_body('ok')
  res\send()

return {}

util = require 'util'

hex_to_char = (x) ->
  string.char(tonumber(x, 16))

unescape = (url) ->
  url\gsub("%%(%x%x)", hex_to_char)

ivar2.webserver.regUrl '/github/(.*)', (req, res) ->
  destination = req.url\match('/github/(.+)/?$')
  destination = unescape(destination)
  json = util.json.decode(req.body)

  repo = json.repository.full_name
  branch = json.ref\gsub 'refs/heads/', ''

  for i, c in pairs(json.commits)
    if i > 3
      break
    message = c.message\gsub '\n.*', ''
    ivar2\Msg 'privmsg', destination, nil, "#{repo}: #{branch}, #{c.author.username}: #{message} #{c.url}"
  if #json.commits > 3
    ivar2\Msg 'privmsg', destination, nil, "#{repo}: #{branch}, #{#json.commits-3} more commits not displayed."

  res\set_status(200)
  res\set_header('Content-Type', 'text/plain')
  res\set_body('ok')
  res\send()

return {}


svada: fix typo

svada: fix typo

-- 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, ' ')


sun/assembler/init: add basic documentation for function_header()

function_header() takes a coroutine and a documented table and will
eventually repeat resume the coroutine with input assembled from the
table

-- vim:set noet sts=0 sw=3 ts=3:

util = require "sun.assembler.util"

header = (sink)->
	resume = (sink, value)-> coroutine.resume sink, type(value) == "string" or string.byte(value)
	-- first bytes of header
	resume sink, "\27Lua"
	resume sink, 0x53
	resume sink, util.grab_luac_data!
	-- size checks
	sizes = util.check_sizes!
	resume sink, sizes.int
	resume sink, sizes.size_t
	resume sink, sizes.Instruction
	resume sink, sizes.lua_Integer
	resume sink, sizes.lua_Number
	-- LUAC_INT and LUAC_NUM
	resume sink, util.check_luac_int!
	resume sink, util.check_luac_num!

function_header = (sink, tree)->
	--[[ documentation for `tree` argument:
	-- `.source` source name (converted using convert_literal_string())
	-- `.line` line defined (0 for file master function)
	-- `.lastline` last line defined (0 for file master function)
	-- `.parameters` list of parameters defined
	-- `.is_vararg` byte saying if is a vararg function
	-- `.maxstacksize` number of registers used
	-- `.instructions` list of instructions to be assembled
	-- `.constants` list of constants to be compiled
	-- `.upvalues` list of upvalues
	-- `.prototypes` list of prototypes
	-- `.debug` {
	--   `.lineinfo` first and last line as two bytes
	--   `.localvars` local variables
	--   `.upvalues` list of upvalues
	-- }
	--]]


passing around options

passing around options

IRCConnection = require 'irc'
Logger = require 'logger'
cqueues = require 'cqueues'
lfs     = require 'lfs'

Logger.set_debug true if os.getenv 'DEBUG'

mods = {}
load_modules = (folder)->
	for file in lfs.dir folder
		if file\match "%.lua$"
			func = assert loadfile folder .. '/' .. file
			table.insert mods, func!

for module_folder in *{'plugins', 'modules'}
	load_modules module_folder if lfs.attributes(module_folder, 'mode') == 'directory'

bots = {}
for file in lfs.dir 'configs'
	if file\match "%.ini$"
		data = {
			dir: lfs.currentdir!
		}
		for line in io.lines('configs/' .. file)
			key, value = assert line\match "^(.-)=(.+)$"
			data[key] = value
		bot  = IRCConnection data.host, data.port, data

		for _, mod in pairs(mods)
			bot\load_modules mod

		bot.user_data = data

		table.insert(bots, bot)

main = (queue = require 'queue')->
	for _, bot in pairs bots
		queue\wrap ->
			local success
			for i=1, 3 do -- three tries
				ok, err = pcall bot.connect, bot
				success = ok
				if not ok
					Logger.print Logger.level.error .. '*** Unable to connect: ' .. bot.user_data.host
					Logger.debug Logger.level.error .. '*** ' .. err
				else
					break

			if not success
				Logger.print Logger.level.fatal .. '*** Not connecting anymore for: ' .. file
				return
			bot\loop!

success, fw = pcall require, 'astronomy'
if not success then
	queue = cqueues.new!
	package.loaded['queue'] = queue
	main!
	while not queue\empty!
		assert queue\step!

else
	package.loaded['queue'] = fw
	fw\wrap main

IRCConnection = require 'irc'
Logger = require 'logger'
cqueues = require 'cqueues'
lfs     = require 'lfs'

Logger.set_debug true if os.getenv 'DEBUG'

mods = {}
load_modules = (folder)->
	for file in lfs.dir folder
		if file\match "%.lua$"
			func = assert loadfile folder .. '/' .. file
			table.insert mods, func!

for module_folder in *{'plugins', 'modules'}
	load_modules module_folder if lfs.attributes(module_folder, 'mode') == 'directory'

bots = {}
for file in lfs.dir 'configs'
	if file\match "%.ini$"
		data = {
			dir: lfs.currentdir!
		}
		for line in io.lines('configs/' .. file)
			key, value = assert line\match "^(.-)=(.+)$"
			data[key] = value
		bot  = IRCConnection data.host, data.port, data

		for _, mod in pairs(mods)
			bot\load_modules mod

		table.insert(bots, bot)

main = (queue = require 'queue')->
	for _, bot in pairs bots
		queue\wrap ->
			local success
			for i=1, 3 do -- three tries
				ok, err = pcall bot.connect, bot
				success = ok
				if not ok
					Logger.print Logger.level.error .. '*** Unable to connect: ' .. data.host
					Logger.debug Logger.level.error .. '*** ' .. err
				else
					break

			if not success
				Logger.print Logger.level.fatal .. '*** Not connecting anymore for: ' .. file
				return
			bot\loop!

success, fw = pcall require, 'astronomy'
if not success then
	queue = cqueues.new!
	package.loaded['queue'] = queue
	main!
	while not queue\empty!
		assert queue\step!

else
	package.loaded['queue'] = fw
	fw\wrap main


Correction perlinMap

Correction perlinMap

noise attend un entier pour les oppérations. Si noises n'est pas
précisé, la valeur sera de 1.

Class = require "nyaa.class"
images = require "images"
Ground = require "data.ground"

tool = (x,y,z) -> -- Cette fonction sert à générer une carte binaire de perlin noise
	part = 5
	pow = 1/9
	t = 2*love.math.noise(x,y,z)-1
	s = ((math.abs(t))^pow)*t/math.abs(t)+1
	t = (math.floor(s*part/2)/part)
	s = (math.abs(t)^(1/pow))*t/math.abs(t)
	return s

noise = (noise,xMax,yMax) ->
	xMax = 400
	yMax = 300
	grid = {}
	for x = 1, xMax
		grid[x] = grid[x] or {}
		for y = 1, yMax
		    grid[x][y] = tool((x+noise)/50,(y+noise)/50,noise)
	return grid

Tile = Class "Tile",
	__init: (arg) =>
		@groundChange = arg.groundChange or nil -- permet de savoir si une case est d'origine (générée par le bruit) ou si elle a été modifiée
		@groundType = arg.groundType
		@structure = arg.structure or nil
		@ressources = arg.ressources or nil

	crossable: =>
		if @groundType != 0 and not @structure
			return true
		else return false

local Map

Map = Class "Map",
	__init: (arg) =>
		@noises = arg.noises or nil -- FIXME
		@defaultground = arg.defaultGround
		@grid = {}
		@xMax = arg.xMax or 300
		@yMax = arg.yMax or 200
		@zMin = arg.zMin or -3
		@zMax = arg.zMax or 3

	__class: {
		:Tile

		perlinMap: (arg) ->
			self = Map arg
			@noises or= 1 -- FIXME

			mapSource1 = noise(@noises,@xMax,@yMax)		--Height Map
			mapSource2 = noise(@noises+0.1,@xMax,@yMax*2)	--GroundType Map
			for x = 1, @xMax
				@grid[x] = {}
				for y = 1, @yMax
					@grid[x][y] = {}
					for z = @zMin, mapSource1[x][y]
						@grid[x][y][z] = Tile
							groundType: Ground[mapSource2[x][y]+1]
					for z = mapSource1[x][y]+1, @zMax
						@grid[x][y][z] = Ground[3] -- empty ground

			self

		flatMap: (arg) ->
			self = Map arg

			rocks = Ground\getByName "Rocks"
			empty = Ground\getByName "Empty"

			for x = 1, @xMax
				@grid[x] = {}

				for y = 1, @yMax
					@grid[x][y] = {}

					for z = @zMin, @zMax
						if z <= 0
							@grid[x][y][z] = rocks
						else
							@grid[x][y][z] = empty

			self

		---
		-- @param str (string)
		fromMoon: (str) =>
	}

	---
	-- @return (Tile)
	get: (x, y, z) =>
		@grid[x][y][z]

	---
	-- @return boolean
	set: (x, y, z, arguments) =>
		local modified

		if arguments.groundType
			@grid[x][y][z].groundType = arguments.groundType
			modified = true

		if arguments.structure
			@grid[x][y][z].structure = arguments.structure
			modified = true

		if arguments.ressource
			@grid[x][y][z].ressource = arguments.ressource
			modified = true

		if modified
			@grid[x][y][z].groundChange = true

		modified

	---
	-- @return (string)
	toMoon: =>

Map

Class = require "nyaa.class"
images = require "images"
Ground = require "data.ground"

tool = (x,y,z) -> -- Cette fonction sert à générer une carte binaire de perlin noise
	part = 5
	pow = 1/9
	t = 2*love.math.noise(x,y,z)-1
	s = ((math.abs(t))^pow)*t/math.abs(t)+1
	t = (math.floor(s*part/2)/part)
	s = (math.abs(t)^(1/pow))*t/math.abs(t)
	return s

noise = (noise,xMax,yMax) ->
	xMax = 400
	yMax = 300
	grid = {}
	for x = 1, xMax
		grid[x] = grid[x] or {}
		for y = 1, yMax
		    grid[x][y] = tool((x+noise)/50,(y+noise)/50,noise)
	return grid

Tile = Class "Tile",
	__init: (arg) =>
		@groundChange = arg.groundChange or nil -- permet de savoir si une case est d'origine (générée par le bruit) ou si elle a été modifiée
		@groundType = arg.groundType
		@structure = arg.structure or nil
		@ressources = arg.ressources or nil

	crossable: =>
		if @groundType != 0 and not @structure
			return true
		else return false

local Map

Map = Class "Map",
	__init: (arg) =>
		@noises = arg.noises or nil -- FIXME
		@defaultground = arg.defaultGround
		@grid = {}
		@xMax = arg.xMax or 300
		@yMax = arg.yMax or 200
		@zMin = arg.zMin or -3
		@zMax = arg.zMax or 3

	__class: {
		:Tile

		perlinMap: (arg) ->
			self = Map arg

			mapSource1 = noise(@noises,@xMax,@yMax)		--Height Map
			mapSource2 = noise(@noises+0.1,@xMax,@yMax*2)	--GroundType Map
			for x = 1, @xMax
				for y = 1, @yMax
					for z = @zMin, mapSource1[x][y]
						grid[x][y][z] = Tile
							groundType: Ground[mapSource2[x][y]+1]
					for z = mapSource1[x][y]+1, @zMax
						grid[x][y][z] = Ground[3] -- empty ground

			self

		flatMap: (arg) ->
			self = Map arg

			rocks = Ground\getByName "Rocks"
			empty = Ground\getByName "Empty"

			for x = 1, @xMax
				@grid[x] = {}

				for y = 1, @yMax
					@grid[x][y] = {}

					for z = @zMin, @zMax
						if z <= 0
							@grid[x][y][z] = rocks
						else
							@grid[x][y][z] = empty

			self

		---
		-- @param str (string)
		fromMoon: (str) =>
	}

	---
	-- @return (Tile)
	get: (x, y, z) =>
		@grid[x][y][z]

	---
	-- @return boolean
	set: (x, y, z, arguments) =>
		local modified

		if arguments.groundType
			@grid[x][y][z].groundType = arguments.groundType
			modified = true

		if arguments.structure
			@grid[x][y][z].structure = arguments.structure
			modified = true

		if arguments.ressource
			@grid[x][y][z].ressource = arguments.ressource
			modified = true

		if modified
			@grid[x][y][z].groundChange = true

		modified

	---
	-- @return (string)
	toMoon: =>

Map