<commit_before>/**
 * Turtle Graphics for Web browser (nadesiko3)
 * plugin_turtle.js
 */

const PluginTurtle = {
  '初期化': {
    type: 'func',
    josi: [],
    fn: function (sys) {
      if (sys._turtle) return
      sys._turtle = {
        list: [],
        target: -1,
        ctx: null,
        canvas: null,
        canvas_r: {left: 0, top: 0, width: 640, height: 400},
        clearAll: function () {
          const me = this
          console.log('[TURTLE] clearAll')
          for (let i = 0; i < me.list.length; i++) {
            const tt = me.list[i]
            tt.mlist = [] // ジョブをクリア
            document.body.removeChild(tt.canvas)
          }
          me.list = []
          if (me.canvas !== null) {
            me.ctx.clearRect(0, 0,
              me.canvas.width,
              me.canvas.height)
          }
          me.target = -1
          me.flagSetTimer = false
        },
        drawTurtle: function (id) {
          const tt = this.list[id]
          const cr = this.canvas_r
          // カメの位置を移動
          tt.canvas.style.left = (cr.left + tt.x - tt.cx) + 'px'
          tt.canvas.style.top = (cr.top + tt.y - tt.cx) + 'px'
          if (!tt.f_update) return
          if (!tt.flagLoaded) return
          tt.f_update = false
          tt.ctx.clearRect(0, 0,
            tt.canvas.width,
            tt.canvas.height)
          if (!tt.f_visible) return
          if (tt.dir !== 270) {
            const rad = (tt.dir + 90) * 0.017453292519943295
            tt.ctx.save()
            tt.ctx.translate(tt.cx, tt.cy)
            tt.ctx.rotate(rad)
            tt.ctx.translate(-tt.cx, -tt.cy)
            tt.ctx.drawImage(tt.img, 0, 0)
            tt.ctx.restore()
          } else {
            tt.ctx.drawImage(tt.img, 0, 0)
          }
        },
        getCur: function () {
          if (this.list.length === 0) {
            throw Error('最初に『カメ作成』命令を呼び出してください。')
          }
          return this.list[this.target]
        },
        flagSetTimer: false,
        setTimer: function () {
          if (this.flagSetTimer) return
          this.flagSetTimer = true
          setTimeout(() => {
            const tt = this.getCur()
            console.log('[TURTLE] Let\'s go! job=', tt.mlist.length)
            sys._turtle.play()
          }, 1)
        },
        line: function (tt, x1, y1, x2, y2) {
          if (tt) {
            if (!tt.flagDown) return
          }
          const ctx = this.ctx
          ctx.beginPath()
          ctx.lineWidth = tt.lineWidth
          ctx.strokeStyle = tt.color
          ctx.moveTo(x1, y1)
          ctx.lineTo(x2, y2)
          ctx.stroke()
        },
        doMacro: function (tt, wait) {
          const me = this
          if (!tt.flagLoaded && wait > 0) {
            console.log('[TURTLE] waiting ...')
            return true
          }
          const m = tt.mlist.shift()
          const cmd = (m !== undefined) ? m[0] : ''
          switch (cmd) {
            case 'mv':
              // 線を引く
              me.line(tt, tt.x, tt.y, m[1], m[2])
              // カメの角度を変更
              const mvRad = Math.atan2(m[1] - tt.x, m[2] - tt.y)
              tt.dir = mvRad * 57.29577951308232
              tt.f_update = true
              // 実際に位置を移動
              tt.x = m[1]
              tt.y = m[2]
              break
            case 'fd':
              const fdv = m[1] * m[2]
              const rad = tt.dir * 0.017453292519943295
              const x2 = tt.x + Math.cos(rad) * fdv
              const y2 = tt.y + Math.sin(rad) * fdv
              me.line(tt, tt.x, tt.y, x2, y2)
              tt.x = x2
              tt.y = y2
              break
            case 'angle':
              const angle = m[1]
              tt.dir = ((angle - 90 + 360) % 360)
              tt.f_update = true
              break
            case 'rotr':
              const rv = m[1]
              tt.dir = (tt.dir + rv) % 360
              tt.f_update = true
              break
            case 'rotl':
              const lv = m[1]
              tt.dir = (tt.dir - lv + 360) % 360
              tt.f_update = true
              break
            case 'color':
              tt.color = m[1]
              break
            case 'size':
              tt.lineWidth = m[1]
              break
            case 'penOn':
              tt.flagDown = m[1]
              break
            case 'visible':
              tt.f_visible = m[1]
              tt.f_update = true
              break
            case 'changeImage':
              tt.flagLoaded = false
              tt.img.src = m[1]
              break
          }
          if (tt.flagLoaded) sys._turtle.drawTurtle(tt.id)
          return (tt.mlist.length > 0)
        },
        doMacroAll: function (wait) {
          let hasNext = false
          for (let i = 0; i < sys._turtle.list.length; i++) {
            const tt = sys._turtle.list[i]
            if (this.doMacro(tt, wait)) hasNext = true
          }
          return hasNext
        },
        play: function () {
          const me = this
          const wait = sys.__getSysValue('カメ速度', 100)
          let hasNext = this.doMacroAll(wait)
          if (wait <= 0) {
            while (hasNext) {
              hasNext = this.doMacroAll(wait)
            }
          } else if (hasNext) {
            setTimeout(() => {
              me.play()
            }, wait)
            return
          }
          console.log('[TURTLE] finished.')
        }
      }
    }
  },

  /// タートルグラフィックス/カメ操作
  'カメ作成': { /// タートルグラフィックスを開始してカメのIDを返す /// かめさくせい
    type: 'func',
    josi: [],
    fn: function (sys) {
      // カメの情報を sys._turtle リストに追加
      const id = sys._turtle.list.length
      const tt = {
        id: id,
        img: null,
        canvas: null,
        ctx: null,
        dir: 270, // 上向き
        cx: 32,
        cy: 32,
        x: 0,
        y: 0,
        color: 'black',
        lineWidth: 4,
        flagDown: true,
        f_update: true,
        flagLoaded: false,
        f_visible: true,
        mlist: []
      }
      sys._turtle.list.push(tt)
      sys._turtle.target = id
      // 画像を読み込む
      tt.img = document.createElement('img')
      tt.canvas = document.createElement('canvas')
      tt.ctx = tt.canvas.getContext('2d')
      tt.canvas.id = id
      tt.img.src = sys.__getSysValue('カメ画像URL', 'turtle.png')
      tt.img.onload = () => {
        tt.cx = tt.img.width / 2
        tt.cy = tt.img.height / 2
        tt.canvas.width = tt.img.width
        tt.canvas.height = tt.img.height
        tt.flagLoaded = true
        sys._turtle.drawTurtle(tt.id)
        console.log('turtle.onload')
      }
      tt.img.onerror = () => {
        console.log('カメの読み込みに失敗')
        tt.flagLoaded = true
        tt.f_visible = false
        sys._turtle.drawTurtle(tt.id)
      }
      tt.canvas.style.position = 'absolute'
      document.body.appendChild(tt.canvas)
      // 描画先をセットする
      const canvasId = sys.__getSysValue('カメ描画先', 'turtle_cv')
      console.log('カメ描画先=', canvasId, sys.__varslist[0]['カメ描画先'])
      const cv = sys._turtle.canvas = document.getElementById(canvasId)
      if (!sys._turtle.canvas) {
        console.log('[ERROR] カメ描画先が見当たりません。' + canvasId)
        return
      }
      const ctx = sys._turtle.ctx = sys._turtle.canvas.getContext('2d')
      ctx.lineWidth = 4
      ctx.strokeStyle = 'black'
      ctx.lineCap = 'round'
      const rect = cv.getBoundingClientRect()
      const rx = rect.left + window.pageXOffset
      const ry = rect.top + window.pageYOffset
      sys._turtle.canvas_r = {
        'left': rx,
        'top': ry,
        width: rect.width,
        height: rect.height
      }
      // デフォルト位置の設定
      tt.x = rect.width / 2
      tt.y = rect.height / 2
      return id
    }
  },
  'カメ操作対象設定': { /// IDを指定して操作対象となるカメを変更する /// かめそうさたいしょうせってい
    type: 'func',
    josi: [['に', 'へ', 'の']],
    fn: function (id, sys) {
      sys._turtle.target = id
    },
    return_none: true
  },
  'カメ描画先': {type: 'var', value: 'turtle_cv'}, /// かめびょうがさき
  'カメ画像URL': {type: 'var', value: 'turtle.png'}, /// かめがぞうURL
  'カメ画像変更': { /// カメの画像をURLに変更する /// かめがぞうへんこう
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (url, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['changeImage', url])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ速度': {type: 'const', value: 100}, /// かめそくど
  'カメ速度設定': { /// カメの動作速度vに設定(大きいほど遅い) /// かめそくどせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (v, sys) {
      sys.__varslist[0]['カメ速度'] = v
    }
  },
  'カメ移動': { /// カメの位置を[x,y]へ移動する /// かめいどう
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (xy, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['mv', xy[0], xy[1]])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ進': { /// カメの位置をVだけ進める /// かめすすむ
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['fd', v, 1])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ戻': { /// カメの位置をVだけ戻す /// かめもどる
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['fd', v, -1])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ角度設定': { /// カメの向きをDEGに設定する /// かめかくどせってい
    type: 'func',
    josi: [['に', 'へ', 'の']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['angle', parseFloat(v)])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ右回転': { /// カメの向きをDEGだけ右に向ける /// かめみぎかいてん
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['rotr', v])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ左回転': { /// カメの向きをDEGだけ左に向ける /// かめひだりかいてん
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['rotl', v])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメペン色設定': { /// カメのペン描画色をCに設定する /// かめぺんいろせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (c, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['color', c])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメペンサイズ設定': { /// カメペンのサイズをWに設定する /// かめぺんさいずせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (w, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['size', w])
      sys._turtle.setTimer()
    }
  },
  'カメペン設定': { /// カメペンを使うかどうかをV(オン/オフ)に設定する /// かめぺんせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (w, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['penOn', w])
      sys._turtle.setTimer()
    }
  },
  'カメ全消去': { /// 表示しているカメと描画内容を全部消去する /// かめぜんしょうきょ
    type: 'func',
    josi: [],
    fn: function (sys) {
      sys._turtle.clearAll()
    },
    return_none: true
  },
  'カメ非表示': { /// カメの画像を非表示にする。描画に影響しない。 /// かめひひょうじ
    type: 'func',
    josi: [],
    fn: function (sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['visible', false])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ表示': { /// 非表示にしたカメを表示する。 /// かめひょうじ
    type: 'func',
    josi: [],
    fn: function (sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['visible', true])
      sys._turtle.setTimer()
    },
    return_none: true
  }
}

