카테고리 보관물: 5. 토이프로젝트

간단한 연습용 프로젝트입니다.

대구대 정보 통합 창구(DU-Things)

Miscthings 동아리 활동을 하면서 다양한 서비스를 만들고 배포하고 있는데요.

사용자의 편의성을 증대하기 위해 기존에 진행하고 있는 서비스를 보완하고 통합 어플을 만들고자 합니다.

기존의 제작하고 있던 밥약과 다양한 정보들을 통합하여 제공하여 재학생의 만족도를 높여가는 서비스를 완성 시키도록 하겠습니다.

This is not a spaghetti, it’s jjamppong

밥약(5)

이번주는 밥약의 프론트 디자인을 진행하였습니다.

디자이너 안 선생님이 기존 제작하신 디자인 소스코드를 참고하여 진행하였습니다. 디자이너 안 선생님께 감사인사 드립니다.

마지막 사진인 타임테이블 제작에 좀 고생 했지만, 데이터를 삽입하면 동적으로 잘 동작합니다.

뿌듯

밥약(4)

다른 일이 바빠서 미루다가 다시 제작하게 되었습니다.

웹으로 제작하기위해 프론트 디자인을 만들어 봤습니다.

깔끔하지 않나요? 네 저도 알고 있어요

간단하게 Python Flask를 이용해서 만들어 보았네요

다음에는 시간표를 자동으로 만드는 코드를 제작하고 디자인해서 올리도록 하겠습니다

시외/고속 버스 AppleWallet Pass 제작 (4)

안녕하세요 오랜만에 글 쓰네요 하핫 ^^

놀고 있던 중에 슬픈 메일이 왔습니다.

아 ㅋㅋ 또 돈내야해? 아 ㅋㅋㅋ

저거 라이센스 끊기기 전에 완성 시키는걸 목표로 잡겠습니다.

QR코드 인식 때문에 애 먹던 중에 건우형이 구원의 손길을 내어 주심

보니까 이건 나도 찾아봤던건데;;; 하면서 에잉 이거 아닌데 했는데 알고 보니까 밑에 내가 원하는 기능이 있었음

진우 바봉 >___<

해서 해당 기능을 토대로 적용시켜보겠습니다 하핫

[토이 프로젝트 – Spring boot] 여행 플래너 GoAnyWhere

내가 사용하려고 만드는 여행 플래너 프로젝트 가능하면 무중단 배포를 곁들인..

보기 좋고 편한 여행 플래너들이 많이 있지만 대부분 모바일 어플리케이션 환경으로 제공되고 있으며, 웹 상에서 친구와 함께 공유 할 수 있도록 구현해보려고 합니다.

공부와 병행하는 프로젝트이니 스프링 이니셜라이져로 환경 세팅을 하는 것이 아닌 그레들로 시작하여 스프링부트 환경을 조성할 예정입니다.

개발 환경

  • Spring boot
  • Java 8
  • Gradle
  • AWS – EC2, RDS, Codedeploy etc..
  • Maria DB

구현하고자 할 기능

  • 로그인 – 구글 API 사용
  • 개인 플래너 기능 저장
  • 플래너 – 지도, 한국관광청 정보 제공 API
  • 그룹 기능 – 플래너 내에서 멤버 추가
  • AWS 배포

공부하면서 하기에 프로젝트가 조금 늦어질 수 있다는 점 양해 부탁드립니다.

렌파이 프로젝트 01

팀원들이랑 하는 프로젝트 입니다.

팀원은 스토리 작가,UI&UX 디자이너, 그림작가, 프로그래머 2명입니다.

아직 베타버전 제작중이니 배포는 금지합니다.

스텐딩 cg 작업 중

캐릭터 컨셉 작성중

코드 작성 등장인물 정의, 배경정의, 스토리 적용, 효과 적용

# 등장인물 정의
init python:
    shin = Character('김신우')
    yeon = Character('이하연')
    park = Character('박윤호')
    yun = Character('이하윤')

# 배경 정의
image bg black: # 효과를 위한 검정 화면
    im.FactorScale("bg/black.png", 1.5)
    yalign 0.5

image bg dark:
    im.FactorScale("bg/dark.png", 1.5)
    yalign 0.5

image bg room:
    im.FactorScale("bg/room.png", 1.5)
    yalign 0.5

image bg livingroom:
    im.FactorScale("bg/livingroom.png", 1.5)
    yalign 0.5

image bg cafe:
    im.FactorScale("bg/cafe.png", 1.5)
    yalign 0.5

image bg street:
    im.FactorScale("bg/street.png", 1.5)
    yalign 0.5

image bg corridor:
    im.FactorScale("bg/corridor.png", 1.5)
    yalign 0.5

image bg school:
    im.FactorScale("bg/school.png", 1.5)
    yalign 0.5

###################################################################################
############################### 등장인물 이미지 정의 ###############################
###################################################################################

# 이하연
image yeon normal:
    im.FactorScale("character/yeon.png",0.4)
    yalign -0.1

image yeon smile:
    im.FactorScale("character/yeon.png",0.4)
    yalign -0.1

image yeon panic:
    im.FactorScale("character/yeon.png",0.4)
    yalign -0.1

# 이하윤
image yun normal:
    im.FactorScale("character/yun.png",0.4)
    yalign -0.1

# 트랜지션

define fade = Fade(1.5, 1.0, 1.5) # 1.5초 페이드 아웃 -> 1.0초 정지 -> 1.5초 페이드 인
define fadeShort = Fade(0.5, 1.0, 0.5)


