search
LoginSignup
0

More than 3 years have passed since last update.

posted at

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

概要

退屈なことはPythonにやらせようという本がある。
とてもよさげな本っぽいので、いつか読みたい。
が、今お金とか時間とかの都合でなかなか手が出せない。

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

方針としては、

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

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

結果

image.png

結果を見てもよく分からないねコレ

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

言語の役割分担を考える

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

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

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

image.png

つかれるよね

というわけで

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

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

image.png

luaでマウンティングする

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

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

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

ストレスを持つ

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

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

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

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

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

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)

こちらをもとにtry-cacheを導入

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

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

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

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

self.stress = self.stress - 10

としてある部分

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

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

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を呼び出して動作を確認する。死んだら終わりにする。

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

人のストレスには限界がある

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

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

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

ストレスを持つ

ここはシンプルにグローバルで持たせる。もちろん限界も持たせる。

上司より容量を持たせる。

stress = 0
deadStressThreshold = 400

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

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

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

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

人なので。

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

呼び出してみる

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

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

より人間らしく

しません。

ふりかえり

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

image.png
血圧は普段から気を付けたほうがいいらしいよ

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0