module.exports = PluginTurtle

// scriptタグで取り込んだ時、自動で登録する
if (typeof (navigator) === 'object') {
  navigator.nako3.addPluginObject('PluginTurtle', PluginTurtle)
}
<commit_msg>タートルグラフィックスに「カメ起点移動」命令を追加。<commit_after>/**
 * Turtle Graphics for Web browser (nadesiko3)
 * plugin_turtle.js
 */

const PluginTurtle = {
  '初期化': {
    type: 'func',
    josi: [],
    fn: function (sys) {
      if (sys._turtle) return
      sys._turtle = {
        list: [],
        target: -1,
        ctx: null,
        canvas: null,
        canvas_r: {left: 0, top: 0, width: 640, height: 400},
        clearAll: function () {
          const me = this
          console.log('[TURTLE] clearAll')
          for (let i = 0; i < me.list.length; i++) {
            const tt = me.list[i]
            tt.mlist = [] // ジョブをクリア
            document.body.removeChild(tt.canvas)
          }
          me.list = []
          if (me.canvas !== null) {
            me.ctx.clearRect(0, 0,
              me.canvas.width,
              me.canvas.height)
          }
          me.target = -1
          me.flagSetTimer = false
        },
        drawTurtle: function (id) {
          const tt = this.list[id]
          const cr = this.canvas_r
          // カメの位置を移動
          tt.canvas.style.left = (cr.left + tt.x - tt.cx) + 'px'
          tt.canvas.style.top = (cr.top + tt.y - tt.cx) + 'px'
          if (!tt.f_update) return
          if (!tt.flagLoaded) return
          tt.f_update = false
          tt.ctx.clearRect(0, 0,
            tt.canvas.width,
            tt.canvas.height)
          if (!tt.f_visible) return
          if (tt.dir !== 270) {
            const rad = (tt.dir + 90) * 0.017453292519943295
            tt.ctx.save()
            tt.ctx.translate(tt.cx, tt.cy)
            tt.ctx.rotate(rad)
            tt.ctx.translate(-tt.cx, -tt.cy)
            tt.ctx.drawImage(tt.img, 0, 0)
            tt.ctx.restore()
          } else {
            tt.ctx.drawImage(tt.img, 0, 0)
          }
        },
        getCur: function () {
          if (this.list.length === 0) {
            throw Error('最初に『カメ作成』命令を呼び出してください。')
          }
          return this.list[this.target]
        },
        flagSetTimer: false,
        setTimer: function () {
          if (this.flagSetTimer) return
          this.flagSetTimer = true
          setTimeout(() => {
            const tt = this.getCur()
            console.log('[TURTLE] Let\'s go! job=', tt.mlist.length)
            sys._turtle.play()
          }, 1)
        },
        line: function (tt, x1, y1, x2, y2) {
          if (tt) {
            if (!tt.flagDown) return
          }
          const ctx = this.ctx
          ctx.beginPath()
          ctx.lineWidth = tt.lineWidth
          ctx.strokeStyle = tt.color
          ctx.moveTo(x1, y1)
          ctx.lineTo(x2, y2)
          ctx.stroke()
        },
        doMacro: function (tt, wait) {
          const me = this
          if (!tt.flagLoaded && wait > 0) {
            console.log('[TURTLE] waiting ...')
            return true
          }
          const m = tt.mlist.shift()
          const cmd = (m !== undefined) ? m[0] : ''
          switch (cmd) {
            case 'xy':
              // 起点を移動する
              tt.x = m[1]
              tt.y = m[2]
              break
            case 'mv':
              // 線を引く
              me.line(tt, tt.x, tt.y, m[1], m[2])
              // カメの角度を変更
              const mvRad = Math.atan2(m[1] - tt.x, m[2] - tt.y)
              tt.dir = mvRad * 57.29577951308232
              tt.f_update = true
              // 実際に位置を移動
              tt.x = m[1]
              tt.y = m[2]
              break
            case 'fd':
              const fdv = m[1] * m[2]
              const rad = tt.dir * 0.017453292519943295
              const x2 = tt.x + Math.cos(rad) * fdv
              const y2 = tt.y + Math.sin(rad) * fdv
              me.line(tt, tt.x, tt.y, x2, y2)
              tt.x = x2
              tt.y = y2
              break
            case 'angle':
              const angle = m[1]
              tt.dir = ((angle - 90 + 360) % 360)
              tt.f_update = true
              break
            case 'rotr':
              const rv = m[1]
              tt.dir = (tt.dir + rv) % 360
              tt.f_update = true
              break
            case 'rotl':
              const lv = m[1]
              tt.dir = (tt.dir - lv + 360) % 360
              tt.f_update = true
              break
            case 'color':
              tt.color = m[1]
              break
            case 'size':
              tt.lineWidth = m[1]
              break
            case 'penOn':
              tt.flagDown = m[1]
              break
            case 'visible':
              tt.f_visible = m[1]
              tt.f_update = true
              break
            case 'changeImage':
              tt.flagLoaded = false
              tt.img.src = m[1]
              break
          }
          if (tt.flagLoaded) sys._turtle.drawTurtle(tt.id)
          return (tt.mlist.length > 0)
        },
        doMacroAll: function (wait) {
          let hasNext = false
          for (let i = 0; i < sys._turtle.list.length; i++) {
            const tt = sys._turtle.list[i]
            if (this.doMacro(tt, wait)) hasNext = true
          }
          return hasNext
        },
        play: function () {
          const me = this
          const wait = sys.__getSysValue('カメ速度', 100)
          let hasNext = this.doMacroAll(wait)
          if (wait <= 0) {
            while (hasNext) {
              hasNext = this.doMacroAll(wait)
            }
          } else if (hasNext) {
            setTimeout(() => {
              me.play()
            }, wait)
            return
          }
          console.log('[TURTLE] finished.')
        }
      }
    }
  },

  /// タートルグラフィックス/カメ操作
  'カメ作成': { /// タートルグラフィックスを開始してカメのIDを返す /// かめさくせい
    type: 'func',
    josi: [],
    fn: function (sys) {
      // カメの情報を sys._turtle リストに追加
      const id = sys._turtle.list.length
      const tt = {
        id: id,
        img: null,
        canvas: null,
        ctx: null,
        dir: 270, // 上向き
        cx: 32,
        cy: 32,
        x: 0,
        y: 0,
        color: 'black',
        lineWidth: 4,
        flagDown: true,
        f_update: true,
        flagLoaded: false,
        f_visible: true,
        mlist: []
      }
      sys._turtle.list.push(tt)
      sys._turtle.target = id
      // 画像を読み込む
      tt.img = document.createElement('img')
      tt.canvas = document.createElement('canvas')
      tt.ctx = tt.canvas.getContext('2d')
      tt.canvas.id = id
      tt.img.src = sys.__getSysValue('カメ画像URL', 'turtle.png')
      tt.img.onload = () => {
        tt.cx = tt.img.width / 2
        tt.cy = tt.img.height / 2
        tt.canvas.width = tt.img.width
        tt.canvas.height = tt.img.height
        tt.flagLoaded = true
        sys._turtle.drawTurtle(tt.id)
        console.log('turtle.onload')
      }
      tt.img.onerror = () => {
        console.log('カメの読み込みに失敗')
        tt.flagLoaded = true
        tt.f_visible = false
        sys._turtle.drawTurtle(tt.id)
      }
      tt.canvas.style.position = 'absolute'
      document.body.appendChild(tt.canvas)
      // 描画先をセットする
      const canvasId = sys.__getSysValue('カメ描画先', 'turtle_cv')
      console.log('カメ描画先=', canvasId, sys.__varslist[0]['カメ描画先'])
      const cv = sys._turtle.canvas = document.getElementById(canvasId)
      if (!sys._turtle.canvas) {
        console.log('[ERROR] カメ描画先が見当たりません。' + canvasId)
        return
      }
      const ctx = sys._turtle.ctx = sys._turtle.canvas.getContext('2d')
      ctx.lineWidth = 4
      ctx.strokeStyle = 'black'
      ctx.lineCap = 'round'
      const rect = cv.getBoundingClientRect()
      const rx = rect.left + window.pageXOffset
      const ry = rect.top + window.pageYOffset
      sys._turtle.canvas_r = {
        'left': rx,
        'top': ry,
        width: rect.width,
        height: rect.height
      }
      // デフォルト位置の設定
      tt.x = rect.width / 2
      tt.y = rect.height / 2
      return id
    }
  },
  'カメ操作対象設定': { /// IDを指定して操作対象となるカメを変更する /// かめそうさたいしょうせってい
    type: 'func',
    josi: [['に', 'へ', 'の']],
    fn: function (id, sys) {
      sys._turtle.target = id
    },
    return_none: true
  },
  'カメ描画先': {type: 'var', value: 'turtle_cv'}, /// かめびょうがさき
  'カメ画像URL': {type: 'var', value: 'turtle.png'}, /// かめがぞうURL
  'カメ画像変更': { /// カメの画像をURLに変更する /// かめがぞうへんこう
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (url, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['changeImage', url])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ速度': {type: 'const', value: 100}, /// かめそくど
  'カメ速度設定': { /// カメの動作速度vに設定(大きいほど遅い) /// かめそくどせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (v, sys) {
      sys.__varslist[0]['カメ速度'] = v
    }
  },
  'カメ移動': { /// カメの位置を[x,y]へ移動する /// かめいどう
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (xy, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['mv', xy[0], xy[1]])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ起点移動': { /// カメの描画起点位置を[x,y]へ移動する /// かめきてんいどう
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (xy, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['xy', xy[0], xy[1]])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ進': { /// カメの位置をVだけ進める /// かめすすむ
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['fd', v, 1])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ戻': { /// カメの位置をVだけ戻す /// かめもどる
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['fd', v, -1])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ角度設定': { /// カメの向きをDEGに設定する /// かめかくどせってい
    type: 'func',
    josi: [['に', 'へ', 'の']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['angle', parseFloat(v)])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ右回転': { /// カメの向きをDEGだけ右に向ける /// かめみぎかいてん
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['rotr', v])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ左回転': { /// カメの向きをDEGだけ左に向ける /// かめひだりかいてん
    type: 'func',
    josi: [['だけ']],
    fn: function (v, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['rotl', v])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメペン色設定': { /// カメのペン描画色をCに設定する /// かめぺんいろせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (c, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['color', c])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメペンサイズ設定': { /// カメペンのサイズをWに設定する /// かめぺんさいずせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (w, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['size', w])
      sys._turtle.setTimer()
    }
  },
  'カメペン設定': { /// カメペンを使うかどうかをV(オン/オフ)に設定する /// かめぺんせってい
    type: 'func',
    josi: [['に', 'へ']],
    fn: function (w, sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['penOn', w])
      sys._turtle.setTimer()
    }
  },
  'カメ全消去': { /// 表示しているカメと描画内容を全部消去する /// かめぜんしょうきょ
    type: 'func',
    josi: [],
    fn: function (sys) {
      sys._turtle.clearAll()
    },
    return_none: true
  },
  'カメ非表示': { /// カメの画像を非表示にする。描画に影響しない。 /// かめひひょうじ
    type: 'func',
    josi: [],
    fn: function (sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['visible', false])
      sys._turtle.setTimer()
    },
    return_none: true
  },
  'カメ表示': { /// 非表示にしたカメを表示する。 /// かめひょうじ
    type: 'func',
    josi: [],
    fn: function (sys) {
      const tt = sys._turtle.getCur()
      tt.mlist.push(['visible', true])
      sys._turtle.setTimer()
    },
    return_none: true
  }
}