# Prologue
label start:

    scene bg dark with dissolve
    # 어두운 음악 on

    "인생은 항상 선택의 연속이었다."
    "찰나의 선택은 항상 인생에 큰 영향을 끼쳤으며, 늘 그 선택에 후회를 하였다."

    "???" "행복했어. 좋은 부모님을 만났고 좋은 사람들과 좋은 시간을 보내왔으니까…."

    "선택 이후에는 늘 책임의 시간이 찾아왔다."
    "하지만, 나는 단 한 번도 그 책임에 대한 각오를 한 적이 없었다."

    "???" "그리고 처음으로 사랑하는 사람을 찾았어. 그러니까. 조금의 후회도 없어. 덕분에 결심을 할 수 있었던 것 같아."

    "어쩌면 각오를 해도 달라지는 것이 없었지 않았을까?"
    "늘 선택에 따른 결과는 비수가 되어, 날아와 나의 심장에 박혔다."
    "그렇게 또 하나의 지울 수 없는 상처만이 내 몸에 새겨질 뿐이었다."
    "더 좋은 선택을 할 수 있지 않았을까?"
    "아니, 어떤 선택을 했어도 결과에 후회를 했었을 것이다."
    "하지만, 그렇게 생각하지 않는다면, 나 자신을 부정할 것만 같았다."

    "???" "고마워…. 그리고 사랑해."

    "그녀를 잡아야 했다."
    "이대로 가다가는 그녀는 분명 사라질 것이었다."
    "하지만, 나는 잡을 수 없었다."
    "왜냐하면, 이 결과는 오로지 내가 선택한 결말이었으니까."
    "되돌릴 수는 없다."

    "???" "그럼 안녕."

    "점점 시야가 어두워진다."
    "그녀의 마지막 모습이었다."
    "끝까지 지켜봐야 하지만, 몸이 말을 듣지 않았다."
    "희미해지는 의식 속에서 그녀의 미소가 보였다."
    "동시에 극심한 후회가 밀려들기 시작했다."
    "잘못된 선택이었다."
    "더 좋은 선택을 할 수 있었을지도 모른다."
    "제길…. 그녀를 잡아야 한다."
    "하지만, 아무리 발버둥 쳐도 그녀는 점점 더 시야에서 멀어져갔을 뿐이었다."
    "그렇게 완전히 정신이 끊어졌다."

    # 어두운 음악 off

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

    scene bg room with fade
    # 밝은 음악 on

    play sound "audio/se/thud.mp3"
    with vpunch

    pause(0.7)
    shin "아이 씨…."

    "무슨 꿈을 꾼 것인지 정신을 차리니 침대가 아닌 바닥에 자빠져있는 나는 극심한 두통을 느끼고 있었다."
    "분명 꿈을 꾼 것 같은데, 기억이 나지 않았다. 그것도 아주 중요한 꿈이었는데…."

    shin "에휴. 모르겠다."

    "떠올리는 것을 포기한 나는 자리에서 일어나서 방 밖으로 나왔다."

    scene bg black with blinds
    play sound "audio/se/footstep.mp3"
    pause(1.1)
    scene bg livingroom with blinds

    "올해 17살로 고등학교에 입학하는 나는 부모님의 카페 알바를 도우면서 기타를 치는 너튜버를 하고 있었다."
    "최근 구독자 30만 명을 달성하면서 나름 큰 유튜버를 운영하고 있었던 나는 주목받는 것을 싫어했기에 유튜버로서의 신분을 숨긴 채로 평범한 학생으로서 살아가고 있었다."

    "윤신혜" "신우야. 오늘 엄마랑 아빠가 어디 가거든? 홀로 카페 봐줄 수 있겠니?"

    "어미니의 목소리에 머리를 박박 긁으면서 주방으로 걸어온 나는 한숨을 크게 내쉬었다."

    shin "오늘 새로운 알바생 온다며, 어떡하려고?"
    "윤신혜" "이제는 우리보다 카페 일에 대해서 더 잘 알면서 그래?"
    shin "그래도 사장님이 있는 거랑 느낌이 다르지."
    "윤신혜" "오늘 중요한 행사니까. 부탁 좀 할게."

    "현재 부모님은 노랑재단이라는 봉사단체에서 상당히 주요한 직책을 맡고 계신다."
    "덕분에 제법 집과 카페를 많이 비우기도 해서 최근에는 내가 카페에 많은 관여를 하고 있었다."
    "물론 그렇다고 부모님이 아예 손을 놓고 계시는 것은 아니지만, 최근에는 재단에서 문제가 생겨서 그런지 내가 더 많이 카페 일에 관여하고 있었다."

    shin "뭐…. 알았어요. 다녀오세요."
    "윤신혜" "그래. 고마워."

    "어머니와 아버지가 집에서 나가자, 나는 밥상에 차려진 밥을 챙겨 먹고는 옷을 입은 후에 카페가 있는 1층으로 내려갔다."

    scene bg black with blinds
    play sound "audio/se/footstep.mp3"
    pause(1.1)
    scene bg cafe with blinds

    "전체적으로 말끔한 인테리어로 이루어진 부모님의 카페 ‘Lastory’는 막 손님이 몰리는 가게는 아니었지만, 단골이 여러 명 있어서 나쁘지 않은 흑자를 거두고 있었다."

    "단골손님" "어! 신우야 오늘도 왔다."
    shin "오…. 형 오늘도 오셨네요. 최근에는 안 바빠요?"
    "단골손님" "급한 일들은 저번에 다 처리해서 최근에는 조금 여유롭지."

    "오픈한지 대략 1분 만에 단골손님을 맞이한 이후로 점차 손님들이 들어오기 시작했다."
    "생각보다 많은 손님의 수에 나는 정신없이 일을 이어나가고 있었다."

    # @여기에 종 효과음을 넣으면 어떠려나?

    yeon "늦어서 죄송합니다!"

    "갑작스러운 목소리에 한참 커피를 타던 나는 고개를 돌렸고 한 예쁜 소녀의 모습이 눈에 들어왔다."

    show yeon smile with dissolve # @이전 대화에 등장하는 건?

    "긴 흑발 포니테일에 루비같이 빛나는 붉은 눈동자를 가진 그녀는 새하얀 피부와 다소 날카로운 턱선과 날 선 코와 커다란 눈이 고양이가 생각나는 그런 얼굴을 가지고 있었다." # @일러가 있으니 주인공 감상만으로 충분할듯
    "예쁘고 귀여운 외모를 가졌다는 감상이 절로 드는 그녀는 싱긋 웃으면서 내게 인사를 해왔다."

    show yeon normal
    yeon "오늘부터 이곳에서 일하게 된, 이하연이라고 해요. 잘 부탁드려요!"
    shin "아…. 하연씨군요. 반갑습니다. 부모님이 급히 볼일이 생기셔서 오늘은 제가 카페를 맡고 있습니다."
    yeon "아! 사장님의 아드님이셨군요."
    shin "네. 잠시 안쪽으로 들어와 주실래요?"

    "상당히 활발한 성격을 가진 하연씨의 모습에 나는 내심 안심하면서 열쇠를 들고 그녀를 안쪽 스태프실로 안내했다."

    show yeon panic
    yeon "손님 많은 것 같은데 괜찮아요?"
    shin "괜찮아요. 형." # @하연이를 형이라고 부르는 거 같은데...

    "걱정하는 하연씨의 말에 나는 입가에 미소를 지으면서 카운터 기준으로 바로 건너편에 있는 단골손님이자 아는 형을 불렀다." # @형을 부르는 거만 묘사하는 건? 그리고 스태프 실로 형을 부른 건가?

    "단골손님" "왜?"
    shin "추가로 손님 오시면 전화 좀 해주실래요?"
    "단골손님" "그래. 갔다 와." # @갔다 와? 어딜??
    shin "네. 부탁할게요. 들어갈까요?" # @바로 장면을 전환해도 괜찮을 듯.
    show yeon smile
    yeon "네!"

    show yeon normal
    "다소 높은 하연의 텐션은 주변 사람을 피곤하게 할 수도 있겠지만, 카페 알바로서는 크게 나쁠 것이 없었기에, 오히려 장점이라고 생각했다." # @대사를 좀 더 혼잣말처럼 바꾸는 건?

    shin "커피와 기타 간식들은 제가 만들고 있으니, 하연씨는 카운터와 중간중간 청소 그리고 서빙을 부탁드릴게요." # @간식보다는 디저트라는 표현이 좀 더 카페사장아들같지 않을려나?
    yeon "주의사항은 없나요?"
    shin "저희는 단골손님들이 많아서 간혹 ‘먹던 걸로’라고 하시는 분들이 있어요. 그분들의 경우에는 이름을 묻고 저에게 알려주시면 제가 알아서 음료를 가져다드릴게요." # @"이름을 묻고"는 빼도 괜찮지 않을까?
    show yeon smile
    yeon "네. 알겠습니다!"

    show yeon normal
    "그 후 본격적인 업무가 시작되었다. 평소보다 제법 사람이 많았기에, 제법 힘들만도 했지만, 하연씨는 상당히 능숙하게 일을 이어나갔다." # @굳이 일러를 넣어야할까?
    "친절하고 상냥한 성격과 더불어 예쁜 외모여서 그런지 단골손님들도 매우 마음에 들어 하는 모습이었다."

    shin "하연씨. 전에 다른 카페에서 일하신 적, 있어요?"
    yeon "아뇨. 딱히 없어요. 아마 알바도 여기가 처음일 거예요."
    shin "오…. 놀랍네요. 상당히 능숙하셔서 분명 경험이 있는 줄 알았어요."
    show yeon smile
    yeon "천직인가 봐요." # @천직이란 잘 안 쓰이는 표현보다는 "저랑 잘 맞나봐요."나 "적성에 맞나봐요." 같은 표현이 좋지 않을까?

    show yeon normal
    "좋은 일꾼과 함께 일을 하다 보니 별문제 없이 영업을 이어나갔다." # @이 부분도 굳이 일러를 넣어야할까?
    "그렇게 어느새 밤이 되었고 카페 문을 닫아놓고 마무리 청소를 하던 나에게 하연씨가 다가왔다." # @여기에 다가오는 듯한 연출로 일러를 넣으면 될 거 같은데.

    show yeon smile
    yeon "수고하셨어요!"
    shin "하연씨도 첫날부터 상당히 바빴는데 수고하셨어요."
    show yeon normal
    yeon "혹시 나이가 어떻게 되세요?"

    "갑작스러운 질문이었지만, 그렇게 중요하다고 생각하지 않았기에, 나는 순순히 대답했다." # @나도 너무 갑작스러운데

    shin "이제 고등학교에 입학해요."
    show yeon smile
    yeon "오..! 17살이에요? 저도 그래요." # @"오..!"보단 "아 진짜요? 저도 17살인데."가 좀 더 한국스럽지 않으...려나?

    show yeon normal
    "계속 봤음에도 불구하고 하연씨의 미소는 여전히 매력적이었다."
    "무표정을 짓고 있으면 고양이상이어서 그런지 조금 무서울 것 같기도 한데, 계속 웃고 있어서 그런지 그런 느낌은 조금도 들지 않았다."

    yeon "저…. 혹시 말 놓아도 괜찮아요?"
    shin "네. 상관없어요. 오히려 일할 때, 편할 것 같네요."

    "딱히 사장대리로서 알바에게 갑질할 생각도 그에 맞는 대우를 받을 생각도 없었기에 나는 흔쾌히 받아들였고 이에 이하연은 입가에 미소를 지었다." # @일러로도 알 수 있으니 "흔쾌히 받아들였다."까지만 쓰는 건?

    show yeon smile
    yeon "신우야! 수고했어."
    shin "그..그래 수고했어."

    "어느 정도를 각오를 했지만, 막상 이름으로 불리자, 조금 낯간지러운 느낌이 들었다."

    hide yeon with dissolve

    "그렇게 하연이 사라지고 말끔하게 정리된 카페를 보면서 나는 크게 한숨을 내쉬었다."

    shin "오늘도 어떻게든 보냈나…."

    # 밝은 음악 off

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

    scene bg room with fade

    "다음날, 차가운 공기를 느낀 나는 곧바로 잠에서 깼다."
    "잠깐 침대에서 뒤척이면서 잠을 몰아낸 후 몸을 일으켰다."
    "잠결에는 그다지 의식하지 않았지만, 어느 정도 정신이 드니 찬바람이 들어오고 있다는 것을 느꼈다." # @상황 설명만 주구장창 늘여놓는 것보단 "으음..."같은 대사를 넣어주는 편이 좋을 듯

    scene bg black with blinds
    play sound "audio/se/footstep.mp3"
    pause(1.5)
    scene bg livingroom with blinds

    "부스스한 머리를 대충 정리한 채로 밖으로 나온 나는 창문이 조금 열린 것을 확인하고는 한숨을 내쉬었다." # @상황 설명만 하면 될 듯(ex: 밖으로 나와보니 역시 창문이 조금 열려있었다.)

    shin "아 문 좀 닫고 다니라니까."

    "아마 부모님이 제대로 닫지 않고 갔을 것이다."
    "완전히 창문을 닫고 잠금을 건 후, 주방으로 가서 베이컨과 계란후라이를 구워서 내려놓고는 토스트기에서 빵을 꺼냈다."

    "아나운서" "월요일 아침 출근길 매우 춥습니다. 서울의 현재 기온은 3도로 제법 추운 날씨가 예상되는 가운데…."

    "3월임에도 불구하고 꽃샘추위가 기승을 부리고 있어서, 밖은 상당히 추웠다."
    "두툼한 패딩과 새로 산 교복을 입고는 곧바로 현관문을 나섰다."

    scene bg black with blinds
    play sound "audio/se/doorlock.mp3"
    pause(1.7)
    play sound "audio/se/door_open.wav"
    pause(1.7)
    scene bg street with blinds

    # 잡음 효과음
    # 밝은노래 on

    "오늘은 처음으로 고등학교에 입학하는 날이다."
    "통학로에는 나와 똑같은 ‘유선 고등학교’ 교복을 입은 학생들이 학교로 향하고 있었다."
    "가던 중, 무거운 짐을 들은 할머니를 보자 뛰어서 다가가 말을 걸었다." # @상황 설명 외에 의성어나 의태어가 대사로 들어가는 편이 미연시스러울 듯

    shin "할머니, 어디까지 가세요?"
    "할머니" "아냐. 괜찮어. 학생 바쁠텐디 어여 가." # @사투리가 어색하여 임의로 수정함.
    shin "아직 시간 많아서 괜찮아요. 제가 도와드릴게요."
    "할머니" "학생이 참 착하구먼. 저기 버스 정류장까지 부탁혀." # @사투리가 어색하여 임의로 수정함.

    "괜한 오지랖일 수도 있지만, 나는 이러한 행동이 일종의 병과 같은 존재였다."
    "부모님 때문에 생긴 봉사병이라고 할까?" # @너무 번역체같은 데ㅋㅋㅋㅋ
    "하여튼 이런 분들을 보고 있으면 가만히 있을 수가 없었다."
    "덕분에 항상 착하다는 이야기를 많이 들었지만, 그만큼 호구라고 한 소리를 들을 때도 있었다."

    park "야! 김신우. 또 이러고 있냐?"

    "할머니의 짐을 내려다 준, 나에게 다가온 남자는 박윤호로 초등학교부터 같이 지낸 동네 친구였다." # @좀 더 문단을 나눌 필요가 있을 듯
    "성격이 매우 관종같지만, 생긴 것은 제법 준수해서 나름대로 인기가 있었다."
    "운 좋게 같은 고등학교에 붙게 되어서, 오늘도 같이 등교를 하고 있었다."

    shin "시끄러. 잘 들리거든?" # @이 부분도 뭔가 어색함. 시끄럽게 말하고 있다는 상황 설명이 필요할 듯
    park "오랜만에 봤는데 왜구루냥."

    "찰거머리처럼 달라붙는 이 자식은 나와 다른 녀석을 대하는 태도가 달랐다."
    "그렇다고 다른 사람에게 차갑게 대하거나, 그러지는 않았다." # @굳이 지금 넣어야하나?

    shin "새학기부터 힘이 넘치네."
    park "당연하지!"

    # 잡음 효과음

    "등굣길을 따라 천천히 걷던 도중, 갑자기 사람들의 수군거리는 소리가 들려왔다."
    "이에 윤호가 나에게 붙으면서 작은 소리로 말했다." # @굳이 넣을 필요가 있으려나?

    park "와. 이하윤이야. 이하윤."
    shin "이하윤? 그게 누군데."
    park "나도 친구들에게 들었는데, 우리 옆 중학교 있잖아. 거기 전교회장 출신이라던데?"
    shin "세카여중?" # @ㅁㅊ 중학교 이름 왜이럼 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

    "우리가 다녔던 중학교는 ‘유선 중학교’였고 그 근처에 ‘세카여자 중학교’라고 꽤 유명한 사립 여자 중학교가 있었다."
    "국내에서 상당히 유명한 중학교로 다른 학교와 달리 추천을 받은 학생만 들어갈 수 있는 학교였다." # @주인공은 모르는 눈치인데, 윤호의 입으로 푸는 편이 좋지 않으려나?

    shin "그런 사람이 왜 여기로 오는 거야? 보통 거기 출신들 다 서울로 가지 않아?"
    park "몇 명은 우리 학교로 오긴 하는데, 그중 한 명이 걔인가 봐. 특이하네. 전교회장 정도라면 유명 고등학교 들어갈 텐데." # @이 부분은 두 부분으로 나눠서 말하는 편이 좋을 듯.

    "‘유선 고등학교’도 자율형공립고등학교로 제법 이름이 있는 학교이긴 했지만, ‘세카여자중학교’에 비하면 다소 네임드가 부족했다." # @이 부분도 주인공은 모르는 부분인데 독백으로 넣는 건 좀 어색하지 않으려나?

    park "자세한 이유는 나도 몰라. 하여튼 저기있네, 저기."

    "학생들이 많아서 제대로 보이지 않았지만, 윤호는 필사적으로 이하윤을 보기 위해서 노력했다."
    "이에 나도 괜히 궁금해져서 조심스럽게 사람들을 헤쳐나갔다."
    "그러자, 이하윤의 모습이 드러났다." # @일러로 표현되는데 굳이 넣을 필요는 없어 보임.

    # 밝은노래 off
    show yun normal with dissolve

    "허리까지 길게 내려진 긴 흑발에 붉은색 커다란 눈동자를 가진 다소 차가운 인상은 예쁘다는 생각이 들면서도 범접하기가 힘든 그런 아우라를 내뿜고 있었다." # @일러가 있으니 주인공의 개인적인 감상만 있으면 될 듯.

    park "오…. 괜히 사람들이 예쁘다고 하는 게 아니네."
    shin "그..그러게."

    "예쁜 것이라 별개로 이하연과 상당히 비슷하다는 인상이 들었다."
    "게다가 이름까지도 상당히 비슷하기에, 혹시 쌍둥이가 아닌가라는 생각이 들 정도였다."
    "물론 분위기 자체가 워낙 달라서 구별하는 데 있어서 어려움은 없었지만 말이다."

    shin "윤호야. 저 사람 쌍둥이 형제가 있어?"

    "갑작스러운 질문에 윤호는 생각에 잠긴 표정으로 고민하더니 이내 고개를 저었다."

    park "아니 들어본 적은 없어. 나도 자세히 아는 것은 아니라서. 근데 왜?"
    shin "아냐. 그냥 어제 카페에 온 사람하고 상당히 비슷하다고 생각해서."
    park "이하윤하고 비슷한 사람이라고? 와. 겁나 부럽네."
    shin "부러운 것도 많다." # @부럽다는 표현은 딱 한 번 나왔는데 좀 어색한듯.

    "그렇게 우리는 등굣길에 중학교 친구 3명을 더 만난 상태에서 학교 안으로 들어갔다." # @말이 좀 어색한데, "친구 3명과 추가로 합류했고, 그 상태로 학교에 도착했다."가 좀 더 자연스럽지 않음?

    hide yun # @여기에서? 좀 더 뒤에서 하는 편이 좋을 듯.
    # 밝은노래 off @진작에 꺼진 상태입니다만?

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

    # 밝은노래 on
    scene bg corridor with fade

    "학교에 들어오자마자, 우리들은 게시판으로 향했다."
    "학생들이 우글거리는 이곳은 반 배정표가 걸려있었다."
    "3년 만에 느끼는 두근거림에 떨리는 마음으로 배정표에 도착했다."

    shin "3반이네. 윤호, 너도야."
    park "오 개꿀이네."

    "기쁜 마음에 우리는 하이파이브를 했다."
    "안 그래도 모르는 사람투성이인데, 한 명의 동지가 얼마나 큰지 알 수 있었다."

    "이치룡" "하…. 씨. 혼자네, 어카냐."
    "정용훈" "나도 그래도 한석이랑 같은 반이네." # @나도 그래도는 뭐야
    "김한석" "그러게. 다행이네."

    "치룡이만 제외한다면 각자 두 명씩, 같은 반에 붙은 모양이었다."
    "한숨을 길게 내쉬는 치룡이를 달래주고는 각자 배정된 반으로 향했다."

    scene bg black with blinds
    play sound "audio/se/footstep.mp3"
    pause(1.1)
    # 드르륵 문 열리는 소리
    scene bg school with blinds

    "‘1-3’이라고 1학년 3반 교실로 들어오자, 소수의 학생이 눈에 들어왔다."
    "당연히 다 모르는 얼굴이었고 상당히 어색한 분위기였기에, 우리는 조용히 앉았다."

    park "와이씨…. 분위기 미쳤네."

    "책상에 얼굴을 박은 채로 얼굴을 찡그리는 윤호를 보면서 피식 웃음이 나왔다."

    shin "진짜 어색하기는 하네."

    "몇몇 아이들만 아는 사이로 보이는 애들끼리만 이야기를 나누고 있었고 대다수의 아이들은 스마트폰만 바라보고 있었다." # @'만'이 연속으로 나와 좀 어색해보임.
    "나도 윤호가 없었다면, 저 아이들과 다를 것이 없었겠지."

    # 드르륵 문 열리는 소리

    "그렇게 조곤조곤 이야기를 나누던 도중, 드르륵 문 열리는 소리에 모두가 문으로 시선이 고정되었다."
    "그리고 그곳에는 이하윤이 있었다."

    show yun normal with dissolve

    "다시 봐도 예쁘다는 것이 느껴지는 얼굴은 정석적인 우등생의 느낌을 주었다."
    "다른 아이들도 그렇게 느낀 것인지 모두 그녀를 멍하게 바라보고 있었다."
    "그런 시선이 익숙한 것인지 아니면, 눈치채지 못한 것인지 그녀는 조용히 자리에 가서 앉더니, 문제집 한 권을 꺼냈다." # @독백으로 상황설명안 주구장창 늘여놓으니 게임적으로 어색함.

    park "야야. 김신우 대박. 이하윤이 우리 반인가 봐!" # @아까 배정표를 봤을텐데 몰랐을까?
    shin "생각지도 못했네."
    park "와. 개이득이네."
    shin "뭐가 개이득이야. 사귀는 것도 아니고."
    park "친해질 기회가 있다는 거잖아."

    "윤호의 말이 이해가 안 가는 것은 아니었지만, 어깨를 으쓱거리면서 그의 등을 가볍게 때렸다." # @어깨를 으쓱거리면서... <- 이부분은 빼도 될 듯.

    shin "말이라도 걸 수 있으면 다행이지."
    park "펙트 아프다…."

    "확실히 이하윤이 풍기는 분위기는 여간, 분위기가 아니었다."
    "특히 공부를 하고 있는 지금과 같은 경우에는 절대 못 건들었다."

    shin "여차하면 나중에 쉬는 시간에 말이라도 걸어봐."
    park "뭐야. 신우 너도 관심 있냐?"
    shin "계속 그쪽으로 몰아가지 마라."

    "황당함에 비소를 지으면서 다시금 윤호의 등을 때렸다."
    "제법 내 손이 매웠는지 박윤호는 얼굴을 찡그리면서 말했다."

    park "아파. 이시키야."

    "그렇게 노가리를 까는 사이, 선생님이 들어오셨고 그 이후로는 입학식의 정석처럼 이어졌다."

    hide yun # @너무 늦게 없애는 건 아닌지?
    # 밝은노래 off
    scene bg black with blinds
    pause(1.1)
    scene bg school with blinds

    "별문제 없이 입학식이 끝나고 첫날 수업이 이어졌다."
    "대부분의 선생님이 OT라고 하면서 가르치는 것보다는 자기소개 위주로 수업을 진행했다."
    "자리는 원하는 대로 앉을 것이라고 생각했는데, 한가지 변수가 생겼다."

    # 밝은노래 off
    # 사고브금 on

    "담임 선생님" "이제부터 자리를 바꿀 거예요. 신학기인 만큼 두루두루 친하게 지내야 하니까. 다들 너무 나쁘게 생각하지 마세요." # @문단을 나눌 필요가 있어보임.
    "반 아이들" "네에?"
    "반 친구A" "에이 쌤. 그건 오바죠."

    "갑자기 자리를 바꾼다는 소식에 나와 윤호는 서로를 바라보면서 ‘망했다’라는 표정을 지었다." # @좀 더 주인공의 속마음이 대화처럼 들어가면 좋을듯.
    "둘이 있어도 이 어색한 분위기를 견디기 힘든데, 다른 사람하고 있게 된다면 도저히 견딜 수가 없을 것이었다."
    "상상만 해도 몰려오는 어색함에 온몸이 쪼그라드는 느낌이었다."

    "담임 선생님" "이미 결정된 사항이에요."

    "첫인상은 상당히 자상하고 부드러운 선생님이었는데, 이런 면에 있어서는 상당히 엄한 부분이 있으셨다."
    "결국 선생님의 진행 아래 자리 바꾸기가 진행되었다."
    "그리고 생각지도 못한 결과가 나와버렸다." # @이 부분에서도 의성어나 의태어같은 부분이 들어가면 괜찮을듯.

    with fade # @굳이?

    "뽑기 결과 놀랍게도 내 옆자리에 앉은 것은..."

    show yun normal with dissolve

    "이하윤이었다." # @여기도

    yun "안녕"
    shin "어..어 안녕."

    "바로 옆에 있다는 것은 그만큼 얼굴도 더 잘 보인다는 것이었다."
    "새하얀 피부에 날카로운 얼굴선, 적당히 각진 코에 살짝 붉은 입술과 커다란 적색의 눈동자는 실로 감탄이 나오는 외모였다."
    "그리고 무엇보다 이하연과 비슷하다는 감상을 지울 수가 없었다." # @여기서 더 의심하는 편이 더 좋지 않을까요?

    shin "분위기는 다른 데 말이지..."
    yun "응? 뭐라고 했어?"
    shin "아냐! 그냥 혼잣말이였어."

    "생각한 것을 겉으로 내뱉은 것이었는지,
    고개를 돌려 의문에 가득 찬 표정을 짓는 이하윤의 모습에 당혹감을 느낀 나머지 양손을 들어 올리면서까지 고개를 저었다." # @당혹감이 아니라 위화감이 느껴지는게 "
    "그 후 이하윤과 딱히 이야기를 나누지 않았다."
    "아니 정확히는 나눌 수가 없었다."
    "방금 그런 모습을 보였는데, 어떻게 말을 걸겠는가?" # @개인적인 견해로 여기서 잠을 잤다가 깨서 종이 울리는게 개연성 부분에서 맞다고 생각합니다!

    # @여기서 페이드를 넣고 자연스럽게 넘어가는 대사를 넣어주면 좋겠다고 생각합니다.
    # 사고브금 off
    # 밝은노래 브금 on
    # 학교 종소리 효과음 on

    "이윽고 수업이 끝나고 쉬는 시간이 되자. 여자애들이 이하윤의 곁으로 다가왔다."

    "윤소진" "하윤이 맞지?"
    yun "어 맞아 너는 소진이지?"
    "윤소진" "오 알고 있었구나!"
    yun "물론이지."

    "이하윤은 딱히 말을 잘하는 것은 아니었지만, 조용히 남의 말을 잘 들어주고 적당한 반응을 하다 보니 금세 여러 여자 애들과 친해졌다."
    "괜히 라세여중에서 인기가 많았던 것이 아니었다." # @세카여중과 라세여중이 똑같은곳?

    # @여기 부분에서 박윤호가 다가오는 묘사를 말해주면 좋겠다.

    park "와…. 김신우 존나 부럽네."
    shin "부럽긴 뭐가 부러워. 여러모로 가시방석이야."
    park "저 모습 보면 그래도 우리가 생각하는 것보다는 괜찮은 것 같은데?"
    shin "그렇긴 한데…."

    "즐겁게 이야기를 나누는 이하윤의 모습은 확실히 처음 이미지와 다르게 다른 여자애들과 다를 것이 없었다."

    shin "그래도 쉽지는 않아."
    park "이럴 때는 여자였으면 조금 편했을 듯?"
    shin "취향 존중할게."
    park "미친놈…. 그래서 오늘 끝나고 피방 기?"
    shin "오늘은 시간 있긴 해."

    "이하윤에 대한 이야기도 잠시 우리들도 원래 하던 이야기로 화제가 돌아왔다."
    "우연히 짝이 된 것은 놀랍지만, 그렇다고 크게 접점이 있지는 않았다."
    "그리고 굳이 무리하여 접점을 가질 필요도 없다 생각했다."

    hide yun

    # 밝은노래 브금 off
    # 교실 배경 off

    with fade

    # 교실 방과 후 배경 on
    # @객관적인 표현 사용 시간 표현.

    "그렇게 시간이 끝나고 방과 후가 되었다." # @접속사 많음.
    "그리고는 첫 번째 당번이 되어서 뒷정리를 하고 있었다."
    "그런 나와 같이 정리를 하고 있는 사람은…." # @비주얼 노벨에서 소설처럼 쓰기에는 어울리지 않습니다.

    show yun normal with dissolve

    yun "거기 칠판지우개 좀 줄래?"
    shin "어 여기."

    "놀랍게도 이하윤이었다."
    "우리가 당번이 된 이유는 1분단 가장 앞자리에 배정받았기에, 이렇게 된 것이었다."
    "물론 당번 일을 시작한 지 10분이 지났음에도 우리의 사이는 어색했다."

    yun "대충 거의 다 했지?"
    shin "어 다했어. 짐만 옮기면 될 것 같아."

    "교실 앞쪽에 한 개의 상자가 있었다."
    "이하윤은 먼저 상자로 다가가더니, 이내 상자를 들어 올렸다."
    "그러나, 상자가 조금 무거웠던 것인지 팔이 덜덜 하면서 떨렸다."
    "이에 빠르게 다가가 그녀의 상자를 대신 들어주었다. "

    shin "도와줄게."
    yun "어..어 고마워."

    # @여기서 박스 드는 소리

    "상당히 묵직한 무게는 제법 운동 좀 한다고 생각했던 나도 무거울 정도였다."
    "이하윤이 들기에는 무리라고 할 정도로 말이다."
    "상자를 든 채로 이하윤과 같이 창고로 들어온 나는 적당한 곳에 내려놓았다."
    "계속해서 침묵을 이어가는 상태에서"

    return

