Python
Linux
上司への愛情
LivesenseDay 12

上司のターミナルにマトリックスを走らせよう!

More than 3 years have passed since last update.

Livesense Advent Caelendar 2015 12日目担当の@sion_cojpです。


振り返り・・・

前はインフラエンジニアとして働いており、ムカついたときは上司のターミナルに汽車を走らせてました。

今はWebアプリエンジニアとして部署異動し、APIを開発しております。


この記事をご覧になっている、そこのあなた。

仕事中にこんなことはありませんか?



部署異動したけど、やっぱり上司から無理な依頼をされた。ちくしょう。。。

わかります。その気持ち。ええ。

せっかく異動したんだから、高い寿司とかおごってくれてもいいのに。。

でも異動出来た事には感謝しないとです。社会って複雑ですよね。








そんな上司の作業中のターミナル(端末)にマトリックスを走らせてやりましょう!!








まずは準備。



①上司が作業しているホストを探そう

何かしらの方法でげっとします。(鬼門)

またまた私は上司のモニターを後ろからこっそり覗いてやりました。






のんびりPHPのレガシーコードと格闘してるわ。


馬鹿め。

上司が開発しているサーバ情報をげっと。


②マトリックスを流すプログラムを書く。

適当に作る。

MATRIX_ANGRY_CHARS に怒りの気持ちをぶつけましょう。

プログラムを流すと分かりますが、怒りの部分はバレないようになってるので安心してください。


MATRIX_THANKS_CHARS には感謝の気持ちを入れましょう。


matrix_curses.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from __future__ import unicode_literals
import locale
import time
import curses
import sys, string
import random
import struct
locale.setlocale(locale.LC_ALL, '')
encoding = locale.getpreferredencoding()

########################################################################
# const

MIN_SPEED = 1
MAX_SPEED = 2
MATRIX_ANGRY_CHARS = "遅刻連絡くらいメールじゃなくてチャットでいいじゃん 波動拳打ち込みたい ほぼ逝きかけました"
MATRIX_THANKS_CHARS = "THANKS DEAR TAKU !!!"
MATRIX_COLOR_WORD = 46
MATRIX_COLOR_BACK = 232

########################################################################

class FallingChar(object):
matrixchr = list(MATRIX_ANGRY_CHARS)
normal_attr = curses.A_NORMAL
highlight_attr = curses.A_REVERSE

def __init__(self, width, MIN_SPEED, MAX_SPEED):
self.x = 0
self.y = 0
self.speed = 1
self.char = ' '
self.reset(width, MIN_SPEED, MAX_SPEED)

def reset(self, width, MIN_SPEED, MAX_SPEED):
self.char = random.choice(FallingChar.matrixchr).encode(encoding)
self.x = random.randint(1, width - 1)
self.y = 0
self.speed = random.randint(MIN_SPEED, MAX_SPEED)

def tick(self, scr):
height, width = scr.getmaxyx()
self.out_of_screen_reset(width, height)
scr.addstr(self.y, self.x, self.char, curses.color_pair(1))
self.char = random.choice(FallingChar.matrixchr).encode(encoding)
self.y += 1
if not self.out_of_screen_reset(width, height):
scr.addstr(self.y, self.x, self.char, curses.A_REVERSE)

def out_of_screen_reset(self, width, height):
if self.x > width-2:
self.reset(width, MIN_SPEED, MAX_SPEED)
return True
if self.y > height-2:
self.reset(width, MIN_SPEED, MAX_SPEED)
return True
return False

def rand():
a = 1
while True:
a ^= (a << 1);
a ^= (a >> 135);
a ^= (a << 104);
yield a

r = rand()
def randint(_min, _max):
n = r.next()
return (n % (_max - _min)) + _min

def color():
curses.start_color()
curses.init_pair(1, MATRIX_COLOR_WORD, MATRIX_COLOR_BACK)
curses.curs_set(0)
curses.noecho()

def main():
scr = curses.initscr()
scr.nodelay(1)
color()

height, width = scr.getmaxyx()
lines = []
for i in range(8):
l = FallingChar(width, MIN_SPEED, MAX_SPEED)
lines.append(l)

scr.refresh()
while True:
for line in lines:
line.tick(scr)
for i in range(30):
x = randint(0, width-1)
y = randint(0, height-1)
scr.addstr(y, x, ' ')

scr.refresh()
time.sleep(0.04)

def last_main():
curses.endwin()
curses.curs_set(1)
curses.reset_shell_mode()
curses.echo()

screen = curses.initscr()
color()
lastchr = string.join(list(MATRIX_THANKS_CHARS), " ")

last_height, last_width = screen.getmaxyx()
start_width = last_width/2 - len(lastchr)/2
for i in range(last_height/2):
screen.clear()
screen.addstr(i, start_width, lastchr, curses.color_pair(1))
screen.refresh()
time.sleep(0.2)
screen.getch()
curses.endwin()

try:
main()
except KeyboardInterrupt:
try:
last_main()
except KeyboardInterrupt:
curses.endwin()
curses.curs_set(1)
curses.reset_shell_mode()
curses.echo()



テストで走らせてみよう

$ python /tmp/matrix_curses.py






よし。


④上司のターミナルにマトリックスを走らせよう!

$ w

私の上司、takuが/dev/pts/○○ だと言う事が判明。

すかさずコマンド投入。

$ python /tmp/matrix_curses.py > /dev/pts/○○







mymovie1.gif





次に、自分が満足したり、上司の怒りがマックスになったところで、ctrl + cを押す。





mymovie2.gif



THANKS DEAR TAKU!!!


達成。本当にありがとうございました。


⑤最後に

障害時など、大事なときはダメ。絶対。

決して怒らない、ユーモアたっぷりで温厚で優しい上司にやってね!