module.exports = PluginTurtle

// scriptタグで取り込んだ時、自動で登録する
if (typeof (navigator) === 'object') {
  navigator.nako3.addPluginObject('PluginTurtle', PluginTurtle)
}
<|endoftext|>


<commit_before>AzureaUtil.mixin(AzureaVim.commands_list, {
    delay: 'delay',
    'でぁｙ': 'delay'
});
// :delay option1 option2
// 指定時間後にstatus updateします。
// option1はポストする時間です。
//   ^(?:(?:(\d{4})-)?(\d{1,2})-(\d{1,2}) )?(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$
// 形式を記述した場合、setTimeeventを使い、指定時後にポストします。
// setTimeeventは、Azureaのセッションを越えて設定を保存、実行します（再起動しても有効です）。
// 其れ以外の記述であった場合、単一の数値と見做して、setTimeoutで指定時間経過後にpostします。
// option1が空白を含む場合、ダブルクオーテーションで囲って下さい。
// option2は、ポストする文です。空白を含められます。
// AzureaVimの仕様上、option2が:から始まる場合、AzureaVimのコマンドとして、該当コマンドが実行されます。
// 遅延投稿時のin_reply_to_status_idは、:delay実行時の物を使用します。

(function() {

if (AzureaUtil.db.get('DelayUseTwitDelay')) {
    AzureaUtil.db.set('DelayUseTwitDelay', '0');
}

function postTwitDelay(text,       // @param String:
                       time,       // @param String: RFC2822
                       callback) { // @param Function:
    Http.postRequestAsync('http://twitdelay.appspot.com/api/post',
                          'user_id=' + AzureaUtil.db.get('UserName') +
                          '&api_key=' + AzureaUtil.db.get('DelayTwitDelayApiKey') +
                          '&status=' + text +
                          '&at=' + time,
                          false,
                          callback);
}

AzureaVim.prototype.delay = function() {
    var regex_date = /^(?:(?:(\d{4})-)?(\d{1,2})-(\d{1,2}) )?(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/,
        m1, d, type;

    if (m1 = this.command[1].match(regex_date)) {
        var d = new Date();
        m1[1] && d.setFullYear(m1[1]);
        m1[2] && d.setMonth(m1[2] - 1);
        m1[3] && d.setDate(m1[3]);
        d.setHours(m1[4]);
        d.setMinutes(m1[5]);
        d.setSeconds(0);
        m1[6] && d.setSeconds(m1[6]);
        this.command[1] = d.getTime();
        type = 2;
        this.command[2] = this.command.slice(2).join(' ');
    } else {
        this.command[1] = new Date().getTime() + (this.command[1] - 0);
        type = 1;
        this.command[2] = this.command.slice(2).join(' ');
    }
    if (AzureaUtil.db.get('DelayUseTwitDelay')) {
        d = new Date(this.command[1]);
        postTwitDelay(this.command[2],
                      d.getUTCDate() + ' ' + d.getUTCMonth() + ' ' + d.getUTCFullYear() + ' ' + d.getUTCHours() + ':' + d.getUTCMinutes() + ':' + d.getUTCSeconds() + ' +0000',
                      function() {});
    } else {
        if (type === 1) {
            AzureaUtil.time.setTimeout((function(obj) {
                return function() {
                    TwitterService.status.update(obj.command[2], obj.status_id);
                }
            })(this),
                                       this.command[1] - new Date().getTime());
        } else {
            AzureaUtil.time.setTimeevent('function() {TwitterService.status.update("' + this.command[2] + '", "' + this.status_id + '");}',
                                         this.command[1]);
        }
    }
}

})();<commit_msg>delay.js bug fix.<commit_after>AzureaUtil.mixin(AzureaVim.commands_list, {
    delay: 'delay',
    'でぁｙ': 'delay'
});
// :delay option1 option2
// 指定時間後にstatus updateします。
// option1はポストする時間です。
//   ^(?:(?:(\d{4})-)?(\d{1,2})-(\d{1,2}) )?(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$
// 形式を記述した場合、setTimeeventを使い、指定時後にポストします。
// setTimeeventは、Azureaのセッションを越えて設定を保存、実行します（再起動しても有効です）。
// 其れ以外の記述であった場合、単一の数値と見做して、setTimeoutで指定時間経過後にpostします。
// option1が空白を含む場合、ダブルクオーテーションで囲って下さい。
// option2は、ポストする文です。空白を含められます。
// AzureaVimの仕様上、option2が:から始まる場合、AzureaVimのコマンドとして、該当コマンドが実行されます。
// 遅延投稿時のin_reply_to_status_idは、:delay実行時の物を使用します。

(function() {

if (AzureaUtil.db.get('DelayUseTwitDelay')) {
    AzureaUtil.db.set('DelayUseTwitDelay', '0');
}

function postTwitDelay(text,       // @param String:
                       time,       // @param String: RFC2822
                       callback) { // @param Function:
    Http.postRequestAsync('http://twitdelay.appspot.com/api/post',
                          'user_id=' + TwitterService.currentUser.id +
                          '&api_key=' + AzureaUtil.db.get('DelayTwitDelayApiKey') +
                          '&status=' + text +
                          '&at=' + time,
                          false,
                          callback);
}

AzureaVim.prototype.delay = function() {
    var regex_date = /^(?:(?:(\d{4})-)?(\d{1,2})-(\d{1,2}) )?(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/,
        m1, d, type;

    if (m1 = this.command[1].match(regex_date)) {
        var d = new Date();
        m1[1] && d.setFullYear(m1[1]);
        m1[2] && d.setMonth(m1[2] - 1);
        m1[3] && d.setDate(m1[3]);
        d.setHours(m1[4]);
        d.setMinutes(m1[5]);
        d.setSeconds(0);
        m1[6] && d.setSeconds(m1[6]);
        this.command[1] = d.getTime();
        type = 2;
        this.command[2] = this.command.slice(2).join(' ');
    } else {
        this.command[1] = new Date().getTime() + (this.command[1] - 0);
        type = 1;
        this.command[2] = this.command.slice(2).join(' ');
    }
    if (AzureaUtil.db.get('DelayUseTwitDelay')) {
        d = new Date(this.command[1]);
        postTwitDelay(this.command[2],
                      d.getUTCDate() + ' ' + d.getUTCMonth() + ' ' + d.getUTCFullYear() + ' ' + d.getUTCHours() + ':' + d.getUTCMinutes() + ':' + d.getUTCSeconds() + ' +0000',
                      function() {});
    } else {
        if (type === 1) {
            AzureaUtil.time.setTimeout((function(obj) {
                return function() {
                    TwitterService.status.update(obj.command[2], obj.status_id);
                }
            })(this),
                                       this.command[1] - new Date().getTime());
        } else {
            AzureaUtil.time.setTimeevent('function() {TwitterService.status.update("' + this.command[2] + '", "' + this.status_id + '");}',
                                         this.command[1]);
        }
    }
}

})();<|endoftext|>


<commit_before>var version = "v1.0";
var express = require('express');
var https = require('https');
var http = require('http');
var fs = require('fs');
var child_process = require('child_process');
var products = require('./routes/catalogue');
var bodyParser = require('body-parser');

// start mongodb
/*
console.log(shell.pwd().stdout);
if (shell.exec('mongod --config ./conf/mongod.conf &').code !== 0) {
  console.log('Error: Failed to start mongodb');
}
*/
/*
var mongoProcess = child_process.spawn('mongod',['--config','./conf/mongod.conf'], {async:true});
mongoProcess.stdout.on('data', function(data) {
  console.log(data);
});
*/
var app = express();

var credentials = {
    key: fs.readFileSync('./ssl/server.key'),
    cert: fs.readFileSync('./ssl/server.crt'),
    //ca: fs.readFileSync('./ssl/ca.crt'),
    //requestCert: true,
    rejectUnauthorized: false
};

var protocol = (process.argv[2])?process.argv[2]:'http';
var port = (process.argv[3])?process.argv[3]:'3000';

app.use(bodyParser.json({limit:10000000}));

//app.get('/products', products.findAll);
app.get('/:dataset/search', products.search);
app.get('/harvestOADS', products.harvestOADS);
app.get('/products/:id', products.findById);
app.post('/products', products.addProduct);
app.post('/ngEOproducts', products.addProductFromNgEO);
app.post('/hubProducts', products.addProductFromHub);
app.put('/products/:id', products.updateProduct);
app.delete('/products/:id', products.deleteProduct);

if(protocol == 'https') {
  https.createServer(credentials, app).listen(port, function() {console.log("EOCat "+version+" is listening HTTPS on port "+port+"...");});
} else {
  http.createServer(app).listen(port, function() {console.log("EOCat "+version+" is listening HTTP on port "+port+"...");});
}
<commit_msg>read server key and certificate only if https is used<commit_after>var version = "v1.0";
var express = require('express');
var https = require('https');
var http = require('http');
var fs = require('fs');
var child_process = require('child_process');
var products = require('./routes/catalogue');
var bodyParser = require('body-parser');

var app = express();

var protocol = (process.argv[2])?process.argv[2]:'http';
var port = (process.argv[3])?process.argv[3]:'3000';

app.use(bodyParser.json({limit:10000000}));

//app.get('/products', products.findAll);
app.get('/:dataset/search', products.search);
app.get('/harvestOADS', products.harvestOADS);
app.get('/products/:id', products.findById);
app.post('/products', products.addProduct);
app.post('/ngEOproducts', products.addProductFromNgEO);
app.post('/hubProducts', products.addProductFromHub);
app.put('/products/:id', products.updateProduct);
app.delete('/products/:id', products.deleteProduct);

if(protocol == 'https') {
  try {
    var credentials = {
        key: fs.readFileSync('./ssl/server.key'),
        cert: fs.readFileSync('./ssl/server.crt'),
        rejectUnauthorized: false
    };
  }
  catch (err) {
    console.log("Could not read the server key or certificate in the ./ssl folder.");
  }
  https.createServer(credentials, app).listen(port, function() {console.log("EOCat "+version+" is listening HTTPS on port "+port+"...");});
} else {
  http.createServer(app).listen(port, function() {console.log("EOCat "+version+" is listening HTTP on port "+port+"...");});
}
<|endoftext|>


<commit_before>/* globals $, chrome, navigator, Vk, console, Popup, Emoji, getCase*/
/*jshint esnext: true */
/*jshint -W097*/
"use strict";
/**
 * Класс сообщения
 * @constructor
 * @param {Object} mess_obj			Объект сообщения загруженный через API
 * @param {Dialog} parentDialog 	Объект родительского диалога
 * @param {Message} parentMessage	Объект родительского сообщения
 */
function Message (mess_obj, parentDialogUrl) {
	this.id = mess_obj.id;

	if ( mess_obj.out === 1 ) {
		this.user_id = Popup.current.id;
	} else {
		this.user_id = mess_obj.user_id;
	}

	if ( parentDialogUrl ) {
		this.url = parentDialogUrl + '&msgid=' + this.id;
	}

	if ( mess_obj.action ) {

		this.body = [ $('<span/>', {
			'class': 'system',
			html: Popup.loc(mess_obj.action) + ' ',
		}) ];

	} else if ( mess_obj.body ) {
		if (/[\wа-яА-Яїєёъ]/.test( mess_obj.body.charAt( mess_obj.body.length-1 ) ))
			mess_obj.body += '. ';
		else
			mess_obj.body += ' ';

		// linkify экранирует html код в строке.
		// mess_obj.body = mess_obj.body.escapeHtml();

		mess_obj.body = mess_obj.body.linkify({
			format: url => url.length > 36 ? `${url.substr(0, 35)}…` : url
		});

		if (mess_obj.emoji === 1) {
			mess_obj.body = Emoji.emojiToHTML(mess_obj.body);
		}

		this.body = [ mess_obj.body ];
	} else {
		this.body = [];
	}

	// Добавляем код карту во вложения
	if ( mess_obj.geo ) {
		if (mess_obj.attachments) {
			mess_obj.attachments = [];
		}
		mess_obj.attachments.push({
			type: 'geo',
			geo: mess_obj.geo
		});
		delete mess_obj.geo;
	}

	// Добавляем код вложений
	if ( $.isArray(mess_obj.attachments) && mess_obj.attachments.length > 0 ) {
		mess_obj.attachments = mess_obj.attachments.map((attach) => {
			const type = attach.type;
			attach = attach[type];
			switch(type) {
				// Изображение
				case 'photo':
					attach.url = '';
					if		(attach.photo_2560)	attach.url = attach.photo_2560;
					else if (attach.photo_1280)	attach.url = attach.photo_1280;
					else if (attach.photo_807)	attach.url = attach.photo_807;
					else if (attach.photo_604)	attach.url = attach.photo_604;
					else if (attach.photo_130)	attach.url = attach.photo_130;
					else if (attach.photo_75)	attach.url = attach.photo_75;

					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-camera'}),
							Popup.loc('Photo'),
						]
					});

				// Подарок
				case 'gift':
					attach.url = '';
					if		(attach.thumb_256)	attach.url = attach.thumb_256;
					else if (attach.thumb_96)	attach.url = attach.thumb_96;
					else if (attach.thumb_48)	attach.url = attach.thumb_48;

					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-gift'}),
							Popup.loc('Gift'),
						]
					});

				// Пост
				case 'wall' :
					return $('<a/>', {
						href: `https://vk.com/wall${attach.from_id}_${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-pencil'}),
							Popup.loc('Post'),
						]
					});

				// Комментарий
				case 'wall_reply' :
					return $('<a/>', {
						href: `https://vk.com/wall${attach.owner_id}_${attach.post_id}?reply=${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-chat'}),
							Popup.loc('Comment'),
						]
					});

				// Аудиозапись
				case 'audio':
					return $('<a/>', {
						href: `https://vk.com/audio${attach.owner_id}_${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-music'}),
							`<b>${attach.artist}</b> – ${attach.title}`,
						]
					});

				// Видеозапись
				case 'video':
					return $('<a/>', {
						href: `https://vk.com/video${attach.owner_id}_${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-video'}),
							attach.title,
						]
					});

				// Документ
				case 'doc'	:
					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-doc'}),
							attach.title,
						]
					});

				// Ссылка
				case 'link'	:
					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-link'}),
							attach.title,
						]
					});

				// Карта
				case 'geo':
					attach.coordinates = attach.coordinates.split(' ');
					return $('<a/>', {
						href: 'https://www.google.com.ua/maps/place/@' +
							`${attach.coordinates[0]},${attach.coordinates[1]}` +
							',13z/data=!3m1!4b1!4m2!3m1!1s0x0:0x0',
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-location'}),
							(attach.place ? attach.place.title : Popup.loc('Map')),
						]
					});

				// Стикеры
				case 'sticker':
					return $('<img/>', {
						'class': 'emoji sticker',
						src: attach.photo_64,
						height: '32'
					});
			}
		});
		this.body = this.body.concat( mess_obj.attachments );
	}

	if ( $.isArray(mess_obj.fwd_messages) && mess_obj.fwd_messages.length > 0 ) {
		this.body.push( $('<a/>', {
			href: this.url,
			target: '_blank',
			html: [
				$('<i/>', { 'class':'icon-chat' }),
				getCase( mess_obj.fwd_messages.length, Popup.loc('forwarded messages') )
			],
		}) );
	}
}