시외/고속 버스 AppleWallet Pass 제작 (3)

Pass를 만드는 변수에 넣을 정보를 받아올 웹 페이지를 제작 중에 있습니다.

QR 사진을 올리면 QR을 인식할 라이브러리를 찾고 있는데 혹시 관련 정보 아시면… 레퍼런스 좀 보내주세요 흑흑 ㅜㅜ

HTML로 일단 만들긴 했는데 CSS로 스타일도 넣어주려 합니다.

우선 라이브러리 찾는게 우선이지만…

JS를 안해봐서 쉽지 않네요 껄껄

디지털액자 (4)

알림 기능을 구현해 보겠습니다.

실시간 알림은 websocket 등으로 구현 하면 되지만 디지털액자는 그렇게까지 실시간으로 알림을 보지 않아도 되기 때문에 2~5초 간격으로 서버에 ajax 요청을 보냅니다. 서버는 알림 배열을 반환합니다.

알림 API 응답

클라이언트는 이 배열을 읽고 알림 표시 기한(expire)이 지났는지 확인한 후 알림을 display_time 초 동안 표시합니다. 랜덤 id 값이 부여되기 때문에 클라이언크는 알림을 표시했으면 localstorage 에 이 id 값을 저장합니다.

localstorage 에 읽을 알림 id 저장

