退屈なことはPythonにやらせよう。の本を読む前にイメージでやってみる。luaで。

# 概要

[退屈なことはPythonにやらせよう](https://www.oreilly.co.jp/books/9784873117782/)という本がある。
とてもよさげな本っぽいので、いつか読みたい。
が、今お金とか時間とかの都合でなかなか手が出せない。

どうするか考えた結果、``退屈なことをPythonにやらせる為のlua``を学ぶ事にした。
なぜなら手元に本があったから。

方針としては、

 + Python -> 退屈なことをする
 + lua -> 退屈なことを生み出す

何言ってるかわからないかもしれないので、先に結果を出そう。

# 結果

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42445/abfd3c1b-ddd4-9dc8-154e-d06bb39503c6.png)

<font color="hotpink">結果を見てもよく分からないねコレ</font>

一応コードは[こちら]。

# 言語の役割分担を考える

退屈な事が何か考えた時に、真っ先に思い浮かぶのが人間関係だ。

 + 上司からの「俺のほうが経験ある」マウンティング
 + チーム内での「俺のほうが知ってる」マウンティング
 + よく知らない人からの「何ができるの？」マウンティング

世の中マウンティングだらけ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42445/cd16a18d-5dd4-fda9-4b43-2ded4f6694b0.png)

<font color="hotpink">つかれるよね</font>

というわけで

 + Python -> マウンティングをいなす人
 + lua -> マウンティングする人

言葉で説明してもあれなので、図に書いておこう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42445/0db6f263-902a-5d08-a682-2103008a08b9.png)

# luaでマウンティングする

早速luaでマウンティングする人を書いてゆく。

 + ストレスを持つ
 + ストレスには限界がある
 + 事あるごとにマウンティング
 + マウンティングするとストレスが下がる
 + 何もしなくてもストレスが上がる

別に個人的な意図はないがクラス名はJoushiにした。
(大事な事なのでもう一回書く。本当に個人的な意図はないです。)

## ストレスを持つ

ストレスにも限界を持たせる。

``` lua
Joushi = {
  stress = 0,
  stressThreshold = 100,
  socket = nil,
}

function Joushi.new()
  self = {__index = Joushi}
  o = {}
  return setmetatable(o, self)
end
```

## 事あるごとにマウンティング

事あるごとにを表現するのは難しい。今のところはランダムで待つ。(*1)
マウンティングはUDPで実装する。マウンティングはTCPみたいに丁寧ではないのだ。
マウンティングは5W1Hにしたがって質問形式のマウンティングを行う。
英語なのはエディタの日本語対応が面倒だったから。

``` lua
function Joushi.mounting(self)
  try {
    function()
      local socket = require("socket")
      local udp = socket.udp()
      udp:setsockname("127.0.0.1", 0)
      udp:setpeername("127.0.0.1", 1880)
      mountingText = self:getMountingText()
      udp:send(mountingText)

      print('Let\'s mounting!: '..mountingText )
      udp:settimeout(3)
      local data = udp:receive()
      if data == nil then
        print("he denied my conversation...")
      else
        print("now conversation succeed! "..data)
	self.stress = self.stress - 10
      end
      udp:close()
    end,
    catch {
      function(error)
        print(error)  -- raise errro
      end
    }
  }
end

function utf8_from(t)
  local bytearr = {}
  for _, v in ipairs(t) do
    local utf8byte = v < 0 and (0xff + v + 1) or v
    table.insert(bytearr, string.char(utf8byte))
  end
  return table.concat(bytearr)
end

function Joushi.getMountingText(self)
  local r = math.random(7)
  if r == 1 then
    -- when
    return "when are you gonna apologize?"
  elseif r == 2 then
    -- where
    return "where were you yesterday?"
  elseif r == 3 then
    -- who
    return "who do you respect?"
  elseif r == 4 then
    -- what
    return "what takes so much time?"
  elseif r == 5 then
    -- why
    return "why can not you?"
  elseif r == 6 then
    -- how
    return "how much are you?"
  else
    -- direct mounting
    return "hey my dog!"
  end
end

-- mounting toutine
co = coroutine.create(function()
  local r = math.random(10)
  while true do
    coroutine.yield() 
    if r <= 0 then
      joushi:mounting()
      r = math.random(10)
    else
      r = r - 1
    end
  end
end)

coroutine.resume(co)
```