/**
 * Возвращает сгенерированный код сообщения
 * @param  {String} type Формат сообщения
 * @return {String}      HTML code
 */
Message.prototype.getHtml = function (users, type) {
	switch(type) {
		case 'compact':
			return [$('<message/>', {
				html: [ users[ this.user_id ].ava({size:25, title: true, marker: false}) ].concat(this.body)
			})];
		default :
			return this.body;
	}
};
<commit_msg>Исправлена ошибка с прикрепленной картой<commit_after>/* globals $, chrome, navigator, Vk, console, Popup, Emoji, getCase*/
/*jshint esnext: true */
/*jshint -W097*/
"use strict";
/**
 * Класс сообщения
 * @constructor
 * @param {Object} mess_obj			Объект сообщения загруженный через API
 * @param {Dialog} parentDialog 	Объект родительского диалога
 * @param {Message} parentMessage	Объект родительского сообщения
 */
function Message (mess_obj, parentDialogUrl) {
	this.id = mess_obj.id;

	if ( mess_obj.out === 1 ) {
		this.user_id = Popup.current.id;
	} else {
		this.user_id = mess_obj.user_id;
	}

	if ( parentDialogUrl ) {
		this.url = parentDialogUrl + '&msgid=' + this.id;
	}

	if ( mess_obj.action ) {

		this.body = [ $('<span/>', {
			'class': 'system',
			html: Popup.loc(mess_obj.action) + ' ',
		}) ];

	} else if ( mess_obj.body ) {
		mess_obj.body += /[\wа-яА-Яїєёъ]/.test( mess_obj.body.charAt( mess_obj.body.length-1 ) ) ? '. ' : ' ';

		// linkify экранирует html код в строке.
		// mess_obj.body = mess_obj.body.escapeHtml();

		mess_obj.body = mess_obj.body.linkify({
			format: url => url.length > 36 ? `${url.substr(0, 35)}…` : url
		});

		if (mess_obj.emoji) {
			mess_obj.body = Emoji.emojiToHTML(mess_obj.body);
		}

		this.body = [ mess_obj.body ];
	} else {
		this.body = [];
	}

	// Добавляем код карту во вложения
	if ( mess_obj.geo ) {
		if (!mess_obj.attachments) {
			mess_obj.attachments = [];
		}
		mess_obj.attachments.push({
			type: 'geo',
			geo: mess_obj.geo
		});
		delete mess_obj.geo;
	}

	// Добавляем код вложений
	if ( $.isArray(mess_obj.attachments) && mess_obj.attachments.length > 0 ) {
		mess_obj.attachments = mess_obj.attachments.map((attach) => {
			const type = attach.type;
			attach = attach[type];
			switch(type) {
				// Изображение
				case 'photo':
					attach.url = '';
					if		(attach.photo_2560)	attach.url = attach.photo_2560;
					else if (attach.photo_1280)	attach.url = attach.photo_1280;
					else if (attach.photo_807)	attach.url = attach.photo_807;
					else if (attach.photo_604)	attach.url = attach.photo_604;
					else if (attach.photo_130)	attach.url = attach.photo_130;
					else if (attach.photo_75)	attach.url = attach.photo_75;

					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-camera'}),
							Popup.loc('Photo'),
						]
					});

				// Подарок
				case 'gift':
					attach.url = '';
					if		(attach.thumb_256)	attach.url = attach.thumb_256;
					else if (attach.thumb_96)	attach.url = attach.thumb_96;
					else if (attach.thumb_48)	attach.url = attach.thumb_48;

					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-gift'}),
							Popup.loc('Gift'),
						]
					});

				// Пост
				case 'wall' :
					return $('<a/>', {
						href: `https://vk.com/wall${attach.from_id}_${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-pencil'}),
							Popup.loc('Post'),
						]
					});

				// Комментарий
				case 'wall_reply' :
					return $('<a/>', {
						href: `https://vk.com/wall${attach.owner_id}_${attach.post_id}?reply=${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-chat'}),
							Popup.loc('Comment'),
						]
					});

				// Аудиозапись
				case 'audio':
					return $('<a/>', {
						href: `https://vk.com/audio${attach.owner_id}_${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-music'}),
							`<b>${attach.artist}</b> – ${attach.title}`,
						]
					});

				// Видеозапись
				case 'video':
					return $('<a/>', {
						href: `https://vk.com/video${attach.owner_id}_${attach.id}`,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-video'}),
							attach.title,
						]
					});

				// Документ
				case 'doc'	:
					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-doc'}),
							attach.title,
						]
					});

				// Ссылка
				case 'link'	:
					return $('<a/>', {
						href: attach.url,
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-link'}),
							attach.title,
						]
					});

				// Карта
				case 'geo':
					attach.coordinates = attach.coordinates.split(' ');
					return $('<a/>', {
						href: 'https://www.google.com.ua/maps/place/@' +
							`${attach.coordinates[0]},${attach.coordinates[1]}` +
							',13z/data=!3m1!4b1!4m2!3m1!1s0x0:0x0',
						target: '_blank',
						html: [
							$('<i/>', {'class': 'icon-location'}),
							(attach.place ? attach.place.title : Popup.loc('Map')),
						]
					});

				// Стикеры
				case 'sticker':
					return $('<img/>', {
						'class': 'emoji sticker',
						src: attach.photo_64,
						height: '32'
					});
			}
		});
		this.body = this.body.concat( mess_obj.attachments );
	}

	if ( $.isArray(mess_obj.fwd_messages) && mess_obj.fwd_messages.length > 0 ) {
		this.body.push( $('<a/>', {
			href: this.url,
			target: '_blank',
			html: [
				$('<i/>', { 'class':'icon-chat' }),
				getCase( mess_obj.fwd_messages.length, Popup.loc('forwarded messages') )
			],
		}) );
	}
}