이 localstorage 는 새로고침해도 데이터가 지워지지 않습니다. 따라서 한번 표시된 알림은 다시 표시되지 않습니다.

이제 notification 을 자동으로 넣어주는 코드를 짜야 합니다. 우선 일정 시작 전 알려주는 코드를 짭니다.

매 1분마다 작업을 돌려줘야 하기 때문에 fastapi_utils 라이브러리를 사용했습니다.

@app.on_event("startup")
@repeat_every(seconds=60 * 1)  # 1 minute
def event_notification() -> None:
    now = datetime.datetime.now(tz=tzoffset(None, 32400))
    evt_list = get_event_list()
    expire = 60 * 10  # 10 분
    display_time = 30  # 30 초

    for evt in evt_list:
        for reminders in evt.reminders:
            reminder_at = get_evt_start_date(evt) - datetime.timedelta(minutes=reminders.minutes_before_start)
            if now <= reminder_at < now + datetime.timedelta(minutes=1):
                start_date = get_evt_start_date(evt).strftime("%m-%d %H:%M")
                add_notification(f"{start_date}<br>{evt.summary}<br>일정이 {reminders.minutes_before_start}분 후 시작합니다.",
                                 expire=now.timestamp() + expire, display_time=display_time, show_notiboard=False)

        if len(evt.reminders) == 0:
            reminder_at = get_evt_start_date(evt) - datetime.timedelta(minutes=30)
            if now <= reminder_at < now + datetime.timedelta(minutes=1):
                start_date = get_evt_start_date(evt).strftime("%m-%d %H:%M")
                add_notification(f"{start_date}<br>{evt.summary}<br>일정이 {30}분 후 시작합니다.",
                                 expire=now.timestamp() + expire, display_time=display_time, show_notiboard=False)

