<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>burningrizen</title>
    <link>https://burningrizen.tistory.com/</link>
    <description>Records of django, python, unity3d, c #, apache2, ubuntu, related development and other interests

(django, python, unity3d, c#, apache2, ubuntu, 관련 개발과 다른 관심있는 것들의 기록)</description>
    <language>ko</language>
    <pubDate>Tue, 14 Apr 2026 15:25:41 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>burningrizen</managingEditor>
    <item>
      <title>[gui] tkinter 로 다중 option menu 구현</title>
      <link>https://burningrizen.tistory.com/288</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;KakaoTalk_20201129_194615328.png&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;318&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BiGxi/btqOvepHnpi/JQCihfG9HM3jsXfPUi0zPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BiGxi/btqOvepHnpi/JQCihfG9HM3jsXfPUi0zPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BiGxi/btqOvepHnpi/JQCihfG9HM3jsXfPUi0zPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBiGxi%2FbtqOvepHnpi%2FJQCihfG9HM3jsXfPUi0zPK%2Fimg.png&quot; data-filename=&quot;KakaoTalk_20201129_194615328.png&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;318&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1606646317772&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import tkinter as tk


class OptionMenu:
    width = 90
    font = (&quot;Ubuntu&quot;, 12)
    side = &quot;top&quot;

    label = None
    menus = list()

    @classmethod
    def create_menus(cls, win, menus):
        cls.menus = [{&quot;menu&quot;: OptionMenu(option_list=menu, win=win, index=i), &quot;text&quot;: menu[0]} for i, menu in enumerate(menus)]
        OptionMenu.add_label()

    def __init__(self, option_list=None, win=None, index=None):
        self.option_list = option_list
        self.var = tk.StringVar(win)
        self.var.set(self.option_list[0])
        self.var.trace(&quot;w&quot;, self.callback)

        self.index = index
        self.menu = tk.OptionMenu(win, self.var, *self.option_list)
        self.menu.config(width=OptionMenu.width, font=OptionMenu.font)
        self.menu.pack(side=OptionMenu.side)

    def callback(self, *args):
        OptionMenu.menus[self.index][&quot;text&quot;] = self.var.get()
        OptionMenu.set_label()

    @classmethod
    def add_label(cls):
        cls.label = tk.Label(text=&quot;&quot;, font=cls.font, fg='blue')
        cls.label.pack(side=&quot;top&quot;)

    @classmethod
    def set_label(cls):
        texts = [menu[&quot;text&quot;] for menu in cls.menus]
        dress = Fashion.get_dress(texts)
        cls.label.configure(text=dress)


class Fashion:
    season = None
    temperature = None
    is_accessories = None
    is_comfortable = None
    is_outer = None

    options = [
        (&quot;봄&quot;, &quot;여름&quot;, &quot;가을&quot;, &quot;겨울&quot;),
        (&quot;따뜻한&quot;, &quot;시원한&quot;),
        (&quot;악세사리 착용&quot;, &quot;악세사리 없음&quot;),
        (&quot;편안한 신발&quot;, &quot;편안하지 않은 신발&quot;),
        (&quot;겉옷 착용&quot;, &quot;겉옷 없음&quot;),
    ]

    tops = {
        &quot;봄&quot;: {&quot;따뜻한&quot;: &quot;빨간색 긴팔&quot;, &quot;시원한&quot;: &quot;흰색 긴팔&quot;},
        &quot;여름&quot;: {&quot;따뜻한&quot;: &quot;빨간색 반팔&quot;, &quot;시원한&quot;: &quot;흰색 반팔&quot;},
        &quot;가을&quot;: {&quot;따뜻한&quot;: &quot;빨간색 니트&quot;, &quot;시원한&quot;: &quot;파란색 니트&quot;},
        &quot;겨울&quot;: {&quot;따뜻한&quot;: &quot;빨간색 목폴라&quot;, &quot;시원한&quot;: &quot;파란색 니트&quot;},
    }
    bottoms = {
        &quot;봄&quot;: {&quot;따뜻한&quot;: &quot;진한 청바지&quot;, &quot;시원한&quot;: &quot;연한 청치마&quot;},
        &quot;여름&quot;: {&quot;따뜻한&quot;: &quot;베이지 면치마&quot;, &quot;시원한&quot;: &quot;연한 숏 청바지&quot;},
        &quot;가을&quot;: {&quot;따뜻한&quot;: &quot;베이지 긴바지&quot;, &quot;시원한&quot;: &quot;하늘색 원피스&quot;},
        &quot;겨울&quot;: {&quot;따뜻한&quot;: &quot;베이지 긴바지&quot;, &quot;시원한&quot;: &quot;체크무늬 롱셔츠&quot;},
    }
    accessories = {
        &quot;봄&quot;: {&quot;따뜻한&quot;: &quot;검정 에코백&quot;, &quot;시원한&quot;: &quot;네이비 캡&quot;},
        &quot;여름&quot;: {&quot;따뜻한&quot;: &quot;흰색 캡&quot;, &quot;시원한&quot;: &quot;하늘색 팔찌&quot;},
        &quot;가을&quot;: {&quot;따뜻한&quot;: &quot;갈색 머플러&quot;, &quot;시원한&quot;: &quot;베이지 머플러&quot;},
        &quot;겨울&quot;: {&quot;따뜻한&quot;: &quot;갈색 머플러&quot;, &quot;시원한&quot;: &quot;검정 머플러&quot;},
    }
    outers = {
        &quot;봄&quot;: &quot;트렌치코트&quot;,
        &quot;여름&quot;: &quot;흰색 롱셔츠&quot;,
        &quot;가을&quot;: &quot;트렌치코트&quot;,
        &quot;겨울&quot;: &quot;베이지울코트&quot;,
    }
    shoes = {
        &quot;봄&quot;: {&quot;따뜻한&quot;: {&quot;편안한 신발&quot;: &quot;흰색 캔버스&quot;, &quot;편안하지 않은 신발&quot;: &quot;갈색워커&quot;},
              &quot;시원한&quot;: {&quot;편안한 신발&quot;: &quot;검정 캔버스&quot;, &quot;편안하지 않은 신발&quot;: &quot;검정 로퍼&quot;}, },

        &quot;여름&quot;: {&quot;따뜻한&quot;: {&quot;편안한 신발&quot;: &quot;흰색 캔버스&quot;, &quot;편안하지 않은 신발&quot;: &quot;검정 구두&quot;},
               &quot;시원한&quot;: {&quot;편안한 신발&quot;: &quot;흰색 샌들&quot;, &quot;편안하지 않은 신발&quot;: &quot;흰색 워커&quot;}, },

        &quot;가을&quot;: {&quot;따뜻한&quot;: {&quot;편안한 신발&quot;: &quot;검정 캔버스&quot;, &quot;편안하지 않은 신발&quot;: &quot;검정 구두&quot;},
               &quot;시원한&quot;: {&quot;편안한 신발&quot;: &quot;흰색 캔버스&quot;, &quot;편안하지 않은 신발&quot;: &quot;검정 로퍼&quot;}, },

        &quot;겨울&quot;: {&quot;따뜻한&quot;: {&quot;편안한 신발&quot;: &quot;검정 캔버스&quot;, &quot;편안하지 않은 신발&quot;: &quot;검정 구두&quot;},
               &quot;시원한&quot;: {&quot;편안한 신발&quot;: &quot;흰색 캔버스&quot;, &quot;편안하지 않은 신발&quot;: &quot;검정 워커&quot;}, },
    }

    @classmethod
    def convert(cls, words):
        cls.season, cls.temperature, cls.is_accessories, cls.is_comfortable, cls.is_outer = words

    @classmethod
    def get_dress(cls, words):
        cls.convert(words)
        top = cls.tops[cls.season][cls.temperature]
        bottom = cls.bottoms[cls.season][cls.temperature]
        accessory = cls.accessories[cls.season][cls.temperature] if &quot;없음&quot; not in cls.is_accessories else &quot;없음&quot;
        outer = cls.outers[cls.season] if &quot;없음&quot; not in cls.is_outer else &quot;없음&quot;
        shoe = cls.shoes[cls.season][cls.temperature][cls.is_comfortable]

        return f&quot;상의: {top}\n하의: {bottom}\n악세사리: {accessory}\n겉옷: {outer}\n신발: {shoe}&quot;


app = tk.Tk()
app.title(&quot;Fashion&quot;)
app.geometry('400x250')
OptionMenu.create_menus(app, Fashion.options)
app.mainloop()

&lt;/code&gt;&lt;/pre&gt;</description>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/288</guid>
      <comments>https://burningrizen.tistory.com/288#entry288comment</comments>
      <pubDate>Sun, 29 Nov 2020 19:48:42 +0900</pubDate>
    </item>
    <item>
      <title>구글크롬원격</title>
      <link>https://burningrizen.tistory.com/287</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://remotedesktop.google.com/support/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;remotedesktop.google.com/support/&lt;/a&gt;&lt;/p&gt;</description>
      <category>common</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/287</guid>
      <comments>https://burningrizen.tistory.com/287#entry287comment</comments>
      <pubDate>Wed, 25 Nov 2020 20:05:53 +0900</pubDate>
    </item>
    <item>
      <title>[python] 호텔 평점 프로젝트</title>
      <link>https://burningrizen.tistory.com/286</link>
      <description></description>
      <category>python lecture/project</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/286</guid>
      <comments>https://burningrizen.tistory.com/286#entry286comment</comments>
      <pubDate>Sun, 8 Nov 2020 21:40:21 +0900</pubDate>
    </item>
    <item>
      <title>[Python] Pillow 영상처리 이미지 회전</title>
      <link>https://burningrizen.tistory.com/285</link>
      <description>&lt;pre id=&quot;code_1602683964464&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import math
from PIL import Image


def rotate(x, y, theta, pi=3.14):
    radian = theta * pi / 180
    sin = math.sin(radian)
    cos = math.cos(radian)
    new_x = cos*x - sin*y
    new_y = sin*x + cos*y
    return new_x, new_y


def rotate_img(ori, theta):
    dst = Image.new(&quot;RGB&quot;, ori.size, (0, 0, 0))
    width, height = ori.size
    pixels_dst = dst.load()
    pixels_ori = ori.load()
    for y in range(height):
        for x in range(width):
            rotate_x, rotate_y = rotate(x, y, theta)
            if 0 &amp;lt;= rotate_x &amp;lt; width and 0 &amp;lt;= rotate_y &amp;lt; height:
                pixels_dst[rotate_x, rotate_y] = pixels_ori[x, y]
    return dst


img = Image.open(&quot;./img/rirak.jpg&quot;)
dst = rotate_img(img, 5)
img.show()
dst.show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이차원 좌표에서 이미지 회전 공식&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;99038F3359CBA85A1D.png&quot; data-origin-width=&quot;261&quot; data-origin-height=&quot;52&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8hhCW/btqKVP08IKn/gzQEP7kdjNebOkNOqg3qLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8hhCW/btqKVP08IKn/gzQEP7kdjNebOkNOqg3qLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8hhCW/btqKVP08IKn/gzQEP7kdjNebOkNOqg3qLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8hhCW%2FbtqKVP08IKn%2FgzQEP7kdjNebOkNOqg3qLk%2Fimg.png&quot; data-filename=&quot;99038F3359CBA85A1D.png&quot; data-origin-width=&quot;261&quot; data-origin-height=&quot;52&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;파이썬에서 각세타가 아니라 라디안으로 math 함수에 인자를 넣어야함&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;라디안 = 세타 * pi / 180&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>python lecture/project</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/285</guid>
      <comments>https://burningrizen.tistory.com/285#entry285comment</comments>
      <pubDate>Wed, 14 Oct 2020 23:09:04 +0900</pubDate>
    </item>
    <item>
      <title>[python] 은행프로그램</title>
      <link>https://burningrizen.tistory.com/284</link>
      <description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1. 계좌생성&lt;/p&gt;
&lt;p&gt;&amp;gt; 예금주 계좌번호 입금액&lt;/p&gt;
&lt;p&gt;2. 입금&lt;/p&gt;
&lt;p&gt;&amp;gt; 계좌번호 입금액&lt;/p&gt;
&lt;p&gt;3. 출금&lt;/p&gt;
&lt;p&gt;&amp;gt; 계좌번호 출금액&lt;/p&gt;
&lt;p&gt;4. 이체&lt;/p&gt;
&lt;p&gt;&amp;gt; 출금계좌번호 입금계좌번호 액수&lt;/p&gt;
&lt;p&gt;5. 조회&lt;/p&gt;
&lt;p&gt;&amp;gt; 계좌번호&lt;/p&gt;
&lt;p&gt;6. 저장&lt;/p&gt;
&lt;p&gt;&amp;gt; 파일로 일괄저장&lt;/p&gt;
&lt;p&gt;&amp;gt; 계좌번호.txt&amp;nbsp;&lt;br /&gt;&amp;gt; 계좌번호 파일에 통장이력은 아래와 같음&lt;/p&gt;
&lt;p&gt;(기록시간, 입금 혹은 출금, 액수, 잔액)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1593694915158&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import datetime


class Log:
    def __init__(self, add=0, sub=0, balance=0):
        self.now = datetime.datetime.now()
        if add:
            self.add = add
        if sub:
            self.sub = sub
        self.balance = balance

    def __str__(self):
        return f&quot;{','.join(map(str, self.__dict__.items()))}&quot;


class Account:
    def __init__(self, name, number):
        self.name = name
        self.number = number
        self.logs = list()
        self.balance = 0

    def add(self, add=0, sub=0):
        if add:
            self.balance += add
        if sub:
            self.balance -= sub
        log = Log(add=add, sub=sub, balance=self.balance)
        self.logs.append(log)

    def send(self, other, amount):
        self.add(sub=amount)
        other.add(add=amount)

    def __get_logs(self):
        return &quot;\n&quot;.join(map(str, self.logs))

    def write(self):
        with open(f&quot;./out/{self.number}.txt&quot;, &quot;w&quot;) as f:
            f.writelines(self.__get_logs())

    def __str__(self):
        head = f&quot;name={self.name} number={self.number}\n&quot;
        body = self.__get_logs()
        return head + body


class Bank:
    def __init__(self):
        self.accounts = list()

    def find_account(self, number):
        accounts = list(filter(lambda account: account.number == number, self.accounts))
        return accounts[0] if accounts else None

    def create(self, name, number, amount):
        if not self.find_account(number):
            account = Account(name, number)
            account.add(add=amount)
            self.accounts.append(account)
            print(account)

    def deposit(self, number, amount):
        account = self.find_account(number)
        if account:
            account.add(add=amount)
            print(account)

    def withdrawal(self, number, amount):
        account = self.find_account(number)
        if account:
            account.add(sub=amount)
            print(account)

    def remittance(self, start_number, target_number, amount):
        start_account = self.find_account(start_number)
        target_account = self.find_account(target_number)
        if start_number and target_number:
            start_account.send(target_account, amount)
            print(start_account)
            print(target_account)

    def show_account(self, number):
        account = self.find_account(number)
        if account:
            print(account)

    def write(self):
        for account in self.accounts:
            account.write()


class CmdManager:
    def __init__(self):
        pass


def main():
    bank = Bank()
    while True:
        menu = input(&quot;메뉴를 입력 하시오\n&quot;)
        if menu == &quot;1&quot;:
            cmd = input(&quot;개설할 계좌 예금주, 계좌번호, 입금금액을 입력하시오\n&quot;).split()
            name, number, amount = cmd[0], cmd[1], int(cmd[2])
            bank.create(name=name, number=number, amount=amount)

        elif menu == &quot;2&quot;:
            cmd = input(&quot;입글할 계좌번호와 금액을 입력하시오\n&quot;).split()
            if len(cmd) == 2:
                number, amount = cmd[0], int(cmd[1])
                bank.deposit(number=number, amount=amount)

        elif menu == &quot;3&quot;:
            cmd = input(&quot;출금할 계좌번호와 금액을 입력하시오\n&quot;).split()
            if len(cmd) == 2:
                number, amount = cmd[0], int(cmd[1])
                bank.withdrawal(number=number, amount=amount)

        elif menu == &quot;4&quot;:
            cmd = input(&quot;이체할 계좌번호, 입금할 계좌번호, 금액을 입력하시오\n&quot;).split()
            if len(cmd) == 3:
                start_number, target_number, amount = cmd[0], cmd[1], int(cmd[2])
                bank.remittance(start_number=start_number, target_number=target_number, amount=amount)

        elif menu == &quot;5&quot;:
            cmd = input(&quot;조회할 계좌번호를 입력하시오\n&quot;).split()
            if len(cmd) == 1:
                number = cmd[0]
                bank.show_account(number)

        elif menu == &quot;6&quot;:
            bank.write()
            exit(&quot;수업종료&quot;)
        else:
            print(&quot;잘못된 명령어 입니다.&quot;)


main()
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>python lecture/project</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/284</guid>
      <comments>https://burningrizen.tistory.com/284#entry284comment</comments>
      <pubDate>Thu, 2 Jul 2020 22:13:19 +0900</pubDate>
    </item>
    <item>
      <title>[python] inner 함수, 이너 함수</title>
      <link>https://burningrizen.tistory.com/283</link>
      <description>&lt;p&gt;1. inner 를 리턴해서 메모리에서 inner 가 해제되지 않는다.&lt;/p&gt;
&lt;p&gt;2. 변수 a 가 해제되지 않는다.&lt;/p&gt;
&lt;p&gt;3. 함수형 프로그래밍에서 상태값을 유지할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1593442978246&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def wrapper():
    a = 0

    def inner():
        nonlocal a
        a += 1
        return a
    return inner


f = wrapper()
for _ in range(10):
    print(f())

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>development/python</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/283</guid>
      <comments>https://burningrizen.tistory.com/283#entry283comment</comments>
      <pubDate>Tue, 30 Jun 2020 00:10:45 +0900</pubDate>
    </item>
    <item>
      <title>[python] 지하철 승하차 기록 조회</title>
      <link>https://burningrizen.tistory.com/282</link>
      <description>&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;승하차기록파일&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/6W8H6/btqEGC7vLg5/QKbHSwNPcsQc6hJmykFmGk/metro.zip.001?attach=1&amp;amp;knm=tfile.001&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;metro.zip.001&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.02MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1. 년월, 역이름 으로 필터&lt;/p&gt;
&lt;p&gt;2. 필터된 승하차 총합을 구함&lt;/p&gt;
&lt;p&gt;3. plotly 설치후 그래프로 표시&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591509577197&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def read_file(path):
    with open(path, &quot;r&quot;) as f:
        return f.readlines()


class Log:
    def __init__(self, date=None, line=None, station=None, in_outs=None):
        self.date = date
        self.line = line
        self.station = station
        self.in_outs = in_outs

    def __str__(self):
        return f&quot;{self.__dict__}&quot;

    @classmethod
    def line_to_list(cls, line):
        line = line.replace('&quot;', &quot;&quot;).replace(&quot;\n&quot;, &quot;&quot;)
        line = line.split(&quot;,&quot;)
        return line

    @classmethod
    def __get_times(cls, times):
        in_outs = {}
        time_stamp = 4
        for i, in_out in enumerate(times):
            if i + 1 &amp;lt; len(times):
                key = f&quot;{'0'+str(time_stamp) if time_stamp &amp;lt; 10 else time_stamp}&quot; \
                      f&quot;{'0'+str(time_stamp+1) if time_stamp+1 &amp;lt; 10 else time_stamp+1}&quot;
                in_outs[key] = (times[i], times[i+1])
                time_stamp += 1
        return in_outs

    @classmethod
    def line_to_ins(cls, line):
        line = cls.line_to_list(line)
        params = list()
        params.append(line[0])
        params.append(line[1])
        params.append(line[2])
        params.append(cls.__get_times(line[3:]))
        return params


class LogManager:
    def __init__(self, path):
        self.lines = read_file(path)
        self.logs = list()

    def import_logs(self, start, stop):
        for line in self.lines[start:] if stop == -1 else self.lines[start:stop]:
            log = Log(*Log.line_to_ins(line))
            self.__add(log)

    def __add(self, item):
        self.logs.append(item)

    def get_logs(self):
        return self.logs

    @classmethod
    def __filter_station(cls, logs, station):
        return list(filter(lambda log: log.station == station, logs))

    @classmethod
    def __filter_date(cls, logs, date):
        return list(filter(lambda log: log.date == date, logs))

    @classmethod
    def __get_summary_in_outs(cls, logs):
        in_outs = [0, 0]
        for log in logs:
            for in_val, out_val in log.in_outs.values():
                in_outs[0] += int(in_val)
                in_outs[1] += int(out_val)
        return in_outs

    def __get_in_outs_from_date_station(self, station, date):
        logs = LogManager.__filter_station(self.logs, station)
        logs = LogManager.__filter_date(logs, date)
        for log in logs:
            print(log)
        return LogManager.__get_summary_in_outs(logs)

    def draw_in_outs_from_date_station(self, station, date):
        in_outs = self.__get_in_outs_from_date_station(station=station, date=date)
        print(in_outs)
        import plotly.express as px
        df = px.data.tips()
        fig = px.histogram(df, title=f&quot;station={station} date={date}&quot;, x=[&quot;in&quot;, &quot;out&quot;], y=in_outs)
        fig.show()


if __name__ == '__main__':
    log_manager = LogManager(&quot;out/metro.csv&quot;)
    log_manager.import_logs(1, -1)
    print(&quot;파일 임포트 완료되었습니다.&quot;)
    while True:
        cmd = input(&quot;[역이름] [년월] 입력하세요\n&quot;).split(&quot; &quot;)
        if len(cmd) == 2:
            log_manager.draw_in_outs_from_date_station(*cmd)
        else:
            print(&quot;잘못된 명령어 입니다.&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>python lecture/project</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/282</guid>
      <comments>https://burningrizen.tistory.com/282#entry282comment</comments>
      <pubDate>Sun, 7 Jun 2020 15:08:08 +0900</pubDate>
    </item>
    <item>
      <title>[python] n 진수 바꾸기</title>
      <link>https://burningrizen.tistory.com/281</link>
      <description>&lt;p&gt;십진수 를 n 진수로 변경하기&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591191822063&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def foo(r, base):
    tokens = &quot;0123456789ABCDEF&quot;
    result = &quot;&quot;
    q = r
    while q:
        q, r = divmod(q, base)
        n = tokens[r]
        result = n + result
    return result


print(foo(23, 5))&lt;/code&gt;&lt;/pre&gt;</description>
      <category>python lecture/project</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/281</guid>
      <comments>https://burningrizen.tistory.com/281#entry281comment</comments>
      <pubDate>Wed, 3 Jun 2020 22:51:07 +0900</pubDate>
    </item>
    <item>
      <title>[python] 시간변환</title>
      <link>https://burningrizen.tistory.com/280</link>
      <description>&lt;p&gt;시간 데이타 파일&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p&gt;22&amp;nbsp;25&amp;nbsp;0 &lt;br /&gt;5&amp;nbsp;30&amp;nbsp;195 &lt;br /&gt;17&amp;nbsp;40&amp;nbsp;200 &lt;br /&gt;17&amp;nbsp;15&amp;nbsp;210 &lt;br /&gt;0&amp;nbsp;40&amp;nbsp;-50 &lt;br /&gt;8&amp;nbsp;40&amp;nbsp;-200 &lt;br /&gt;22&amp;nbsp;10&amp;nbsp;-50 &lt;br /&gt;2&amp;nbsp;15&amp;nbsp;910 &lt;br /&gt;23&amp;nbsp;20&amp;nbsp;100 &lt;br /&gt;10&amp;nbsp;50&amp;nbsp;-20 &lt;br /&gt;8&amp;nbsp;40&amp;nbsp;200&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bG5aTp/btqEC8FAcY5/xRNyeB5oFCrYRxMqcVUKhK/data.txt?attach=1&amp;amp;knm=tfile.txt&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;data.txt&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;결과&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p&gt;22:25 &lt;br /&gt;8:45 &lt;br /&gt;21:0 &lt;br /&gt;20:45 &lt;br /&gt;23:50 &lt;br /&gt;5:20 &lt;br /&gt;21:20 &lt;br /&gt;17:25 &lt;br /&gt;1:0 &lt;br /&gt;10:30 &lt;br /&gt;12:0&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/kMBz6/btqEBnDUnOe/r81TpY5XjNenr33wkRgAMK/output.txt?attach=1&amp;amp;knm=tfile.txt&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;output.txt&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1590550706685&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def read_file(path):
    with open(path, &quot;r&quot;) as f:
        return f.readlines()


def write_file(path, lines):
    with open(path, &quot;w&quot;) as f:
        f.writelines(lines)


def lines_to_rows(lines):
    rows = list(map(lambda x: x.replace(&quot;\n&quot;, &quot;&quot;).split(&quot; &quot;), lines))
    for i, row in enumerate(rows):
        rows[i] = list(map(int, rows[i]))
    return rows


def row_to_time(row):
    hours, mins = row[0], row[1]+row[2]
    final_hours = mins // 60 + hours
    final_mins = mins % 60
    if final_hours &amp;gt; 24:
        final_hours -= 24
    if final_hours &amp;lt; 0:
        final_hours += 24
    return final_hours, final_mins


def convert(rows):
    times = []
    for i, row in enumerate(rows):
        time = row_to_time(row)
        times.append(f&quot;{i+1}: time={time[0]}:{time[1]}&quot;)
    return &quot;\n&quot;.join(times)


lines = read_file(&quot;data.txt&quot;)
rows = lines_to_rows(lines)
times = convert(rows)
write_file(&quot;reuslt.txt&quot;, times)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>python lecture/project</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/280</guid>
      <comments>https://burningrizen.tistory.com/280#entry280comment</comments>
      <pubDate>Wed, 27 May 2020 12:38:38 +0900</pubDate>
    </item>
    <item>
      <title>[python] 스테가노그래피</title>
      <link>https://burningrizen.tistory.com/279</link>
      <description>&lt;p&gt;원본, 히든 이미지&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bRfaZF/btqEEfjIobA/4SQyd4vPTRhFYkbpCb3kcK/dog.jpg?attach=1&amp;amp;knm=img.jpg&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;dog.jpg&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.06MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/mCZN7/btqFecm8Ktv/kvfE58RH9NHWqN6mscdda1/hidden.jpg?attach=1&amp;amp;knm=img.jpg&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;hidden.jpg&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.02MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://m.blog.naver.com/PostView.nhn?blogId=aepkoreanet&amp;amp;logNo=221342395644&amp;amp;proxyReferer=https:%2F%2Fwww.google.com%2F&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;스테가노그래피 설명&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Pillow 라이브러리 설치&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591501728177&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PIL import Image as image


def encoding(dec, data):
    val = bin(dec)[:-1] + (&quot;1&quot; if data else &quot;0&quot;)
    return int(val, 2)


def decoding(dec):
    return 255 if int(bin(dec)[-1]) else 0


def encoding_pixel(color_ori, color_data):
    r = encoding(color_ori[0], color_data[0] if isinstance(color_data, tuple) else color_data)
    g = encoding(color_ori[1], color_data[1] if isinstance(color_data, tuple) else color_data)
    b = encoding(color_ori[2], color_data[2] if isinstance(color_data, tuple) else color_data)
    return r, g, b


def decoding_pixel(color_ori):
    return decoding(color_ori[0]), decoding(color_ori[1]), decoding(color_ori[2])


def insert(ori_img, data_img):
    if ori_img.size != data_img.size:
        raise ValueError(&quot;Image size is difference&quot;)
    dst = image.new(&quot;RGB&quot;, ori_img.size, (0, 0, 0))
    width, height = ori_img.size
    pixels_ori = ori_img.load()
    pixels_dst = dst.load()
    pixels_data = data_img.load()
    for y in range(height):
        for x in range(width):
            color_ori = pixels_ori[x, y]
            color_data = pixels_data[x, y]
            encoding_pixel(color_ori, color_data)
            pixels_dst[x, y] = encoding_pixel(color_ori, color_data)
    return dst


def extract(ori):
    dst = image.new(&quot;RGB&quot;, ori.size, (0, 0, 0))
    width, height = ori.size
    pixels_dst = dst.load()
    pixels_ori = ori.load()
    for y in range(height):
        for x in range(width):
            color = pixels_ori[x, y]
            pixels_dst[x, y] = decoding_pixel(color)
    return dst


if __name__ == '__main__':
    ori = image.open(&quot;./img/dog.jpg&quot;)
    data = image.open(&quot;./img/hidden.png&quot;)
    ori.show()
    data.show()
    input(&quot;press and start encoding&quot;)
    new_img = insert(ori, data)
    new_img.save(&quot;./img/encoding.png&quot;)
    new_img.show()
    input(&quot;encoding is done\npress and start decoding&quot;)
    decoding_img = extract(new_img)
    decoding_img.show()
    decoding_img.save(&quot;./img/decoding.png&quot;)
    input(&quot;decoding is done&quot;)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>python lecture/project</category>
      <author>burningrizen</author>
      <guid isPermaLink="true">https://burningrizen.tistory.com/279</guid>
      <comments>https://burningrizen.tistory.com/279#entry279comment</comments>
      <pubDate>Mon, 25 May 2020 23:33:03 +0900</pubDate>
    </item>
  </channel>
</rss>