/**
 * Возвращает сгенерированный код сообщения
 * @param  {String} type Формат сообщения
 * @return {String}      HTML code
 */
Message.prototype.getHtml = function (users, type) {
	switch(type) {
		case 'compact':
			return [$('<message/>', {
				html: [ users[ this.user_id ].ava({size:25, title: true, marker: false}) ].concat(this.body)
			})];
		default :
			return this.body;
	}
};
<|endoftext|>


<commit_before>function site_title(){
    return "
Joe Armstrong - Erlang and other stuff
";
}

function site_links(x){
    return `

Index

About

Lectures

Resources

Whoomph

	`;
}

function dots(x){
    var y = x.level;
    if(y == 0){
	return ".";
    } else if(y==1) {
	return "..";
    }
}

function template(x){
    // meta variables x.title and x.data x.level x.disqus_id
    // typical value
    // x.disqus_id = "/2016-09-08-Some-title.html"
    var url = "https://joearms.github.io/published" + x.disqus_id;
    var t = `

  <meta charset="UTF-8">
  </meta>

    <link href="${dots(x)}/src/style.css" rel="stylesheet" type="text/css"></link>

${site_title()}

	    ${site_links(x)}

${x.title}

	  ${x.data}

	  Tweet

Comments:

	`;
    return t;
}

<commit_msg>Include <title> and fix <meta> position in DOM<commit_after>function site_title(){
    return "
Joe Armstrong - Erlang and other stuff
";
}

function site_links(x){
    return `

Index

About

Lectures

Resources

Whoomph

	`;
}

function dots(x){
    var y = x.level;
    if(y == 0){
	return ".";
    } else if(y==1) {
	return "..";
    }
}

function template(x){
    // meta variables x.title and x.data x.level x.disqus_id
    // typical value
    // x.disqus_id = "/2016-09-08-Some-title.html"
    var url = "https://joearms.github.io/published" + x.disqus_id;
    var t = `

    <meta charset="UTF-8">
    <title>${x.title} - ${site_title()}</title>
    <link href="${dots(x)}/src/style.css" rel="stylesheet" type="text/css"></link>

${site_title()}

	    ${site_links(x)}

${x.title}

	  ${x.data}

	  Tweet

Comments:

	`;
    return t;
}

<|endoftext|>


<commit_before>// @flow

import $ from 'jquery'
import * as capsid from '../index.js'
import cj from '../plugins/jquery-plugin.js'
import { Foo, Bar } from './fixture.js'

global.$ = $
global.__DEV__ = true
global.capsidDebugMessage = () => {}

;(cj: any)(capsid, $)

before(() => {
  capsid.def('foo', Foo)
  capsid.def('bar', Bar)
})

export const clearComponents = () =>
  Object.keys(capsid.__ccc__).forEach(key => {
    delete capsid.__ccc__[key]
  })

/**
 * @param {Function} decorator The decorator
 * @param {Function} cls The class
 * @param {string} key The key of the method to decorate
 */
export const callDecorator = (decorator: Function, cls: Function, key: string) => {
  const descriptor = Object.getOwnPropertyDescriptor(cls.prototype, key)
  const result = decorator(cls.prototype, key, descriptor)
  Object.defineProperty(cls.prototype, key, result || descriptor)
}
<commit_msg>fix: fix minor flow error<commit_after>// @flow

import $ from 'jquery'
import * as capsid from '../index.js'
import cj from '../plugins/jquery-plugin.js'
import { Foo, Bar } from './fixture.js'

global.$ = $
global.__DEV__ = true
global.capsidDebugMessage = () => {}

;(cj: any)(capsid, $)

before(() => {
  capsid.def('foo', Foo)
  capsid.def('bar', Bar)
})

export const clearComponents = () =>
  Object.keys(capsid.__ccc__).forEach(key => {
    delete capsid.__ccc__[key]
  })

/**
 * @param {Function} decorator The decorator
 * @param {Function} cls The class
 * @param {string} key The key of the method to decorate
 */
export const callDecorator = (decorator: Function, cls: Function, key: string) => {
  const descriptor = Object.getOwnPropertyDescriptor(cls.prototype, key)
  const result = decorator(cls.prototype, key, descriptor)
  Object.defineProperty(cls.prototype, key, result || descriptor || {})
}
<|endoftext|>


<commit_before>import { LogMessage } from '../message';
import { Slack, Fluentd, Console } from '../service';
import Level from '../enum/level';
import Logger from '../logger';

describe('logger', () => {
  describe('config', () => {
    it('should accept object', () => {
      expect(() => new Logger({ key: 'value' })).not.toThrow('invalid config');
    });

    it('should not accept string', () => {
      expect(() => new Logger('not object')).toThrow('invalid config');
    });

    it('should not accept integer', () => {
      expect(() => new Logger(1)).toThrow('invalid config');
    });

    it('should not accept null', () => {
      expect(() => new Logger(null)).toThrow('invalid config');
    });

    it('should not accept array', () => {
      expect(() => new Logger([3, 4, 5])).toThrow('invalid config');
    });

    it('should initiate proper services according to config', () => {
      const originalSlackConfigCheck = Slack.prototype.IsConfigValid;
      const originalFluentdConfigCheck = Fluentd.prototype.IsConfigValid;
      const originalConsoleConfigCheck = Console.prototype.IsConfigValid;
      Slack.prototype.IsConfigValid = jest.fn(originalSlackConfigCheck);
      Fluentd.prototype.IsConfigValid = jest.fn(originalFluentdConfigCheck);
      Console.prototype.IsConfigValid = jest.fn(originalConsoleConfigCheck);

      const config = {
        base: {
          project: 'cool project',
          environment: 'production',
        },
        Slack: {
          logLevel: Level.DEBUG,
          slackToken: 'token',
          slackChannel: 'slack channel',
        },
        // disable console logger
        Console: false,
        // fluentd logger config is missing
      };

      const logger = new Logger(config);

      expect(logger.services).toHaveLength(1);
      expect(logger.services[0]).toBeInstanceOf(Slack);
      expect(logger.services[0].config).toEqual(
        Object.assign({}, config.base, config.Slack)
      );
      expect(Slack.prototype.IsConfigValid).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.IsConfigValid).not.toHaveBeenCalled();
      expect(Console.prototype.IsConfigValid).not.toHaveBeenCalled();

      Slack.prototype.IsConfigValid = originalSlackConfigCheck;
      Fluentd.prototype.IsConfigValid = originalFluentdConfigCheck;
      Console.prototype.IsConfigValid = originalConsoleConfigCheck;
    });

    it('should accept process env override', () => {
      process.env.LOG_LEVEL = Level.INFO;

      const config = {
        base: {
          logLevel: Level.WARN,
          project: 'cool project',
          environment: 'production',
        },
        Slack: {
          logLevel: Level.ERROR,
          slackToken: 'token',
          slackChannel: 'slack channel',
        },
        Console: true,
        Fluentd: {
          collectorUrl: 'collector URL',
        },
      };

      const logger = new Logger(config);

      expect(logger.services).toHaveLength(3);
      expect(logger.services[0]).toBeInstanceOf(Slack);
      expect(logger.services[0].config).toEqual(
        Object.assign({}, config.base, config.Slack)
      );

      delete process.env.LOG_LEVEL;
    });
  });

  describe('logging', () => {
    const message = 'something happened';
    const label = 'some:label';
    const originalSlackLog = Slack.prototype.Log;
    const originalFluentdLog = Fluentd.prototype.Log;
    const originalConsoleLog = Console.prototype.Log;
    let config;

    beforeEach(() => {
      Slack.prototype.Log = jest.fn(() => Promise.resolve());
      Fluentd.prototype.Log = jest.fn(() => Promise.resolve());
      Console.prototype.Log = jest.fn(() => Promise.resolve());

      config = {
        base: {
          logLevel: Level.INFO,
          project: 'cool project',
          environment: 'production',
        },
        Slack: {
          logLevel: Level.ERROR,
          slackToken: 'token',
          slackChannel: 'slack channel',
        },
        Console: true,
        Fluentd: {
          collectorUrl: 'collector URL',
        },
      };
    });

    afterAll(() => {
      Slack.prototype.Log = originalSlackLog;
      Fluentd.prototype.Log = originalFluentdLog;
      Console.prototype.Log = originalConsoleLog;
    });

    it('should call each service and pass through message', () => {
      const logger = new Logger(config);

      logger.Log(Level.ERROR, new LogMessage(message), label);

      expect(logger.services).toHaveLength(3);
      expect(Slack.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Slack.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
    });

    it('should skip services with incomplete config', () => {
      const originalSlackConfigCheck = Slack.prototype.IsConfigValid;
      Slack.prototype.IsConfigValid = jest.fn(() => false);

      const logger = new Logger(config);

      logger.Log(Level.ERROR, new LogMessage(message), label);

      expect(logger.services).toHaveLength(2);
      expect(Slack.prototype.Log).not.toHaveBeenCalled();
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);

      Slack.prototype.IsConfigValid = originalSlackConfigCheck;
    });

    it('should partially disable some services depending on log level', () => {
      const logger = new Logger(config);

      logger.Log(Level.WARN, new LogMessage(message), label);

      expect(logger.services).toHaveLength(3);
      expect(Slack.prototype.Log).not.toHaveBeenCalled();
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
    });

    it('should be able to preset label and pass through message', () => {
      const logger = new Logger(config).Label(label);

      logger.Log(Level.WARN, new LogMessage(message));

      expect(Slack.prototype.Log).not.toHaveBeenCalled();
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
    });

    it('should wait for logger to finish in promise', () => {
      // delay log services
      const delay = new Promise(resolve => setTimeout(resolve, 1000));
      const logFinished = jest.fn(() => Promise.resolve());
      Slack.prototype.Log = jest.fn(() => delay.then(logFinished));
      Fluentd.prototype.Log = jest.fn(() => delay.then(logFinished));
      Console.prototype.Log = jest.fn(() => delay.then(logFinished));

      const logger = new Logger(config).Label(label);

      return logger.Log(Level.WARN, new LogMessage(message))
        .then(() => {
          expect(Slack.prototype.Log).not.toHaveBeenCalled();
          expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
          expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
          expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
          expect(Console.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
          expect(logFinished).toHaveBeenCalledTimes(2);
        });
    });
  });
});
<commit_msg>revert changes in logger test<commit_after>import { LogMessage } from '../message';
import { Slack, Fluentd, Console } from '../service';
import Level from '../enum/level';
import Logger from '../logger';