임의의 초에 1분마다 실행되는 것이기 때문에 (현재시각 <= 리마인더시각 < 현재시각 + 1분) 범위로 잡아야 알림을 빠짐없이 잡을 수 있습니다.

다음은 학사·학과공지 코드로 알림을 구현할 예정입니다.

디지털액자 (3)

하드웨어를 구성했으니 웹 서버를 만들 차례입니다.

FastAPI 와 Jinja2 템플릿을 사용하여 빠르게 만들겠습니다.

FastAPI: https://fastapi.tiangolo.com/ko/

레이아웃은 아래와 같이 할겁니다

눈이 부시면 안 되기 때문에 다크 테마로 적용시켰고 미래 일정까지 다 보이도록 일정 공간을 넓게 잡았습니다. 그리고 매주 금요일마다 서울에 다녀와야 해서 예매 까먹는걸 방지하기 위해 예매 내역을 조회할 수 있는 칸을 만들었습니다.

그리고 웹 페이지기 때문에 주기적으로 데이터를 변경해줘야 합니다. 아래 코드로 120초마다 페이지를 새로 고칩니다.

function reloadFunction() {
    window.location.reload();
}

let timeout = window.setTimeout(reloadFunction, 120 * 1000);

이제 데이터를 만들어 넣어야 합니다.