[こちら](https://gist.github.com/cwarden/1207556)をもとにtry-cacheを導入

*1: 今のところはって言っても今後手を付ける予定もない。

## マウンティングするとストレスが下がる

マウンティングの成功でストレスを軽減する。

先のサンプルで```now conversation succeed```を言っているところで

``` lua
self.stress = self.stress - 10
```

としてある部分

## 何もしなくてもストレスが上がる

一定間隔でストレスを上げる。

``` lua
constantStress = coroutine.create(function()
  local r = math.random(2)
  while true do
    coroutine.yield() 
    if r <= 0 then
      joushi.stress = joushi.stress + 10
      r = math.random(2)
    else
      r = r - 1
    end
  end
end)

coroutine.resume(constantStress)
```

## 呼び出してみる

最後にjoushiを呼び出して動作を確認する。死んだら終わりにする。

```lua
print('I\'m still alive.')
while true do
  socket.sleep(1)
  coroutine.resume(co)
  coroutine.resume(constantStress)
  if joushi:checkStressLimit() then
    break
  else
    print("joushi stress: "..joushi.stress)
  end
end
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42445/7adf2c14-085d-e85d-8269-c536dd841494.png)

<font color="hotpink">人のストレスには限界がある</font>

# pythonでマウンティングをいなす

マウンティングする人ができたので今度はマウンティングをいなす人を書いてゆく。特徴としては

 + ストレスを持つ
 + マウンティングを受けて対応するし、マウンティングされるとストレスが上がる
 + 何もしなくてもストレスが上がる

## ストレスを持つ

ここはシンプルにグローバルで持たせる。もちろん限界も持たせる。  
上司より容量を持たせる。

```python
stress = 0
deadStressThreshold = 400
```

## マウンティングを受けて対応するし、マウンティングされるとストレスが上がる

ちょっと長いけどUDPで受けてストレス貯めてるだけ。

```python
class MountingStress(threading.Thread):
  def __init__(self):
    super(MountingStress, self).__init__()

    self.lock = threading.Lock()
    self.bStop = False

  def stop(self):
    with self.lock:
      self.bStop = True

  def run(self):
    global stress, deadStressThreshold
    host = '127.0.0.1'
    port = 1880
    buffSize = 2046
    while True:
      with self.lock:
        if self.bStop:
          return

      sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      with closing(sock):
        sock.settimeout(1.0)
        sock.bind((host, port))
  
        try:
          mountText, addr = sock.recvfrom(buffSize)
          print("Mount: {0}".format(mountText))
          stress += 20
          answer = ""
          if mountText == b"when are you gonna apologize?":
            stress += random.randint(20, 80)
            answer = "sorry, I'm wrong human..."
          elif mountText == b"where were you yesterday?":
            stress += random.randint(20, 80)
            answer = "sorry, was at home..."
          elif mountText == b"who do you respect?":
            stress += random.randint(20, 80)
            answer = "just only you!I'm Happy!"
          elif mountText == b"what takes so much time?":
            stress += random.randint(20, 80)
            answer = "sorry, my ability is missing..."
          elif mountText == b"why can not you?":
            stress += random.randint(20, 80)
            answer = "sorry, my ability is wrong..."
          elif mountText == b"how much are you?":
            stress += random.randint(20, 80)
            answer = "sorry, I am not worth..."
          elif mountText == b"hey my dog!":
            stress += random.randint(20, 80)
            answer = "yes! I'm dog! your dog! I'm Happy!"
          print("Answer: {0}".format(answer)) 
          print(" - mounting stress: {0}".format(stress))
          time.sleep(1)
          sock.sendto(bytes(answer, 'utf-8'), addr)
        except socket.timeout:
          pass
        except:
          # stress -= 5 
          import traceback
          traceback.print_exc()

      if stress < 0:
        stress = 0
      if stress >= deadStressThreshold:
        print("mounting stress break: {0}".format(stress))
        break
```


## 何もしなくてもストレスが上がる

人なので。

```python
class ConstantStress(threading.Thread):
  def __init__(self,interval):
    super(ConstantStress, self).__init__()

    self.interval = interval
    self.lock = threading.Lock()
    self.bStop = False

  def stop(self):
    with self.lock:
      self.bStop = True

  def run(self):
    global stress, deadStressThreshold
    while True:
      with self.lock:
        if self.bStop:
          return
      if stress >= deadStressThreshold:
        print("stress over deadline: {0}".format(stress))
        break
      stress = stress + 10
      time.sleep(self.interval)
    print("constant stress break: {0}".format(stress))
```

## 呼び出してみる

一定時間経つとちゃんとストレスで(プログラムが)終了する。

```python
def main():
  global stress, deadStressThreshold

  print('I\'m still alive.')
  # constant stress
  constantStress = ConstantStress(1)
  constantStress.start()

  mountingStress = MountingStress()
  mountingStress.start()

  constantStress.join()
  mountingStress.join()
  return

if __name__ == "__main__":
    main()
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42445/5db20eae-16b1-0c03-d8be-b81440796a57.png)


# より人間らしく

しません。


# ふりかえり

ストレスの代わりに血圧という単語を使おうとも思ったが、
リアルに傷つく方がいてはあれなのでやめた。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42445/d4806b48-a8cb-9f04-8c0a-ab4404ef0340.png)
<font color="hotpink">血圧は普段から気を付けたほうがいいらしいよ</font>