describe('logger', () => {
  describe('config', () => {
    it('should accept object', () => {
      expect(() => new Logger({ key: 'value' })).not.toThrow('invalid config');
    });

    it('should not accept string', () => {
      expect(() => new Logger('not object')).toThrow('invalid config');
    });

    it('should not accept integer', () => {
      expect(() => new Logger(1)).toThrow('invalid config');
    });

    it('should not accept null', () => {
      expect(() => new Logger(null)).toThrow('invalid config');
    });

    it('should not accept array', () => {
      expect(() => new Logger([3, 4, 5])).toThrow('invalid config');
    });

    it('should initiate proper services according to config', () => {
      const originalSlackConfigCheck = Slack.prototype.IsConfigValid;
      const originalFluentdConfigCheck = Fluentd.prototype.IsConfigValid;
      const originalConsoleConfigCheck = Console.prototype.IsConfigValid;
      Slack.prototype.IsConfigValid = jest.fn(originalSlackConfigCheck);
      Fluentd.prototype.IsConfigValid = jest.fn(originalFluentdConfigCheck);
      Console.prototype.IsConfigValid = jest.fn(originalConsoleConfigCheck);

      const config = {
        base: {
          project: 'cool project',
          environment: 'production',
        },
        Slack: {
          logLevel: Level.DEBUG,
          slackToken: 'token',
          slackChannel: 'slack channel',
        },
        // disable console logger
        Console: false,
        // fluentd logger config is missing
      };

      const logger = new Logger(config);

      expect(logger.services).toHaveLength(1);
      expect(logger.services[0]).toBeInstanceOf(Slack);
      expect(logger.services[0].config).toEqual(
        Object.assign({}, config.base, config.Slack)
      );
      expect(Slack.prototype.IsConfigValid).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.IsConfigValid).not.toHaveBeenCalled();
      expect(Console.prototype.IsConfigValid).not.toHaveBeenCalled();

      Slack.prototype.IsConfigValid = originalSlackConfigCheck;
      Fluentd.prototype.IsConfigValid = originalFluentdConfigCheck;
      Console.prototype.IsConfigValid = originalConsoleConfigCheck;
    });
  });

  describe('logging', () => {
    const message = 'something happened';
    const label = 'some:label';
    const originalSlackLog = Slack.prototype.Log;
    const originalFluentdLog = Fluentd.prototype.Log;
    const originalConsoleLog = Console.prototype.Log;
    let config;

    beforeEach(() => {
      Slack.prototype.Log = jest.fn(() => Promise.resolve());
      Fluentd.prototype.Log = jest.fn(() => Promise.resolve());
      Console.prototype.Log = jest.fn(() => Promise.resolve());

      config = {
        base: {
          logLevel: Level.INFO,
          project: 'cool project',
          environment: 'production',
        },
        Slack: {
          logLevel: Level.ERROR,
          slackToken: 'token',
          slackChannel: 'slack channel',
        },
        Console: true,
        Fluentd: {
          collectorUrl: 'collector URL',
        },
      };
    });

    afterAll(() => {
      Slack.prototype.Log = originalSlackLog;
      Fluentd.prototype.Log = originalFluentdLog;
      Console.prototype.Log = originalConsoleLog;
    });

    it('should call each service and pass through message', () => {
      const logger = new Logger(config);

      logger.Log(Level.ERROR, new LogMessage(message), label);

      expect(logger.services).toHaveLength(3);
      expect(Slack.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Slack.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
    });

    it('should skip services with incomplete config', () => {
      const originalSlackConfigCheck = Slack.prototype.IsConfigValid;
      Slack.prototype.IsConfigValid = jest.fn(() => false);

      const logger = new Logger(config);

      logger.Log(Level.ERROR, new LogMessage(message), label);

      expect(logger.services).toHaveLength(2);
      expect(Slack.prototype.Log).not.toHaveBeenCalled();
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.ERROR, new LogMessage(message), label);

      Slack.prototype.IsConfigValid = originalSlackConfigCheck;
    });

    it('should partially disable some services depending on log level', () => {
      const logger = new Logger(config);

      logger.Log(Level.WARN, new LogMessage(message), label);

      expect(logger.services).toHaveLength(3);
      expect(Slack.prototype.Log).not.toHaveBeenCalled();
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
    });

    it('should be able to preset label and pass through message', () => {
      const logger = new Logger(config).Label(label);

      logger.Log(Level.WARN, new LogMessage(message));

      expect(Slack.prototype.Log).not.toHaveBeenCalled();
      expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
      expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
      expect(Console.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
    });

    it('should wait for logger to finish in promise', () => {
      // delay log services
      const delay = new Promise(resolve => setTimeout(resolve, 1000));
      const logFinished = jest.fn(() => Promise.resolve());
      Slack.prototype.Log = jest.fn(() => delay.then(logFinished));
      Fluentd.prototype.Log = jest.fn(() => delay.then(logFinished));
      Console.prototype.Log = jest.fn(() => delay.then(logFinished));

      const logger = new Logger(config).Label(label);

      return logger.Log(Level.WARN, new LogMessage(message))
        .then(() => {
          expect(Slack.prototype.Log).not.toHaveBeenCalled();
          expect(Fluentd.prototype.Log).toHaveBeenCalledTimes(1);
          expect(Fluentd.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
          expect(Console.prototype.Log).toHaveBeenCalledTimes(1);
          expect(Console.prototype.Log).toHaveBeenCalledWith(Level.WARN, new LogMessage(message), label);
          expect(logFinished).toHaveBeenCalledTimes(2);
        });
    });
  });
});
<|endoftext|>


<commit_before>var utils = require('../utils/httpUtils.js');
var _ = require('underscore');
var constants = require('../utils/constants.js');

exports.create = function(options) {
  var shares = require('../share/share.js')(options.apiUrls.reports);

  var optionsToSend = {
    url: options.apiUrls.reports,
    accessToken : options.accessToken
  };

  var getReport = function(getOptions, callback) {
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var sendReportViaEmail = function(postOptions, callback) {
    optionsToSend.url = options.apiUrls.reports + postOptions.reportId + '/emails';
    return utils.post(_.extend(optionsToSend, postOptions), callback);
  };

  var getReportAsExcel = function(getOptions, callback) {
    optionsToSend.accept = 'application/vnd.ms-excel';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var getReportAsCSV = function(getOptions, callback) {
    optionsToSend.accept = 'text/csv';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var getReportPublishStatus = function(getOptions, callback) {
    optionsToSend.url = options.apiUrls.reports + getOptions.reportId + '/publish';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var buildReportObject = function() {
    var reportObject = {
      listReports : getReport,
      getReport         : getReport,
      sendReportViaEmail : sendReportViaEmail,
      getReportAsExcel : getReportAsExcel,
      getReportAsCSV : getReportAsCSV,
      getReportPublishStatus : getReportPublishStatus
    };

    reportObject = _.extend(reportObject, shares.create(options));
    return reportObject;
  };

  return buildReportObject();
};
<commit_msg>Add endpoint: 'Set Report Publish Status'<commit_after>var utils = require('../utils/httpUtils.js');
var _ = require('underscore');
var constants = require('../utils/constants.js');

exports.create = function(options) {
  var shares = require('../share/share.js')(options.apiUrls.reports);

  var optionsToSend = {
    url: options.apiUrls.reports,
    accessToken : options.accessToken
  };

  var getReport = function(getOptions, callback) {
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var sendReportViaEmail = function(postOptions, callback) {
    optionsToSend.url = options.apiUrls.reports + postOptions.reportId + '/emails';
    return utils.post(_.extend(optionsToSend, postOptions), callback);
  };

  var getReportAsExcel = function(getOptions, callback) {
    optionsToSend.accept = 'application/vnd.ms-excel';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var getReportAsCSV = function(getOptions, callback) {
    optionsToSend.accept = 'text/csv';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var getReportPublishStatus = function(getOptions, callback) {
    optionsToSend.url = options.apiUrls.reports + getOptions.reportId + '/publish';
    return utils.get(_.extend(optionsToSend, getOptions), callback);
  };

  var setReportPublishStatus = function(putOptions, callback) {
    optionsToSend.url = options.apiUrls.reports + putOptions.reportId + '/publish';
    return utils.put(_.extend(optionsToSend, putOptions), callback);
  };

  var buildReportObject = function() {
    var reportObject = {
      listReports : getReport,
      getReport         : getReport,
      sendReportViaEmail : sendReportViaEmail,
      getReportAsExcel : getReportAsExcel,
      getReportAsCSV : getReportAsCSV,
      getReportPublishStatus : getReportPublishStatus,
      setReportPublishStatus : setReportPublishStatus
    };

    reportObject = _.extend(reportObject, shares.create(options));
    return reportObject;
  };

  return buildReportObject();
};
<|endoftext|>


<commit_before>export default class NPC02 extends Phaser.Sprite {
    constructor(game) {
        super(game, 1450, 850, 'npc02', 0);

        // enable interaction with player
        this.scale.setTo(1.1);
        this.inputEnabled = true;
        this.events.onInputDown.add(this.startDialogue, this);
    }
    startDialogue() {
        this.game.dialogue = JSON.parse(this.game.cache.getText('dialogue'));
        this.totalCorrect = 0;
        this.party = [];
        this.id = this.game.dialogue.start;
        this.showDialogue(this.game.dialogue, this.id);
    }
    showDialogue(dialogue, id) {
        let x = 50, y = 700;

        // show question
        let question = dialogue['elements'][id].npc;
        this.style = {
            font: "22px Arial",
            fill: "white",
            align: "center",
            backgroundColor: "000"
        };
        this.question = this.game.add.text (
            this.game.world.centerX+x, y, question, this.style
        );

        // show answers and add input to click
        let answers = dialogue['elements'][id].character;
        this.answers_set = [];
        for (var i in answers) {
            this.answers_set[i] = this.game.add.text (
                this.game.world.centerX+x, y+=60, answers[i][i], this.style
            );
            this.answers_set[i].inputEnabled = true;
            this.answers_set[i].events.onInputDown.add(this.checkAnswer, this)
        }
    }
    checkAnswer(selected) {
        let selectedAnswer = selected.text;
        let correctAnswer = this.game.dialogue['elements'][this.id].correct;
        if (selectedAnswer == correctAnswer) {
            this.assignParty();
        } else {
            console.log("You got it wrong...");
        }
        this.updateDialogue();
    }
    updateDialogue() {
        // update id to point to next question
        this.id = this.game.dialogue['elements'][this.id].followup;
        if (this.id == "") {
            this.startBattle(this.party);
        }

        // remove question and answers from game
        this.question.destroy();
        this.answers_set.forEach(function(answer) { answer.destroy() });
        this.showDialogue(this.game.dialogue, this.id);
    }
    assignParty() {
        this.party.push({ name: 'thief' });
    }
    startBattle(party) {
        this.game.dialogue = JSON.parse(this.game.cache.getText('dialogue'));
        this.game.state.start('Battle', true, false, party)
    }
}
<commit_msg>added save feature to questions portion<commit_after>export default class NPC02 extends Phaser.Sprite {
    constructor(game) {
        super(game, 1450, 850, 'npc02', 0);

        // enable interaction with player
        this.scale.setTo(1.1);
        this.inputEnabled = true;
        this.events.onInputDown.add(this.startDialogue, this);
    }
    startDialogue() {
        this.game.dialogue = JSON.parse(this.game.cache.getText('dialogue'));
        this.totalCorrect = 0;
        this.party = [];
        this.id = this.game.dialogue.start;
        this.showDialogue(this.game.dialogue, this.id);
    }
    showDialogue(dialogue, id) {
        let x = 50, y = 700;

        // show question
        let question = dialogue['elements'][id].npc;
        this.style = {
            font: "22px Arial",
            fill: "white",
            align: "center",
            backgroundColor: "000"
        };
        this.question = this.game.add.text (
            this.game.world.centerX+x, y, question, this.style
        );

        // show answers and add input to click
        let answers = dialogue['elements'][id].character;
        this.answers_set = [];
        for (var i in answers) {
            this.answers_set[i] = this.game.add.text (
                this.game.world.centerX+x, y+=60, answers[i][i], this.style
            );
            this.answers_set[i].inputEnabled = true;
            this.answers_set[i].events.onInputDown.add(this.checkAnswer, this)
        }
    }
    checkAnswer(selected) {
        let selectedAnswer = selected.text;
        let correctAnswer = this.game.dialogue['elements'][this.id].correct;
        if(Cookies.get('NPC02') === undefined){
            Cookies.set('NPC02', '0', { expires: 7 });
        }
        if (selectedAnswer == correctAnswer) {
            var counterCookie = parseInt(Cookies.get('NPC02')) + 1;
            Cookies.set('NPC02', counterCookie.toString(), { expires: 7 });
            this.assignParty();
        } else {
            console.log("You got it wrong...");
        }
        this.updateDialogue();
    }
    updateDialogue() {
        // update id to point to next question
        this.id = this.game.dialogue['elements'][this.id].followup;
        if (this.id == "") {
            this.startBattle(this.party);
        }

        // remove question and answers from game
        this.question.destroy();
        this.answers_set.forEach(function(answer) { answer.destroy() });
        this.showDialogue(this.game.dialogue, this.id);
    }
    assignParty() {
        this.party.push({ name: 'thief' });
    }
    startBattle(party) {
        this.game.dialogue = JSON.parse(this.game.cache.getText('dialogue'));
        this.game.state.start('Battle', true, false, party)
    }
}
<|endoftext|>


<commit_before>import reserved from '../utils/reserved.js';
import CompileError from '../utils/CompileError.js';

const letConst = /^(?:let|const)$/;

const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';

export default function Scope ( options ) {
	options = options || {};

	this.parent = options.parent;
	this.canMangle = !!this.parent;
	this.isBlockScope = !!options.block;
	this.useStrict = this.parent && this.parent.useStrict;

	// vars declared in blocks are stored here, so that we
	// can hoist them if those blocks are removed but the
	// declarations are used. TODO an alternative approach
	// would be to replace instances of the hoisted var
	// with `void 0`
	this.varDeclarations = new Set();
	this.hoistedVars = new Set();
	this.varDeclarationNodes = [];

	let scope = this;
	while ( scope.isBlockScope ) scope = scope.parent;
	this.functionScope = scope;

	this.identifiers = [];
	this.declarations = Object.create( null );
	this.references = Object.create( null );
	this.blockScopedDeclarations = this.isBlockScope ? null : Object.create( null );
	this.aliases = Object.create( null );

	this.idCounter = [ 0 ];
}

Scope.prototype = {
	addAlias ( alias ) {
		this.aliases[ alias ] = true;
		if ( this.parent ) this.parent.addAlias( alias );
	},

	addDeclaration ( identifier, kind ) {
		if ( kind === 'var' && this.isBlockScope ) {
			this.varDeclarations.add( identifier.name );
			this.parent.addDeclaration( identifier, kind );
			return;
		}

		const { name } = identifier;

		const existingDeclaration = this.declarations[ name ];
		if ( existingDeclaration ) {
			if ( letConst.test( kind ) || letConst.test( existingDeclaration.kind ) ) {
				// TODO warn about double var declarations?
				throw new CompileError( identifier, `${name} is already declared` );
			}

			// special case — function expression IDs that are shadowed by
			// declarations should just be removed (TODO unless the user wishes
			// to keep function names — https://github.com/Rich-Harris/butternut/issues/17)
			if ( existingDeclaration.node.parent.type === 'FunctionExpression' ) {
				existingDeclaration.node.parent.shadowed = true;
			}

			else {
				identifier.isDuplicate = true;

				if ( existingDeclaration.activated ) {
					identifier.activate();
				} else {
					existingDeclaration.duplicates.push( identifier );
				}

				return;
			}
		}

		const declaration = {
			activated: !this.parent, // TODO is this necessary?
			name,
			node: identifier,
			kind,
			instances: [],
			duplicates: []
		};

		this.declarations[ name ] = declaration;

		if ( this.isBlockScope ) {
			if ( !this.functionScope.blockScopedDeclarations[ name ] ) this.functionScope.blockScopedDeclarations[ name ] = [];
			this.functionScope.blockScopedDeclarations[ name ].push( declaration );
		}

		if ( kind === 'param' ) {
			declaration.instances.push( identifier );
		}
	},

	addReference ( identifier ) {
		const declaration = this.declarations[ identifier.name ];
		if ( declaration ) {
			declaration.instances.push( identifier );

			if ( !declaration.activated ) {
				declaration.activated = true;
				// const parent = declaration.node.parent;

				declaration.node.activate();
				declaration.duplicates.forEach( dupe => {
					dupe.activate();
				});
				// if ( declaration.kind === 'param' ) {
				// 	// TODO is there anything to do here?
				// } else if ( parent.activate ) {
				// 	parent.activate();
				// }
			}
		} else {
			this.references[ identifier.name ] = true;
			if ( this.parent ) this.parent.addReference( identifier );
		}
	},

	contains ( name ) {
		return this.declarations[ name ] ||
		       ( this.parent ? this.parent.contains( name ) : false );
	},

	containsAlias ( alias ) {
		return this.aliases[ alias ] || ( this.parent && this.parent.containsAlias( alias ) );
	},

	createIdentifier ( used ) {
		let alias;

		do {
			alias = this.idCounter.map( i => validChars[i] ).join( '' );

			let i = this.idCounter.length;
			while ( i-- ) {
				this.idCounter[i] += 1;
				if ( this.idCounter[i] === validChars.length ) {
					this.idCounter[i] = 0;

					if ( i === 0 ) this.idCounter.push( 0 );
				} else {
					break;
				}
			}
		} while ( used[ alias ] || reserved[ alias ] );

		return alias;
	},

	deopt () {
		if ( !this.deopted ) {
			this.deopted = true;
			this.canMangle = false;

			if ( this.parent ) this.parent.deopt();

			Object.keys( this.declarations ).forEach( name => {
				this.declarations[name].node.activate();
			});
		}
	},

	findDeclaration ( name ) {
		return this.declarations[ name ] ||
		       ( this.parent && this.parent.findDeclaration( name ) );
	},

	mangle ( code ) {
		if ( !this.canMangle ) return;

		let used = Object.create( null );

		Object.keys( this.references ).forEach( reference => {
			const declaration = this.parent && this.parent.findDeclaration( reference );
			used[ declaration && declaration.alias || reference ] = true;
		});

		Object.keys( this.declarations ).forEach( name => {
			const declaration = this.declarations[ name ];
			if ( declaration.instances.length === 0 ) return;

			// special case — function expression IDs may be removed outright
			if ( declaration.node.parent.type === 'FunctionExpression' && declaration.node === declaration.node.parent.id ) {
				if ( declaration.node.shadowed || declaration.instances.length === 1 ) return;
			}

			declaration.alias = this.createIdentifier( used );

			declaration.instances.forEach( instance => {
				const replacement = instance.parent.type === 'Property' && instance.parent.shorthand ?
					`${instance.name}:${declaration.alias}` :
					declaration.alias;

				code.overwrite( instance.start, instance.end, replacement, true );
			});
		});
	}
};
<commit_msg>remove unused methods<commit_after>import reserved from '../utils/reserved.js';
import CompileError from '../utils/CompileError.js';

const letConst = /^(?:let|const)$/;

const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';

export default function Scope ( options ) {
	options = options || {};

	this.parent = options.parent;
	this.canMangle = !!this.parent;
	this.isBlockScope = !!options.block;
	this.useStrict = this.parent && this.parent.useStrict;

	// vars declared in blocks are stored here, so that we
	// can hoist them if those blocks are removed but the
	// declarations are used. TODO an alternative approach
	// would be to replace instances of the hoisted var
	// with `void 0`
	this.varDeclarations = new Set();
	this.hoistedVars = new Set();
	this.varDeclarationNodes = [];

	let scope = this;
	while ( scope.isBlockScope ) scope = scope.parent;
	this.functionScope = scope;

	this.identifiers = [];
	this.declarations = Object.create( null );
	this.references = Object.create( null );
	this.blockScopedDeclarations = this.isBlockScope ? null : Object.create( null );
	this.aliases = Object.create( null );

	this.idCounter = [ 0 ];
}

Scope.prototype = {
	addDeclaration ( identifier, kind ) {
		if ( kind === 'var' && this.isBlockScope ) {
			this.varDeclarations.add( identifier.name );
			this.parent.addDeclaration( identifier, kind );
			return;
		}

		const { name } = identifier;

		const existingDeclaration = this.declarations[ name ];
		if ( existingDeclaration ) {
			if ( letConst.test( kind ) || letConst.test( existingDeclaration.kind ) ) {
				// TODO warn about double var declarations?
				throw new CompileError( identifier, `${name} is already declared` );
			}

			// special case — function expression IDs that are shadowed by
			// declarations should just be removed (TODO unless the user wishes
			// to keep function names — https://github.com/Rich-Harris/butternut/issues/17)
			if ( existingDeclaration.node.parent.type === 'FunctionExpression' ) {
				existingDeclaration.node.parent.shadowed = true;
			}

			else {
				identifier.isDuplicate = true;

				if ( existingDeclaration.activated ) {
					identifier.activate();
				} else {
					existingDeclaration.duplicates.push( identifier );
				}

				return;
			}
		}

		const declaration = {
			activated: !this.parent, // TODO is this necessary?
			name,
			node: identifier,
			kind,
			instances: [],
			duplicates: []
		};

		this.declarations[ name ] = declaration;

		if ( this.isBlockScope ) {
			if ( !this.functionScope.blockScopedDeclarations[ name ] ) this.functionScope.blockScopedDeclarations[ name ] = [];
			this.functionScope.blockScopedDeclarations[ name ].push( declaration );
		}

		if ( kind === 'param' ) {
			declaration.instances.push( identifier );
		}
	},

	addReference ( identifier ) {
		const declaration = this.declarations[ identifier.name ];
		if ( declaration ) {
			declaration.instances.push( identifier );

			if ( !declaration.activated ) {
				declaration.activated = true;
				// const parent = declaration.node.parent;

				declaration.node.activate();
				declaration.duplicates.forEach( dupe => {
					dupe.activate();
				});
				// if ( declaration.kind === 'param' ) {
				// 	// TODO is there anything to do here?
				// } else if ( parent.activate ) {
				// 	parent.activate();
				// }
			}
		} else {
			this.references[ identifier.name ] = true;
			if ( this.parent ) this.parent.addReference( identifier );
		}
	},

	contains ( name ) {
		return this.declarations[ name ] ||
		       ( this.parent ? this.parent.contains( name ) : false );
	},

	createIdentifier ( used ) {
		let alias;

		do {
			alias = this.idCounter.map( i => validChars[i] ).join( '' );

			let i = this.idCounter.length;
			while ( i-- ) {
				this.idCounter[i] += 1;
				if ( this.idCounter[i] === validChars.length ) {
					this.idCounter[i] = 0;

					if ( i === 0 ) this.idCounter.push( 0 );
				} else {
					break;
				}
			}
		} while ( used[ alias ] || reserved[ alias ] );

		return alias;
	},

	deopt () {
		if ( !this.deopted ) {
			this.deopted = true;
			this.canMangle = false;

			if ( this.parent ) this.parent.deopt();

			Object.keys( this.declarations ).forEach( name => {
				this.declarations[name].node.activate();
			});
		}
	},

	findDeclaration ( name ) {
		return this.declarations[ name ] ||
		       ( this.parent && this.parent.findDeclaration( name ) );
	},

	mangle ( code ) {
		if ( !this.canMangle ) return;

		let used = Object.create( null );

		Object.keys( this.references ).forEach( reference => {
			const declaration = this.parent && this.parent.findDeclaration( reference );
			used[ declaration && declaration.alias || reference ] = true;
		});

		Object.keys( this.declarations ).forEach( name => {
			const declaration = this.declarations[ name ];
			if ( declaration.instances.length === 0 ) return;

			// special case — function expression IDs may be removed outright
			if ( declaration.node.parent.type === 'FunctionExpression' && declaration.node === declaration.node.parent.id ) {
				if ( declaration.node.shadowed || declaration.instances.length === 1 ) return;
			}

			declaration.alias = this.createIdentifier( used );

			declaration.instances.forEach( instance => {
				const replacement = instance.parent.type === 'Property' && instance.parent.shorthand ?
					`${instance.name}:${declaration.alias}` :
					declaration.alias;

				code.overwrite( instance.start, instance.end, replacement, true );
			});
		});
	}
};
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
/**
 * @module geo
 */

/*jslint devel: true, forin: true, newcap: true, plusplus: true*/
/*jslint white: true, indent: 2*/

/*global geo, ogs, inherit, document$*/
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class feature
 *
 * @class
 * @returns {geo.feature}
 */
//////////////////////////////////////////////////////////////////////////////
geo.feature = function(arg) {
  "use strict";
  if (!(this instanceof geo.feature)) {
    return new geo.feature(arg);
  }
  geo.object.call(this);

  ////////////////////////////////////////////////////////////////////////////
  /**
   * @private
   */
  ////////////////////////////////////////////////////////////////////////////
  arg = arg || {};

  var m_style = {},
      m_layer = arg.layer === undefined ? null : arg.layer,
      m_gcs = arg.gcs === undefined ? "EPSG:4326" : arg.gcs,
      m_renderer = arg.renderer === undefined ? null : arg.renderer,
      m_dataTime = geo.timestamp(),
      m_buildTime = geo.timestamp(),
      m_updateTime = geo.timestamp();

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set style used by the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.style = function(arg1, arg2) {
    if (arg1 === undefined ) {
      return m_style;
    }  else if (arg2 === undefined) {
      m_style = $.extend({}, m_style, arg1);
      this.modified();
      return this;
    } else {
      m_style[arg1] = arg2;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get layer referenced by the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.layer = function() {
    return m_layer;
  }

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get renderer used by the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.renderer = function() {
    return m_renderer;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set projection of the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.gcs = function(val) {
    if (val === undefined ) {
      return m_gcs;
    } else {
      m_gcs = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set timestamp of data change
   */
  ////////////////////////////////////////////////////////////////////////////
  this.dataTime = function(val) {
    if (val === undefined ) {
      return m_dataTime;
    } else {
      m_dataTime = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set timestamp of last time build happened
   */
  ////////////////////////////////////////////////////////////////////////////
  this.buildTime = function(val) {
    if (val === undefined ) {
      return m_buildTime;
    } else {
      m_buildTime = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set timestamp of last time update happened
   */
  ////////////////////////////////////////////////////////////////////////////
  this.updateTime = function(val) {
    if (val === undefined ) {
      return m_updateTime;
    } else {
      m_updateTime = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Initialize
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._init = function(arg) {
    if (!m_layer) {
      throw "Feature requires a valid layer";
    }
    m_style = $.extend({},
                {"opacity": 1.0}, arg.style === undefined ? {} :
                arg.style);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Build
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._build = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._update = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Destroy
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._exit = function() {
  };

  this._init(arg);
  return this;
};

inherit(geo.feature, geo.object);
<commit_msg>Added API to get context specific drawables/nodes<commit_after>//////////////////////////////////////////////////////////////////////////////
/**
 * @module geo
 */

/*jslint devel: true, forin: true, newcap: true, plusplus: true*/
/*jslint white: true, indent: 2*/

/*global geo, ogs, inherit, document$*/
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class feature
 *
 * @class
 * @returns {geo.feature}
 */
//////////////////////////////////////////////////////////////////////////////
geo.feature = function(arg) {
  "use strict";
  if (!(this instanceof geo.feature)) {
    return new geo.feature(arg);
  }
  geo.object.call(this);

  ////////////////////////////////////////////////////////////////////////////
  /**
   * @private
   */
  ////////////////////////////////////////////////////////////////////////////
  arg = arg || {};

  var m_style = {},
      m_layer = arg.layer === undefined ? null : arg.layer,
      m_gcs = arg.gcs === undefined ? "EPSG:4326" : arg.gcs,
      m_renderer = arg.renderer === undefined ? null : arg.renderer,
      m_dataTime = geo.timestamp(),
      m_buildTime = geo.timestamp(),
      m_updateTime = geo.timestamp();

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set style used by the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.style = function(arg1, arg2) {
    if (arg1 === undefined ) {
      return m_style;
    }  else if (arg2 === undefined) {
      m_style = $.extend({}, m_style, arg1);
      this.modified();
      return this;
    } else {
      m_style[arg1] = arg2;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get layer referenced by the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.layer = function() {
    return m_layer;
  }

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get renderer used by the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.renderer = function() {
    return m_renderer;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get list of drawables or nodes that are context/api specific.
   */
  ////////////////////////////////////////////////////////////////////////////
  this.drawables = function() {
    return this._drawables();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set projection of the feature
   */
  ////////////////////////////////////////////////////////////////////////////
  this.gcs = function(val) {
    if (val === undefined ) {
      return m_gcs;
    } else {
      m_gcs = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set timestamp of data change
   */
  ////////////////////////////////////////////////////////////////////////////
  this.dataTime = function(val) {
    if (val === undefined ) {
      return m_dataTime;
    } else {
      m_dataTime = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set timestamp of last time build happened
   */
  ////////////////////////////////////////////////////////////////////////////
  this.buildTime = function(val) {
    if (val === undefined ) {
      return m_buildTime;
    } else {
      m_buildTime = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set timestamp of last time update happened
   */
  ////////////////////////////////////////////////////////////////////////////
  this.updateTime = function(val) {
    if (val === undefined ) {
      return m_updateTime;
    } else {
      m_updateTime = val;
      this.modified();
      return this;
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Initialize
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._init = function(arg) {
    if (!m_layer) {
      throw "Feature requires a valid layer";
    }
    m_style = $.extend({},
                {"opacity": 1.0}, arg.style === undefined ? {} :
                arg.style);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Build
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._build = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get context specific drawables
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._drawables = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._update = function() {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Destroy
   *
   * Derived class should implement this
   */
  ////////////////////////////////////////////////////////////////////////////
  this._exit = function() {
  };

  this._init(arg);
  return this;
};

inherit(geo.feature, geo.object);
<|endoftext|>