파이썬 srt 라이브러리로 티켓 가져오는 코드를 짭니다.

def srt_get_reservations() -> List:
    srt = SRT(srt_id=srt_id, srt_pw=srt_pw)
    reservations = srt.get_reservations()
    return reservations[0:3]

레이아웃이 깨지지 않게 하려면 3개까지 보여지게 합니다.

페이지가 120초마다 새로고침 되므로 위 코드도 계속 실행되면 SRT 서버에 부하를 발생시키고 심하면 차단당할 것입니다. 따라서 적절하게 캐시를 사용해야 합니다. 함수 실행결과를 disk 에 캐시해주는 라이브러리인 diskcache 를 사용하였습니다.

from diskcache import FanoutCache
cache = FanoutCache("./.cache/memoize")

@cache.memoize(expire=60 * 30)
def srt_get_reservations() -> List:
    ...

위와 같이 어노테이션 한줄만으로 쉽게 캐시할 수 있습니다.

마찬가지로 구글 캘린더도 gcsa 라이브러리를 사용하여 작업합니다. 타임존 관련으로 어려운 부분이 있었는데 이 부분은 따로 포스팅 하겠습니다.

다음은 일정이 임박하면 소리와 함께 알려주는 코드를 작성해 보겠습니다.

시외/고속 버스 AppleWallet Pass 제작 (2)

Pass를 만들 때 사용되는 주요 정보는 다음과 같습니다.

해당 코드는 예시로 Pass를 제작할 때 사용했던 코드이며 SM Ent. 세계관을 인용하여 만들었습니다. 에스파 사랑해

저기에 들어가는 정보들을 이제 원본 승차권에서 받아와서 Pass로 만드는게 목표

승차권 예매 플랫폼별로 표시되는 정보도 달라서 이 점 감안하여 만들어야 할 것 같습니다.

    pass.barcodes = [{message : "20200208600351000461620200208164002111", format : "PKBarcodeFormatQR", messageEncoding : "iso-8859-1", key: "passCode"},];
    pass.primaryFields.add({label: 'Pangyo', value: '판교', key: "origin"});
    pass.primaryFields.add({label: 'Kwangya', value: '광야', key: "destination"});
    pass.secondaryFields.add({key: 'time', value: '3:40', label: '소요시간'});
    pass.auxiliaryFields.add({key: 'date', value: '01/14 04:00', label: '출발일자'});
    pass.auxiliaryFields.add({key: 'grade', value: '심야우등', label: '등급'});
    pass.auxiliaryFields.add({key: 'gate', value: '1', label: '승차홈'});
    pass.auxiliaryFields.add({key: 'seat', value: '01', label: '좌석번호'});
    pass.transitType = ('PKTransitTypeBus')