본문 바로가기

[Recoeve.net]

Career Portfolio - 이강수

반응형
# Career Portfolio - 이강수 Physicist, Programmer. 최근의 좌우명은 "What you eat, how you think, and most importantly what you have done become who you are. Who are you? and who will you be?"
나 어렸을때 사진
## PH
  • 2023-05-31 : MBTI 추가.
  • 2017-03-21 : 정리.
  • 2016-03-16 : 정리.
  • 2015-12-23 : 대충 좀 더 정리.
  • 2015-12-18 : First posting.
## TOC ## HEXACO
  • Honesty-Humility
  • Emotionality
  • eXtraversion
  • Agreeableness (versus Anger)
  • Conscientiousness
  • Openness to Experience
https://hexaco.org/ (2023-06-25 검사)
## My MBTI (Myers-Briggs Type Indicator, 성격유형): 전략가 INTJ-A (2023-05-31 검사) 내 MBTI: (2023-05-31 검사), 검사한 site https://www.16personalities.com/ko/무료-성격-유형-검사, 나무위키 :: 마이어스-브릭스 유형 지표 (MBTI), [Physics/Math/Science]--뇌과학 ; [정치/사회/경제]--심리 of kipid's Recoeve.net
. 성격 유형: 전략가 INTJ-A(Assertive)
전략가는 모든 일에 계획을 세우며 상상력이 풍부한 성격 유형입니다.
57% 내향형|Introversion (외향형|Extroversion 43%, 내향형|Introversion 57%)
내향형의 사람들은 소수의 사람들과 깊고 의미 있는 관계를 맺는 일을 선호하며, 차분한 환경을 원할 때가 많습니다.
78% 직관형|iNtuition (직관형|iNtuition 78%, 현실주의형|Sensing 22%)
직관형의 사람들은 매우 상상력이 뛰어나고 개방적이며 호기심이 많습니다. 이들은 독창성을 중시하며 어떤 것에 숨은 의미와 막연한 가능성에 대해 집중하곤 합니다.
54% 사고형|Thinking (사고형|Thinking 54%, 감정형|Feeling 46%)
사고형의 사람들은 객관성과 합리성을 중시하며 논리에 집중하느라 감정을 간과할 때가 많습니다. 이들은 사회적 조화보다는 효율성이 더 중요하다고 생각하는 경향이 있습니다.
78% 계획형|Judging (계획형|Judging 78%, 탐색형|Perceiving 22%)
계획형의 사람들은 결단력이 높고 철저하며 계획적인 성격을 지니고 있습니다. 이들은 명확성과 예측 가능성을 중시하고 어떤 일을 제대로 끝내고자 하며 즉흥적인 일보다는 체계적으로 계획을 세우는 일을 선호합니다.
90% 확신형|Assertive (확신형|Assertive 90%, 민감형|Turbulent 10%)
확신형의 사람들은 스스로를 믿고 평정심을 잘 유지하며 스트레스에 크게 영향을 받지 않습니다. 이들은 걱정을 자주 하지 않으며 목표를 달성하기 위해 노력하는 과정에서 높은 자신감을 보이는 경향이 있습니다.
### Description of my MBTI (성격 유형: 전략가 INTJ-A(Assertive) / INTJ-T(Turbulent)) 성격 유형: 전략가 INTJ-A(Assertive) / INTJ-T(Turbulent)
사고 능력은 인간의 위대한 점 중 하나이다. 인간은 갈대처럼 연약하지만 생각하는 갈대이다. --by 블레즈 파스칼--
최고가 되는 것은 외로운 일입니다. 매우 희귀한 성격이면서도 뛰어난 능력을 지닌 전략가(INTJ)는 이러한 말의 의미를 잘 알고 있습니다. 전략가는 이성적이면서도 두뇌 회전이 빠른 성격으로, 자신의 뛰어난 사고 능력을 자랑스러워하며 거짓말과 위선을 꿰뚫어 보는 능력이 있습니다. 하지만 이로 인해 끊임없이 생각하고 주변의 모든 것을 분석하려는 자신의 성향을 이해할 수 있는 사람을 찾는 데 어려움을 겪기도 합니다. #### 개척자 정신 전략가는 모든 것에 의문을 제기합니다. 다른 많은 성격은 현재 상태를 유지하고 일반적인 통념과 다른 사람의 전문 지식에 의존해 살아가곤 합니다. 하지만 비판적인 성향을 지닌 전략가는 자신만의 방식을 찾아내기를 원하며, 일을 진행하는 더 나은 방식을 찾기 위해 규칙을 깨거나 다른 사람의 반대를 무릅쓰는 일도 마다하지 않습니다. 사실 오히려 이러한 과정을 즐기는 편입니다. 전략가는 실제로 활용할 수 있는 아이디어만이 가치가 있다고 생각하며, 단순히 새로운 아이디어를 내는 데 그치는 것이 아니라 아이디어를 이용해 성공을 쟁취하고자 합니다. 이들은 업무에 자신의 모든 통찰력과 논리력과 의지를 쏟아부으며, 불필요한 규칙을 설정하거나 쓸모없는 비판을 제기하면서 자신을 방해하는 사람에게는 가차 없는 모습을 보입니다.
전략가는 매우 독립적인 성격으로 다른 사람의 기대를 따르기보다는 자신만의 아이디어를 추구합니다.
전략가는 독립성이 매우 강하며 혼자서 행동하는 일을 두려워하지 않습니다. 아마 다른 사람을 기다리는 일을 좋아하지 않기 때문일 수도 있습니다. 또한 일반적으로 다른 사람의 의견을 묻지 않고 결정을 내리는 편입니다. 이렇게 혼자서 행동하려는 성향으로 인해 다른 사람의 의견과 욕구와 계획을 무시함에 따라 무신경한 사람처럼 보일 수도 있습니다. 하지만 전략가가 남에게 무심하다는 생각은 사실이 아닙니다. 감정이 풍부하지 않고 지적인 성격이라는 편견이 있기는 하지만 사실 전략가는 예민한 감성을 지니고 있기 때문입니다. 전략가는 일이 잘못되거나 남에게 상처를 주게 되었을 때 슬픔과 후회를 느끼며, 왜 그런 일이 발생했는지 파악하는 데 많은 시간과 에너지를 투자합니다. 결정을 내릴 때 감정을 중시하지 않는다고 해서 감정을 느끼지 못하는 것은 아니기 때문입니다. #### 지식에 대한 갈망 전략가는 대담한 몽상가인 동시에 극심한 비관주의자이기도 합니다. 이들은 의지와 지적 능력이 있다면 어떠한 목표라도 성취할 수 있다고 믿지만, 동시에 대부분의 사람이 게으르고 상상력이 부족하고 특별할 것이 없다고 냉소적으로 생각하기도 합니다. 전략가의 자존감은 대부분 자신의 지식과 지적 능력에 기반을 두고 있습니다. 학교에서 '책벌레'나 '범생이'라는 소리를 듣기도 하지만, 이러한 말을 모욕이 아닌 자신의 특징으로 받아들입니다. 또한 자신에게 코딩, 무술, 클래식 음악 등 관심이 있는 분야라면 어떤 분야든지 최고가 될 수 있는 능력이 있다는 사실을 알고 있습니다.
전략가가 새로운 것을 배우는 이유는 남에게 보여주기 위해서가 아니라 자신의 지식을 확장하는 일 자체를 즐기기 때문입니다.
전략가는 완고할 때가 있으며 주의가 산만한 환경이나 불필요한 잡담 등 시시한 일을 참지 못합니다. 하지만 그렇다고 이들이 지루하거나 재미없는 성격이라는 의미는 아닙니다. 진지해 보이는 모습과 달리 재치가 넘치며. 날카롭게 비꼬면서도 재미있는 유머 감각을 지니고 있는 경우가 많기 때문입니다. #### 상대적으로 취약한 사교 능력 일반적으로 전략가가 따뜻하고 부드러운 성격은 아닙니다. 겸손함과 인사치레보다는 이성과 성공을 중시하며, 입바른 말을 하기보다는 솔직하게 이야기하는 성격이기 때문입니다. 소설이나 영화의 악당이 전략가의 성격을 지닌 것으로 표현되는 이유도 바로 이러한 점 때문일 것입니다. 솔직함을 중시하고 핵심만을 이야기하려는 전략가는 잡담과 빈말 등 일반적인 사교 활동이 무의미하거나 멍청하다고 생각할 수 있습니다. 이로 인해 솔직함에만 집중하느라 무례하거나 공격적인 사람처럼 보일 수도 있습니다.
전략가는 가끔 다른 사람을 대하는 일 자체가 불필요한 것은 아닌지 생각할 때가 있습니다.
하지만 전략가도 다른 성격과 마찬가지로 다른 사람과의 소통을 원합니다. 다만 자신과 가치관이 비슷한 사람을 만나고 싶어하며, 그럴 수 없다면 차라리 혼자 있는 것을 선택할 뿐입니다. 이들은 자신의 관심사에 집중할 때 자신감을 발산하는 성격으로, 이러한 자신감은 직장 동료와 관계를 맺거나 친구나 연인을 사귈 때 도움이 되기도 합니다. #### 체스 경기와 같은 삶 전략가는 모순이 가득한 성격입니다. 상상력이 넘치면서도 결단력이 강하고, 야망이 넘치면서도 차분하고, 호기심이 많으면서도 집중력이 높은 성격이기 때문입니다. 다른 사람은 모순적인 전략가의 성격을 이해하기 힘들다고 생각할 수도 있지만, 전략가의 사고방식을 생각하면 이러한 모순도 이해할 수 있습니다. 전략가에게 삶은 거대한 체스 경기와 같습니다. 이들은 운보다는 전략에 의존하며 결정을 내릴 때마다 결정으로 인한 장단점을 심사숙고합니다. 또한 아무리 힘든 일이 생기더라도 지적 능력과 통찰력을 이용하면 승리할 방법을 찾을 수 있다고 믿습니다. #### 전략가형 인물들 이름 옆 괄호에 있는건 영화 제목. 영화 내의 인물의 성격이 INTJ 인거 일듯. Friedrich Nietzsche, Michelle Obama, Elon Musk, Christopher Nolan, Arnold Schwarzenegger, Colin Powell, Samantha Power, Walter White ("Heisenberg", Breaking Bad), Petyr Baelish ("Littlefinger", Game of Thrones), Tywin Lannister (Game of Thrones), Yennefer of Vengerberg (The Witcher series), Gandalf the Grey (The Lord of the Rings), Professor Moriarty (Sherlock Holmes series), Katniss Everdeen (The Hunger Games), Seven of Nine (Star Trek: Voyager ), Jay Gatsby (The Great Gatsby) ##[.no-sec-N#sec-CV] Curriculum vitae (이력서)
  • 1984-11-08: Born in Ansan, Republic of Korea.
  • 2002-03 ~ 2006-02: Diploma studies in Physics at KAIST, Korea.
    // Simple Research on Quantum Dot and Quantum Information theory.
    // Graduation thesis on ‘Electro-Magnetism with General Relativity’; Crude try on explanation of electro-magnetic forces from gravity only. See .
  • 2007-09 ~ 2013-12: Entered Seoul National University.
    // Combined master’s and doctorate course in Experimental Lab and Theoritical Lab .
    // But dropped at 2013 since I don't care about insignificant certificate of Doctorial degree.
    // Published papers are listed in Subsec. .
  • 2014 ~ Now: Developed recoeve.net .
  • 2017-07 ~ 2017-10: Skelter Labs intern (3 months).
    // The proudest program which I coded alone is the one to correct inaccurate location measured by GPS with wifi RSSI (Received Signal Strength Indicatior) .
  • 2018-04-21 ~ Now: Managed Emart24 learning economies .
SNU
### Incomes during scholarship Since I have a special and unique economic philosophy , I open my incomes. 지출은 privacy 라 공개를 안할지라도 돈을 어떻게 벌었는지는 다른 사람들에게 인정을 받아야 제대로 된 자본주의 경제가 돌아간다고 믿기에... 제 income 부터 공개합니다 .
### Some other remarks
  • Feb. 2008 ~ Spring 2010: Programmed plenty of Labview, C++ programs. Almost of them analyze image files taken from microscope with vector calculus. Some of them compile statistics on properties of magnetic domain.
  • Jan. 2010: Organized ‘3rd BK21 Young Physicists Workshop’. A committee of arrangements.
###[#subsec-papers] Papers Published (and Selected ones which I am proud of.) #### Truncated many-body dynamics of interacting bosons: A variational principle with error monitoring Read More : http://www.worldscientific.com/doi/abs/10.1142/S0217979215500216 This is one of my favorite papers published, although many would not understand this well enough. See it in docuK html form in .
Cited 15 times until 2023-05-26. #### Emergence of a new pair-coherent phase in many-body quenches of repulsive bosons
#### Universality Classes of Magnetic Domain Wall Motion
#### Long-Range Domain Wall Tension in Pt/Co/Pt Films with Perpendicular Magnetic Anisotropy
## Recoeve.net 최근까지 개발했었던 서비스. Fuzzy search, Multi-Categorized Records 등이 핵심 포인트. Vert.x JAVA server + MySQL JDBC (Java DataBase Connector) + Javascript, jQuery, AJAX 등 이용하여 개발. 개발에 쓰인 코드들은 github.com/kipid/Recoeve 에서 열람 가능합니다. history.pushState 를 이용해서 페이지를 새로 띄우지 않고 내부적으로 이동하도록 디자인 했습니다. 개발하면서 정리했던 Recoeve database setup 도 참고하시기 바랍니다. Machine learning 을 이용한 user-collaborative recommendation 이 핵심. Self-customizing + Multi-Categorized Records, or Scrapbook, for Everything, and Personalized Recommendation for Everything at each Category, which can be called Computer-Assisted Cloud/Crowd Curating. The below page is [Music/Break]--K-Pop of kipid's Recoeve.net.
### Fuzzy search Fuzzy search 를 이용해 자신이 reco 했던 것들을 쉽게 다시 찾을 수 있도록 만들었습니다.
### Structured and Multi Categorization Tag 기능과 비슷하지만 상하위 구조를 가지는 (structured) categorization 이 가능하도록 만들었습니다. Tag 처럼 한 reco 에 여러 category 를 구분자 ";"를 통해 지정할 수 있습니다. Category 를 입력할때도 fuzzy search 의 도움을 받을 수 있도록 구현하였습니다.
Reco 의 category 부분 link 를 통해서도 category jump 가 가능하도록 만들었습니다.
### Change orders of category list Category list 의 위치를 user 가 쉽게 바꿀 수 있도록 디자인하고 구현하였습니다. 제 페이지 https://recoeve.net/user/kipid 에서 테스트 해보실 수 있습니다. (본인 페이지가 아니더라도 category list 위치를 수정할 수 있게 디자인하였습니다. 자기 페이지가 아닌만큼 이 순서는 페이지 새로고침 전까지만 유지됩니다. 새로고침하면 원래 user 의 category list 순서대로 다시 돌아옵니다.)
### Pattern replace 를 통한 다국어 지원 Pattern replace 를 통해 다국어 지원이 쉽도록 디자인 하였습니다.
[--Pattern--] 형태를 찾아 다국어 replace. 아래는 코드 일부분. ```[.linenums.scrollable.lang-java] public static final Pattern ptnReplacer=Pattern.compile("\\[--[\\s\\S]+?--\\]"); public static final Pattern ptnVariable=Pattern.compile("\\{--[\\s\\S]+?--\\}"); static { fileMap=new HashMap<String, Map<String, ArrayList<String>>>(fileMapSize); File file=null; String fileStr=null; file=new File(filePath+"lang.txt"); if (file.exists()) { try { StringBuilder sb=new StringBuilder(); int ch; FileReader reader=new FileReader(file); while((ch=reader.read())!=-1) { sb.append((char)ch); } reader.close(); fileStr=sb.toString(); } catch (IOException e) { System.out.println(e); } finally { file=null; } } StrArray langMap=new StrArray(fileStr, true, true); // System.out.println(langMap); fileStr=null; for (String fileName: fileNames) { file=new File(filePath+fileName); if (file.exists()) { try { StringBuilder sb=new StringBuilder(); int ch; FileReader reader=new FileReader(file); while((ch=reader.read())!=-1) { sb.append((char)ch); } reader.close(); fileStr=sb.toString(); } catch (IOException e) { System.out.println(e); } finally { file=null; } } if (fileStr!=null) { // System.out.println("\nfileName : "+fileName); fileMap.put(fileName, new HashMap<String, ArrayList<String>>(fileLangMapSize)); Map<String, ArrayList<String>> fileLangMap=fileMap.get(fileName); ArrayList<String> strListVars=new ArrayList<String>(); Matcher matchVariable=ptnVariable.matcher(fileStr); // default int start=0; while (start<fileStr.length()) { if (matchVariable.find(start)) { strListVars.add(fileStr.substring(start, matchVariable.start())); strListVars.add(matchVariable.group()); start=matchVariable.end(); } else { strListVars.add(fileStr.substring(start)); start=fileStr.length(); } } fileLangMap.put("df", strListVars); // default. ArrayList<String> strList=new ArrayList<String>(); Matcher matchReplacer=ptnReplacer.matcher(fileStr); start=0; while (start<fileStr.length()) { if (matchReplacer.find(start)) { strList.add(fileStr.substring(start, matchReplacer.start())); strList.add(matchReplacer.group()); start=matchReplacer.end(); } else { strList.add(fileStr.substring(start)); start=fileStr.length(); } } if (strList.size()>1) { int colSize=langMap.getColSizeAtRow(0); for (int k=2;k<colSize;k++) { String lang=langMap.get(0,k); if (!lang.equals("desc")) { String strReplaced=""; String replaced=null; for (int i=0;i<strList.size();i++) { if (i%2==0) { strReplaced+=strList.get(i); } else { replaced=langMap.get(strList.get(i), lang); if (replaced==null||replaced.isEmpty()||replaced.equals("-")) { replaced=langMap.get(strList.get(i), "en"); // "en" is default lang. } if (replaced==null) { replaced=strList.get(i); } strReplaced+=replaced; } } strListVars=new ArrayList<String>(); matchVariable=ptnVariable.matcher(strReplaced); // [--lang--] replaced start=0; while (start<strReplaced.length()) { if (matchVariable.find(start)) { strListVars.add(strReplaced.substring(start, matchVariable.start())); strListVars.add(matchVariable.group()); start=matchVariable.end(); } else { strListVars.add(strReplaced.substring(start)); start=strReplaced.length(); } } fileLangMap.put(lang, strListVars); // after replacing langMap. } } } fileStr=null; } } } public FileMapWithVar() {} public static String get(String fileName, String lang, Map<String,String> varMap) { Map<String, ArrayList<String>> fileLangMap=fileMap.get(fileName); if (fileLangMap==null) {return null;} ArrayList<String> strList=fileLangMap.get(lang); if (strList==null) { strList=fileLangMap.get("df"); } String res=""; String replaced=null; for (int i=0;i<strList.size();i++) { if (i%2==0) { res+=strList.get(i); } else { replaced=varMap.get(strList.get(i)); if (replaced==null) { replaced=strList.get(i); } res+=replaced; } } return res; } ```/ ### 둘러보기 (로그인 및 카테고리 별로 둘러보기)
### Recoeve.net as a playlist of YouTubes and videos Youtube API 를 이용해서 자신이 reco 한 youtube 영상들을 연속으로 재생할 수 있게 해놓았습니다. 1개의 동영상만 반복해서 재생할수도 있고, 전체 영상을 반복해서 재생할수도 있게 디자인했고, Shuffle 기능도 구현해 놨습니다. Reco 해 놓은 youtube 영상이 재생될 수 없는 경우에는 1초뒤 다음 영상으로 재생되도록 error handling 도 해 놓았습니다.
테스트는 https://recoeve.net/user/kipid?cat=[Music/Break]--K-Pop 에서 해보실 수 있습니다. "Toggle reco list play" 버튼을 눌러보세요. #### 둘러보기 (유튜브 뮤직비디오 연속 재생하기.)
### Side widget Side widget 을 만들어서 어느 위치에서든 Go (Fuzzy search), Forward, Backward, New Reco 가 쉽도록 디자인 하였습니다.
### 둘러보기 (Reco example :: Reco imgur page.)
### Recoeve widget (Recoeve 로 내보내기) Recoeve widget 을 만들어서 twitter 나 facebook 처럼 SNS 내보내기 가 가능하도록 만들었습니다.
### Editting reco Reco 의 수정이 쉽도록, 그리고 바로 화면에 반영되도록 구현하였습니다.
### 동영상과 가사 함께보기 Reco description 에 #lyrics 를 통해 가사를 입력하면 Toggle lyrics 버튼과 함께 가사를 접었다 펼 수 있게 디자인했습니다. 동영상은 stick to the left top 버튼을 통해 왼쪽 위에 붙일 수 있도록 만들었습니다.
### Scalable design 스마트폰에서도 잘 동작하도록 CSS media query 를 통해 Responsible/Scalable 하게 디자인 하였습니다. 사이트를 방문하셔서 직접 테스트 해보세요.
아래는 사용된 CSS. ```[.linenums.scalable.lang-css] @media all and (min-width:701px) { #container {margin-left:14.9em} #sidebar {margin:0; position:fixed; left:0; top:0; bottom:0; width:15em} #sidebar-dragger {display:none} #sidebar-exit {display:none} .side2 {padding:.5em} .rC.fixed {width:646px; border-right:.15em solid black} .lyrics {text-align:right} ::-webkit-scrollbar {width:11px; height:11px} } @media all and (min-width:901px) { #container {margin-left:19.9em} #sidebar {width:20em} } @media all and (min-height:500px) { #fuzzy-search-list {max-height:430px;} } ```/ ### 로그인 암호 해킹 방지 시스템 Iteration 이 들어가는 단방향 암호화 (Hash) 를 이용해서 네트워크 중간에 가로채는 해킹에 대해서도 어느정도 면역이 생기게 디자인하였습니다. User 쪽 javascript 단에서 처음에는 10000 iteration 해서 보내고. 다음부터는 9999 iteration 해서 보내고 나머지는 server 에서 iteration 통해 암호가 일치하는지 확인하는 방법. 사용자 암호가 털리지 않는한, 네트워크 중간에서 가로챈 암호화 된 암호 가지고도 해킹이 불가능하게 디자인. 단 user 쪽 iteration 은 항상 줄어들어야 함. 안그러면 hash function 이 javascript 에 노출되므로 뒷쪽 iteration 을 유추가능. Server 의 user data 에는 iteration 정보를 저장하고 있어야 하고, user 가 로그인할때 id/e-mail 만 AJAX 로 먼저 보내서 암호 iteraion 을 몇번할 것인지 받아낸 다음 iteration 으로 암호화 후 전체 데이터 전송. 아래는 코드 일부분. ```[.linenums.scrollable.lang-javascript] eve.encrypt=function(salt, pwd, iter) { iter=pwd.length+131+((iter&&iter.constructor==Number&&iter>=0)?iter:0);; pwd=salt+pwd; var h1=eve.hash1(pwd); var h2=eve.hash2(pwd); var h3=eve.hash3(pwd); var h4=eve.hash4(pwd); var h5=eve.hash5(pwd); var h6=eve.hash6(pwd); var h7=eve.hash7(pwd); var h8=eve.hash8(pwd); var h9=eve.hash9(pwd); var h10=eve.hash10(pwd); var h11=eve.hash11(pwd); var h12=eve.hash12(pwd); var h13=eve.hash13(pwd); var tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13; for (var i=0;i<iter;i++) { tmp1=h13+h12+h11+h10+h9+salt+h8+h7+h6+h5+h4+h3+h2+h1; tmp2=h1+h3+salt+h2; tmp3=salt+h2+h8+h1+h3; tmp4=h7+salt+h5; tmp5=h4+salt+h8; tmp6=h10+h13+salt+h6; tmp7=h6+h1+h9+salt; tmp8=h9+salt+h10; tmp9=h7+salt+h12; tmp10=h11+salt+h5; tmp11=h4+salt+h13+h2; tmp12=h11+salt+h6; tmp13=h4+h12+salt+h8; h1=eve.hash1(tmp1); h2=eve.hash2(tmp2); h3=eve.hash3(tmp3); h4=eve.hash4(tmp4); h5=eve.hash5(tmp5); h6=eve.hash6(tmp6); h7=eve.hash7(tmp7); h8=eve.hash8(tmp8); h9=eve.hash9(tmp9); h10=eve.hash10(tmp10); h11=eve.hash11(tmp11); h12=eve.hash12(tmp12); h13=eve.hash13(tmp13); } return h1+h2+h3+h4+h5+h6+h7+h8+h9+h10+h11+h12+h13; }; eve.iterFull=10000; eve.logIn=function(elem) { var $elem=$(elem).eq(0); $elem[0].disabled=true; var $form=$elem.parent("form").eq(0); var idType="id"; var userId=$form.find(".user-id")[0].value; var userIdLength=eve.byteCount(userId); var userPwd=$form.find(".user-pwd")[0].value; var err=""; var valid=false; if (userIdLength==0) { err+="[--ID or E-mail is empty.--]"; } else if (userIdLength<eve.minIdLength) { err+="[--ID or E-mail is too short.--]"; } else if (userPwd.length==0) { err+="[--Password is empty.--]"; } else if (userPwd.length<eve.minPwdLength) { err+="[--Password is too short.--]"; } else { if (eve.regExId.test(userId)) { $form.find("#input-idType")[0].value=idType="id"; valid=true; } else if (eve.regExEmail.test(userId)) { $form.find("#input-idType")[0].value=idType="email"; valid=true; } else { err+="[--ID--]/[--E-mail--] '"+userId+"' [--is of invalid form.--]"; } } if (valid) { var form_data="log\tiehack\tscreenWidth\tscreenHeight\tidType\tuserId\trememberMe\tuserPwd\n" +"web\t☠\t"+sW+"\t"+sH+"\t"+idType+"\t"+userId+"\t"+($("input:checkbox[name='rememberMe']").is(":checked")?"yes":"no")+"\t"; $elem.before( eve.encloseErr("[--Checking ID/E-mail--] : [--Please wait.--]") ); $.ajax("./pwd_iteration", { type: "POST" , data: idType+"\t"+userId }).fail(function() { $elem.before( eve.encloseErr("[--Request times out.--] [--Please click the Log-in button again.--]") ); $elem[0].disabled=false; }).done(function(resp) { // resp: pwd_iteration or "No such id" salt var res=resp.split('\t'); var iter=Number(res[0]); if (isNaN(iter)) { $elem.before( eve.encloseErr("Error : "+res[0]) ); $elem[0].disabled=false; } else { $elem.before( eve.encloseErr("[--Password is being encrypted.--]") ); setTimeout(function() { form_data+=eve.encrypt(res[1], userPwd, iter); userPwd=""; $elem.before( eve.encloseErr("[--Logging in--] : [--Please wait.--]") ); $.ajax("./log-in.do", { type: "POST" , data: form_data }).done((resp) => { $elem.before( eve.encloseErr(resp) ); if (resp==="log-in success") { window.location.pathname="/"; } else { $elem[0].disabled=false; } }); }, 500); } }); } else { $elem.before( eve.encloseErr(err) ); $elem[0].disabled=false; } var errorMsgs=$form.find(".error-msg"); for (var i=errorMsgs.length-6;i>=0;i--) { errorMsgs.eq(i).css({display:"none"}); }; }; ```/ 아래는 동작하는 장면.
### Delayed loading 을 통한 high performance 구현 Reco 들이 많아지면 많아질수록 페이지 다운로드 속도가 느려질 수 있는데 click event 나 scroll event 를 통해 delayed loading 이 trigger 되도록 구현해 high performance 를 구현하였습니다. 또한 페이지 reload 없이 history.pushState 를 이용 페이지를 새로 띄우지 않고 내부적으로 category 를 이동하도록 디자인했습니다. 한번 방문했던 category 의 data 들은 javascript 에 저장해 다시 같은 category 를 방문했을때에는 http request 없이 (즉 통신없이) 이전에 다운로드 받았던 reco list 를 출력하도록 구현했습니다.
## Markdown Language : SEE (Super Easy Edit) and docuK 인터넷에서 글쓸때, 매번 html 로 작성하기는 너무 많은 공을 필요로 해서 만들게 된 Markdown Language. 해당 코드들은 github.com/kipid/docuK 에서 확인 가능합니다. This is an HTML document format named docuK which is rendered by JavaScript, jQuery, MathJax, and google code prettifier. Specific features are
  • Changable mode, font-family.
  • Resizable font-size, line-height.
  • Table of contents.
  • Numbering of sections/figures/equations.
  • Citing references in bubble-shape pop up.
  • Refering figures and equations.
  • Refering anything with id and element with class="number".
  • Delayed(lazy)-loading of figures (images, iframes).
  • Delayed(lazy)-rendering of maths (MathJax).
  • Auto code printing from <codeprint id="code-id"></codeprint> to <pre id="pre-code-id"></pre>.
  • Quite similar to LaTeX or Wiki document, but extended a little bit.
The details are described in This document is also made up by using docuK+SEE. ### Citing references and Refering anything inside docuK You can cite references like <cite class="ref-some"></cite>. \sum_i x_i ... Refering the above equation . ### Delayed(lazy)-loading and rendering Delayed(lazy)-loading of images, videos, html element with src attribute. And delayed(lazy)-rendering of MathJax. \begin{aligned} \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ \nabla \cdot \vec{\mathbf{B}} & = 0 \end{aligned} ## LaTeX to HTML and "docuK" format "LaTeX to HTML"는 LaTeX 형태로 만들어진 문서를 HTML로 바꿔주는 프로그램입니다. (이 converter는 아주 간단한 형태의 LaTeX 문서만 convert 되고 저 개인에 맞춰진 감이 크긴 합니다.) "docuK"는 document designed by kipid란 뜻으로 개인적으로 만들고 있는 LaTeX 비슷한 HTML document format입니다 . 이 문서도 docuK format을 이용해서 만들었습니다.
tensor.png
LaTeX로 편집한 Tensor 관련 설명. (텐서와 상대론 - Tensor란 무엇인가?) 그림과 같이 자동으로 "Table of Contents"가 만들어지고, hyperlink도 자동으로 만들어짐.
LaTeX는 수식이 많이 들어가있는 문서나 구조화 (상호참조(cite, refer), 목차(table of contents, section, subsection), 참고문헌(references) 등) 되어있는 문서의 작성에 용이한 문서 편집 방식입니다 . 하지만 대부분 결과물을 출력이 용이한 pdf 파일형태로 내놓기 때문에 인터넷 상에서 공유하고, 문서의 내용 또한 웹 검색엔진에서 검색이 되도록 하는데에는 불편한 점이 많습니다. 물리 연구를 하면서 몇가지 물리전문지식들에 대한 설명들을 LaTeX 문서로 정리하게 되었는데 , 인터넷 상에서도 공유하고 싶어서 만들어 보게 된 프로그램입니다. 많은 책들과 논문들이 LaTeX 형태로 편집되고 작성되기 때문에 E-book과도 관련이 있을듯했고, HTML(css, javascript 등)도 더 공부해볼겸 수작업을 많이 거치면서 어떤식으로 LaTeX 문서를 HTML 형태로 바꿀지를 고민하면서 만든 프로그램 입니다. 최근에는 HTML을 더 공부하면서 docuK format을 만들고 있기도 합니다 . 궁극적으로는 WYSIWYG (What you see is What you get) 형태의 편집과 text 형태의 명령어 편집의 장점들만 모아놓은 편집기를 개발해보고 싶은 욕심도 있습니다.
  1. 기본적으로 수식이 들어가는 HTML 문서는 이미지 형태의 인터넷 수식을 제공하는 codecogs.com나 javascript를 이용해 문자위치를 적절히 배치해 수식으로 나타내주는 MathJax를 사용하여 만듬 .
  2. 문서가 긴 경우 스크롤이 너무 길 수 있고, 문서를 읽는 사람이 어디쯤을 읽고 있는지도 파악이 어렵기 때문에 “▼ Show/Hide, ▲ Hide” 기능을 javascript/jQuery로 구현해서 첨부. 클릭시 각 section, subsection을 보여주거나 감춤. (감출때는 window.scrollBy()를 이용해서 문서를 읽는 사용자의 혼란을 줄였음.)
  3. 전체적으로 LaTeX 명령어들을 분석하여 그에 상응하는 HTML 형태의 명령어들로 바꾸어 줌. (특수문자들도 HTML 형태로: ex] \"o -> &ouml; -> ö)
  4. \newcommand 형태로 명렁어를 간단하게 만들어 쓰는 LaTeX 문법을 분석하여 바꾸는 기능 + ref, label, cite 등 상호참조나 목차 자동만들기를 분석하여 HTML로 만드는 기능 등이 있음.
  5. 반응형 웹 (Responsible web) 으로 스마트폰, 타블렛 PC 등 다양한 화면크기에서도 제대로 보이도록 design.
아래는 docuK format에 쓰인 javascript/jQuery 일부분. ```[.linenums.scrollable] <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script> $.fn.exists=function() { return this.length!==0; } var sec=$(".docuK>.sec"), subsec, subsubsec, secContents=""; var secIH2, subsecIH3, subsubsecIH4; var i, j, k, secI=0, secITxt="", subsecI=0, subsubsecI=0, tocHtml="", txt="", secId="", secPreTxt=""; var eqqs, eqN="", eqC="", figs; function fTocHtml () { return "<h"+hN+"><a class='jump' id='toc-"+secId+"' href='#sec-"+secId+"'><span class=\"secN\">"+secPreTxt+".</span>"+txt+"</a></h"+hN+">"; } function fSecHtml () { return "<a class='jump' id='sec-"+secId+"' href='#toc-"+secId+"'><span class=\"secN\">"+secPreTxt+".</span></a>"+txt; } function fEqqHtml () { return '<div class="eqCC"><div class="eqN"><span class="number">('+eqN+')</span></div><div class="eqC">\\[ '+eqC+' \\]</div></div>'; } for (i=0;i<sec.length;i++) { secIH2=sec.eq(i).find("h2:first-child"); if (secIH2.exists() && !secIH2.is(".notsec")) { // exclude .sec>h1 and .sec>h2.notsec in ToC hN="2"; txt=secIH2.html(); if (secIH2.is(".no-sec-N")) { secPreTxt=secId=secITxt=secIH2.attr('id'); tocHtml+="<h"+hN+"><a class='jump' id='toc-"+secId+"' href='#sec-"+secId+"'>"+txt+"</a></h"+hN+">"; secIH2.html(function(ith,origText){return "<a class='jump' id='sec-"+secId+"' href='#toc-"+secId+"'>"+origText+"</a>";}); } else { secI++; secPreTxt=secId=secITxt=secI.toString(); tocHtml+=fTocHtml(); secIH2.html(fSecHtml()); } if (!sec.eq(i).is(".noToggleUI")) { secContents="sec-"+secITxt+"-contents"; sec.eq(i).append("<div class=\"Hide\" onclick=\"Hide('"+secContents+"')\">▲ Hide</div><div class=\"cBoth\"></div>"); sec.eq(i).find(">*:not(:first-child)").wrapAll("<div class=\"sec-contents\" id=\""+secContents+"\"></div>"); sec.eq(i).append("<div class=\"cBoth\"></div>"); secIH2.after("<div class=\"ShowHide\" onclick=\"ShowHide('"+secContents+"')\">▼ Show/Hide</div>"); } subsec=sec.eq(i).find(".subsec"); subsecI=0; for (j=0;j<subsec.length;j++) { subsecIH3=subsec.eq(j).find("h3:first-child"); hN="3"; subsecI++; secId=secITxt+"-"+subsecI; secPreTxt=secITxt+"."+subsecI; txt=subsecIH3.html(); tocHtml+=fTocHtml(); subsecIH3.html(fSecHtml()); subsubsec=subsec.eq(j).find(".subsubsec"); subsubsecI=0; for (k=0;k<subsubsec.length;k++) { subsubsecIH4=subsubsec.eq(k).find("h4:first-child"); hN="4"; subsubsecI++; secId=secITxt+"-"+subsecI+"-"+subsubsecI; secPreTxt=secITxt+"."+subsecI+"."+subsubsecI; txt=subsubsecIH4.html(); tocHtml+=fTocHtml(); subsubsecIH4.html(fSecHtml()); } } } else { secITxt="x"; } eqqs=sec.eq(i).find("eqq"); for(j=0;j<eqqs.length;j++){ eqN=secITxt+"-"+(j+1).toString(); eqC=eqqs.eq(j).html().trim(); eqqs.eq(j).html(fEqqHtml()); } figs=sec.eq(i).find("figure"); for(j=0;j<figs.length;j++){ figN=secITxt+"-"+(j+1).toString(); figs.eq(j).find(".caption").html(function(ith,orgTxt){return "Fig. <span class=\"number\">("+figN+")</span>: "+orgTxt.trim();}); } } $(".docuK>.sec>.toc").html(tocHtml); var eqs=$(".docuK eq"); for (i=0;i<eqs.length;i++){ eqs.eq(i).html(function(ith,orgTxt){return "\\( "+orgTxt.trim()+" \\)";}); } </script> <script> function ShowHide (divId) { $("#"+divId).toggle(); } function Hide (divId) { var div=$("#"+divId); window.scrollBy(0,-div.outerHeight()); div.hide(); } var timerHide; function ShowBubbleRef (divId) { clearTimeout(timerHide); $(".docuK .bubbleRef").hide(); $(".docuK .bubbleRef#"+divId).show(); } function HideBubbleRef (divId) { timerHide = setTimeout(function(){$(".docuK .bubbleRef#"+divId).hide();}, 1000); } function pad (str, max) { str=str.toString(); return str.length<max?pad("0"+str,max):str; } $(".docuK cite").html('<span class="emph">[No ref]</span>'); var refs=$(".docuK ol.refs>li"), i, refId, refN="", refHtml=""; var cites, j, citeN=""; function fCiteHtml () { return '<div class="inRef" onmouseover="ShowBubbleRef(\'bRef-'+citeN+'\')" onmouseout="HideBubbleRef(\'bRef-'+citeN+'\')">['+refN+']<div id="bRef-'+citeN+'" class="bubbleRef"><div class="content">Ref. ['+citeN+'] '+refHtml+'</div><div class="arrow"></div></div></div>'; } for(i=0;i<refs.length;i++){ // ref [i+1] with id if (refs.eq(i).is("[id]")){ refN=pad(i+1,2); refHtml=refs.eq(i).html().trim(); refId=refs.eq(i).attr("id"); cites=$(".docuK cite."+refId); for(j=0;j<cites.length;j++){ // (j+1)th cite of [i+1] reference. citeN=refN+"-"+(j+1).toString(); cites.eq(j).html(fCiteHtml()); } } } </script> <script type="text/x-mathjax-config"> MathJax.Hub.Config({ tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]} }); </script> <script src="https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <script> $(".docuK refer").html('<span class="emph">[No eq or fig]</span>'); var refers=$(".docuK refer"), i, referI, refered, citeN="", refN="", refHtml=""; function fReferHtml () { return '<div class="inRef" onmouseover="ShowBubbleRef(\'bRef-'+citeN+'\')" onmouseout="HideBubbleRef(\'bRef-'+citeN+'\')">'+refN+'<div id="bRef-'+citeN+'" class="bubbleRef"><div class="content">'+refHtml+'</div><div class="arrow"></div></div></div>'; } for(i=0;i<refers.length;i++){ referI=refers.eq(i); citeN=(i+1).toString()+"-"+referI.attr("class"); refered=$(".docuK #"+referI.attr("class")); refHtml=refered.html(); refN=refered.find(".number").html(); referI.html(fReferHtml()); } </script> <script> var docuKSec, fontSize=10, lineHeight=16, fontStyle="맑은 고딕", mode="dark"; function Cmode (modeI) { if (modeI==mode) { return; } var docuKSec=$(".docuK>.sec"); if (modeI=="dark") { docuKSec.css({"background":"rgb(0,0,0)","color":"rgb(255,255,255)"}); } else if (modeI=="bright") { docuKSec.css({"background":"rgb(255,255,255)","color":"rgb(0,0,0)"}); } else { return; } mode=modeI; } function CfontSize (increment) { fontSize+=increment; if (fontSize<8) { fontSize=8; } else if (fontSize>12) { fontSize=12; } $(".docuK").css({"font-size":fontSize+"px"}); $(".docuK .TFontSize").html(fontSize.toString()+"px &gt; 1.8em="+(fontSize*1.8).toString()+"px"); } function ClineHeight (increment) { lineHeight+=increment; if (lineHeight<13) { lineHeight=13; } else if (lineHeight>20) { lineHeight=20; } $(".docuK").css({"line-height":(lineHeight/10).toString()}); $(".docuK .TLineHeight").html((lineHeight/10).toString()); } </script> ```/ ## Memorizer App LabVIEW 프로그램과 안드로이드 앱 두가지로 구현.
memorizer.png
LabVIEW로 구현한 Memorizer App.
주로 단어를 외우거나 할 때 체계적으로 암기를 도와주는 프로그램.
  1. TXT파일로 A, B 두 열의 데이터만 저장해 놓는다. (꼭 2열일 필요는 없고, A와 B에 해당하는 열이 어떤것인지만 명시되면 됨.)
  2. 파일 선택 뒤, 몇번째 행부터(From) 몇개의 단어를 외울것인지(count) 결정한다. Cutoff ratio를 설정하고 Auto Select 옵션을 키면 최근 10개의 성적(Recent 10 Scores)이 cutoff를 넘긴 단어는 제외하고 외울단어들을 count(예: 20개)만큼 선택한다.
  3. 프로그램을 시작하면 랜덤하게 문제에 해당하는 A를 보여주고 답 B를 맞추도록 한다. (A를 보고 B를 맞출수도 있고, B를 문제로 내고 A를 맞추게 할수도 있다.)
  4. 현재 얼마나 진행되었고, 몇개를 맞추고 틀렸는지를 막대 바 형태로 출력해준다. (맞추었는지 틀렸는지의 판단은 사용자가 직접 클릭을 통해 함. 문자 입력을 받은 뒤 자동처리도)
  5. 한번의 사이클이 다 지나면, 틀린문제만 모아서 다시 순서를 섞은 뒤 다 맞출때까지 반복시킨다. (잘 외워지지 않는 것들만 반복적으로 더 보여줌으로써 암기 효율을 높인다.)
  6. 암기가 다 끝났다면, 이번에 외운 단어들의 성적을 색을 이용하여 시각적으로 보여준다. (성적 표시는 HTML을 이용.)
memorizer_html.png
Memorizer App 결과. 암기 결과를 어떻게 보여줄지 고민하다가 여러기기에서 잘 동작하는 HTML 형태로 결정. HTML table은 LabVIEW 프로그램을 통해 자동으로 생성된 뒤 열림. 빨간색은 잘 못외운 단어들, 녹색은 잘 외운 단어들. 밝은 색은 최근 성적이 좋은 단어들, 어두운 색은 최근 성적이 좋지 못한 단어들이다.
mem1.png mem2.png mem3.png mem4.png mem5.png mem6.png
안드로이드 앱으로 구현해 놓은 암기어플의 진행과정 스크린샷. 앱은 LabVIEW로 구현한 것에 비해 몇가지 기능들이 빠져있는 하위버전입니다. 안드로이드 앱 만드는 법을 배워볼 목적으로 만든 감도 있어서 기초적인 기능들로만 구현되어 있습니다.
여러 사이트들에서 제공되는 인터넷 사전 대부분은 사용자가 검색했던 단어들의 리스트를 모아서 내 단어장을 만들어줍니다. 기본적인 단어들만 모아놓은 공개단어장들을 제공하기도 합니다. 이런 파일들을 다운받아 txt 형태로 저장하고 잘 외워지지 않는 단어들을 더 반복적으로 외울 수 있게 만들었습니다. 사진을 보여주고 답을 맞추게 하는 기능 등도 추가로 생각 중 입니다. 개인적으로 영어공부를 할 때 필요로해서 만든 앱이라 저 개인에 맞춰진 감이 많습니다. 또한 요새는 굳이 뭔가를 외울일이 없어서 방치해두고 있는 앱이기도 합니다. (그냥 무료로 배포할까 생각했었는데, 아직 만족할만큼 완성된 것도 아니고 마켓에 올리는 절차가 복잡한거 같아서 계속 미뤄지고 있는 중입니다.) ## Designed and Produced Lab Homepage and Blog page ### Lab Homepage 대학원에서 연구를 하면서 교수님께서 Lab Homepage가 있으면 좋을거 같다는 말씀에 간단하게나마 만들어 드렸습니다 . HTML이나 CSS를 계속 배워나가면서 지금 다시보니 이것저것 이상한 부분도 고치고 싶은 부분도 많긴 합니다.
iframe of Lab Homepage of "Theory of Cold Atoms @ SNU"
### Publications
iframe of 이강수. 제가 참여한 논문들 목록입니다. Excel, Google spreadsheet 형태로 정리해 놓은것을 프로그래밍을 통해 HTML code로 변환하여 추가하였습니다. Lab Homepage의 다른 publication list도 같은 방식으로 작업.
### Blog page (kipid's blog)
iframe of 개인 블로그 페이지 (kipid's blog). 기본 티스토리 스킨(skin.html) 및 css를 약간 손봐서 꾸민 개인 블로그 페이지입니다. 스마트폰에서도 같은 화면이 보이도록 반응형(responsible web with css media query)으로 만들었습니다.
## 음력/양력 변환 및 D-day, D+day 계산기
Date_SL.png
양력을 음력으로 변환.
Date_LS.png
음력을 양력으로 변환.
Date_SD.png
기준일로부터 몇일째인지 계산. (양력)
Date_LD.png
기준일로부터 몇일째인지 계산. (음력)
음력과 양력 변환. 이 외에도 다른 달력으로의 변환이 어떻게 이루어지는지 분석하여 프로그램을 만들어 보았습니다. 음력 달력의 경우 달의 공전을 기준으로 날짜를 정하기 때문에 정확한 규칙이란것이 없지만, 각 달의 정보를 데이터베이스화 놓은뒤 대략적인 규칙을 이용해 빠르게 원하는 데이터를 접근하고 상호 변환이 가능하도록 프로그래밍 하였습니다.
  1. 기준일(0번째 일)을 "양력 1900년 01월 01일 = 음력 1899년 12월 01일"로 잡고, 이 기준일로부터 매월 첫째일이 몇번째 날인지 그 달의 총 일수는 몇인지를 데이터베이스화 해놓음.
  2. 달력마다 각 달의 평균일수가 정해져 있으므로 이 평균일수로 기준일로부터의 일수를 나누어 1~2번내에 바로 해당일의 달력 데이터에 접근할 수 있도록 프로그래밍.
  3. 대략 200년 정도의 음력 데이터베이스는 20KB, 3000년간의 양력 데이터베이스는 282KB를 차지. 입력된 날짜의 유효성에 따라 Error는 “Out of convertible years”, “Out of month”, “Out of day”, “Wrong leap option A/B”등을 반환.
날짜를 기준으로한 그래프를 그릴때나 시간 개념이 들어간 대규모 데이터를 처리할 때, 날짜를 숫자로 바꿔주는 이러한 코드 (최적화 되어 속도도 빨라야 하는) 를 필요로 하여 만들어 보았습니다. (이미 배포된 여러가지 코드들이 있는것 같았지만, 속도나 확장성 면에서 마음에 드는게 없었어서...) ## Canvas: 프로그램화 된 그림/그래프
Canvas.png
프로그램화 된 그림/그래프를 예쁘고 쉽게 그리고 싶어서 만들고 있는 프로그램. 이미지를 분석하는 작업도 가능.
시중에 그래프를 그려주는 다양한 프로그램들이 있지만, text 기반의 명령어로 프로그램화해서 수학적인 그림들 (line, rectangular, polygon and so on) 과 그래프를 그려주는 프로그램은 찾지 못했습니다. 이런 프로그램이 있다면 조금 더 개인 취향에 맞게, 내 임의대로 많은것을 편집하고 조정할 수 있는 그래프를 그릴 수 있을것 같다는 생각, 한번 공들여 그린 그래프 포멧을 쉽게 재사용 할수는 없을까하는 생각이 들어서 만들어보고 있는 프로그램입니다. 또한 그래프 프로그램들이 어떻게 돌아가는지도 bottom up으로 공부하고 싶기도 했고, 짜면서 프로그래밍 적으로 배우는것도 많고, 그래프 외에도 여러가지로 활용할 수 있을거 같아서 만들어 봤습니다. (최근에는 HTML과 javascript를 배우면서 그림이 아닌 사용자와 반응하는 그래프들 (interactive graph) 을 어떻게 구현할 수 있을까도 공부하고 있습니다 .) 기본적으로 구상하고 구현한 명령어들은 다음과 같습니다. Text 명령어를 분석하여 RGB로 구성된 24bit color image array의 값들을 조정하는 방식입니다. ```[.linenums.scrollable] /* multi-line comments */ // single line comment // Trim whitespaces always automatically. // Command [\s\t\n\r] ";" End-marker // 속성(Attributes) ":(" delimiter // 인수값(Arguments) ")" delimiter // "/" color delimiter "//" comments랑 겹치는데... // If an error occurs, stop and display remaining commands. // CanvasLoad, Canvas8, Canvas24 // First command must be "Canvas24" or "Canvas8". Canvas24 right,bottom:(400,300) background:(255/255/255); // with opacity: (255/255/255,1.0) // Default right,bottom:(0,0) // Default background:(255/255/255); Canvas8 right,bottom:(400,300) background:(255); // Default right,bottom:(0,0) // Default background:(255); CanvasLoad file:(C:\Folders\file.bmp); // Absolute path: "[A-Z]:" // Relative path: // "a.bmp" under base folder // "..\a.bmp" upper folder // "..\..\a.bmp" upper-upper folder and so on. // Save, #Define // line1s, lines, lline1s, llines, cline1s, clines // rectangles, circles, circleLines, polygon // texts Save file:(C:\Folders\file.bmp); #Define var:(00/00/00) var2:(5px); // makes '"var"' into '00/00/00' // affects only afterwards. line1s color:(255/0/0) offset:(100.5,10.5) x0y0 to x1y1:( // x0y0 toward dxdy:( 10 10 100 100 100 100 10 100 ); lline1s // linked line1s : cline1s // closed line1s color:(255/0/0) offset:(100.5,10.5) xn yn:( // x0y0 dxdys:( 0 0 100 0 100 100 0 100 ); lines, llines, clines line_width:(2.0) rectangles color:(0/0/0) offset:(100.5,10.5) x0y0 to x1y1:( // x0y0 toward dxdy:( 10 10 100 100 ); ```/
CanvasEx0.png
프로그램화하여 그린 그래프 예시 (Roughness Exponent of Magnetic Domain Wall/Boundary ). 이 그래프는 제가 만든 프로그램으로 그린 그래프이기는 하지만, 위에 열거한 text 기반 명령어로 돌리지는 않았습니다. 이런 저런 그래프들 (알리고자 하는 바를 명확히 나타내는) 을 그리면서 text 명령어 기반으로 그림/그래프를 그려주는 프로그램이 있으면 좋을것 같아 만들게 된 프로그램이 Canvas입니다.
CanvasEx1.png
각 나라들의 GDP를 그래프로 보여주는 프로그램을 만들어 본 적도 있습니다. 제가 원하는 형태까지는 아직 못만들었지만… Canvas 프로그램을 만들기 시작한 이유가 이것 때문이기도 합니다.
CanvasEx2.png
촛불 집회 인원수가 논란이 되었어서 짜본 집회 인원수 추산 프로그램.
Figure 는 Canvas에 추가적으로 프로그램을 짜서 이용했고 사용한 명령어는 다음과 같습니다. ```[.linenums] CanvasLoad file:(image\촛불 큰사진.jpg); Count color:(250/250/200) around:(150) min&max domain:(1, 900) // min보다 미만인 애들과 max보다 초과인 domain은 제거. font&format:(굴림, 10:%#p) // font, font-size:format per:(10); Save file:(image\촛불 큰사진 counted.jpg); ```/ 이미지를 제대로 분석하려면 고화질 풀샷을 필요로 했는데 구할수가 없어서 대충만 분석한 결과입니다. 결과값에 대한 오해가 있을수 있어 첨언하자면, 멀리서 찍힌 촛불 부분에서의 노이즈 및 촛불을 들지 않고 있는 사람을 못센 다는 점 등이 있어 넓이와 인구밀집도로도 추산하였었습니다. (이건 제가 프로그램한게 아니라서… 포트폴리오에 넣는게 적절하지는 않지만.)
CanvasEx2DaumMap.png
다음지도 서비스를 이용하여 서울시청광장 집회장소의 사람밀집지역 넓이 추정. => 10,887m$^2$. 3.3m$^2$(1평)당 5~8명 정도 계산. (밀집집회에 대한 경찰들의 일반적인 추산) => 16,500~26,400명. 참고로 경찰 추산은 딱 "한 시기"에 집회장소에 모여 있는 사람, 주최측 추산은 "잠시 들렀다가 간 사람"도 포함해서 계산한다고 합니다.
## 기타: 물리연구 및 잡다한 일들 (개인적인 관심사 통계분석 등) 을 하면서 만들었던 프로그램들. 가장 많은 시간을 투자하고 복잡한 구성을 가진 프로그램들은 물리연구를 하면서 만든 것들이지만, 다른곳에 활용도가 떨어지고 그래픽적으로 보여줄 부분은 많지 않아서 일부만 캡쳐했습니다. 대부분 이미지 데이터를 처리하고 분석하는 프로그램들, 수치계산 프로그램들 입니다.
ImageProcess.png
Magnetic Domain 이미지 처리 과정: 원본(raw) 이미지에서 background를 뺌.
현미경을 통해 PMA (Perpendicular Magnetic Anisotropy) thin film의 자성변화를 MOKE (Magneto-Optical Kerr Effect) 현미경을 통해 관측/기록. 이 과정에서 외부에서 가해주는 자기장 등 내외부 요인으로 자성박막이 미세하게 ($1\sim10 \mu m$ 정도) 떨림. 이를 자성박막에 고정되어 있는 black spot(불순물)을 이용해 기판이 움직인것을 보정해서 background로 찍은 여러장의 사진을 average하고 raw image를 x-y로 shift해서 뺌. (이 과정은 프로그래밍적으로 돌아감. 선택된 black spot 부분이 가장 일치하는 shift 값을 찾아가서 image를 처리하도록 프로그래밍. Shift는 정수(integer) pixel로만 움직이는 것이 아니라 double 값으로 이동. Black spot 부분의 standard deviation 값이 minimum이 되는 부분을 찾아가는 프로그램. 기본적으로 method of the steepest descent 및 속도 향상을 위해 Hessian matrix (다차원에서의 2차 근사) 등을 이용.) 이후 contrast와 offset을 조정해 Black&White로 변환. Domain 분석을 통해 크기가 noise 이하이면 주변(surrounding) color로 변환.
ImgP1.png ImgP1-1.png
자성 Domain이 확장하는 것을 현미경으로 찍어 저장한 이미지들에서 일정 시간간격으로 이미지를 추출하고 겹쳐서 한눈에 시간에 따른 Domain 확장을 보여주는 이미지 제작 프로그램. Color code로 시간표현 및 각 사진상의 noise도 표현 .
ImgP1-1.png ImgP1-1.png
자성 Domain이 확장하는 이미지들을 분석하여 Domain wall (Up domain과 Down domain의 경계부분) 이 움직이는 속도를 측정해주는 프로그램. 이미지를 저장할 때 같이 저장된 “측정배율(10x, 100x), 시간, 자기장값” 등을 같이 이용하여 자동으로 분석.
이미지를 분석하는 프로그래밍에 C++의 class 기능이 유용해서 C++와 LabVIEW (그래프 및 데이터 입력/출력 컨트롤에 용이) 를 DLL (Win32 Dynamic-Link Library) 를 연계하여 프로그램을 만들었음. ▼ 아래는 사용한 C++ 코드 예시. (너무 길어져서 ImageProcess.cpp 파일 중 일부만.) ```[.linenums.scrollable] #include <iostream> // input, output stream. (cin << ; cout <<;) #include <fstream> // file input, output stream. (fout <<; f.seekg();) #include <cmath> // c math. (sqrt) #include <cstdlib> // c standard lib. using namespace std; // class Vector_d2D (Vector double 2-Dimensional) : start class Vector_d2D{ public: double x; double y; public: // Constructor Vector_d2D(double x0=0, double y0=0){ x = x0; y = y0; }; ~Vector_d2D(){ x = 0; y = 0; }; // Operators Vector_d2D& Set(const double x0, const double y0){ x = x0; y = y0; return *this; }; bool operator==(const Vector_d2D& v) { return ( x==v.x && y==v.y ); }; bool operator!=(const Vector_d2D& v) { return ( x!=v.x || y!=v.y ); }; Vector_d2D& operator= (const Vector_d2D v) { x = v.x; y = v.y; return *this; }; Vector_d2D& operator+=(const Vector_d2D v) { x += v.x; y += v.y; return *this; }; Vector_d2D& operator-=(const Vector_d2D v) { x -= v.x; y -= v.y; return *this; }; Vector_d2D& operator*=(const double rH) { x *= rH; y *= rH; return *this; }; Vector_d2D& operator/=(const double rH) { x /= rH; y /= rH; return *this; }; Vector_d2D operator-()const{ Vector_d2D res; res.x=-x; res.y=-y; return res; }; Vector_d2D operator+(const Vector_d2D rH) const{ Vector_d2D res; res.x=x+rH.x; res.y=y+rH.y; return res; }; Vector_d2D operator-(const Vector_d2D rH) const{ Vector_d2D res; res.x=x-rH.x; res.y=y-rH.y; return res; }; // inner product double operator*(const Vector_d2D rH)const{ double res; res=x*rH.x + y*rH.y; return res; }; Vector_d2D operator*(const double rH)const{ Vector_d2D res; res.x=x*rH; res.y=y*rH; return res; }; friend Vector_d2D operator*(const double lH, const Vector_d2D rH) { Vector_d2D res; res.x=lH*rH.x; res.y=lH*rH.y; return res; }; Vector_d2D operator/(const double rH)const{ Vector_d2D res; res.x=x/rH; res.y=y/rH; return res; }; const Vector_d2D Crossz(const double z){ Vector_d2D res; res.x=y*z; res.y=-x*z; return res; }; const double norm(){ return sqrt(x*x + y*y); }; friend ostream& operator<<(ostream& os, const Vector_d2D& v){ os<<v.x<<"\t"<<v.y; return os; }; }; double norm(const Vector_d2D v){ return sqrt(v.x*v.x + v.y*v.y); } double norm(const double x, const double y){ return sqrt(x*x + y*y); } double Cross(const Vector_d2D v1, const Vector_d2D v2){ double res; res = v1.x*v2.y - v1.y*v2.x; return res; } Vector_d2D Cross(const double z, const Vector_d2D v){ Vector_d2D res; res.x = -z*v.y; res.y = z*v.x; return res; } Vector_d2D Cross(const Vector_d2D v, const double z){ Vector_d2D res; res.x = v.y*z; res.y = -v.x*z; return res; } // class Vector_d2D (Vector double 2-Dimensional) : end // class Vector_i2D (Vector int 2-Dimensional) : start class Vector_i2D{ public: int x; int y; public: // Constructor Vector_i2D(int x0=0, int y0=0){ x = x0; y = y0; }; ~Vector_i2D(){ x = 0; y = 0; }; // Operators Vector_i2D& Set(const int x0, const int y0){ x = x0; y = y0; return *this; }; bool operator==(const Vector_i2D v) { return ( x==v.x && y==v.y ); }; bool operator!=(const Vector_i2D v) { return ( x!=v.x || y!=v.y ); }; Vector_i2D& operator= (const Vector_i2D v) { x = v.x; y = v.y; return *this; }; Vector_i2D& operator+=(const Vector_i2D v) { x += v.x; y += v.y; return *this; }; Vector_i2D& operator-=(const Vector_i2D v) { x -= v.x; y -= v.y; return *this; }; Vector_i2D& operator*=(const int rH) { x *= rH; y *= rH; return *this; }; Vector_i2D& operator/=(const int rH) { x /= rH; y /= rH; return *this; }; Vector_i2D operator-()const{ Vector_i2D res; res.x=-x; res.y=-y; return res; }; Vector_i2D operator+(const Vector_i2D rH)const{ Vector_i2D res; res.x=x+rH.x; res.y=y+rH.y; return res; }; Vector_i2D operator-(const Vector_i2D rH)const{ Vector_i2D res; res.x=x-rH.x; res.y=y-rH.y; return res; }; // inner product int operator*(const Vector_i2D rH)const{ int res; res=x*rH.x + y*rH.y; return res; }; Vector_i2D operator*(const int rH)const{ Vector_i2D res; res.x=x*rH; res.y=y*rH; return res; }; friend Vector_i2D operator*(const int lH, const Vector_i2D rH) { Vector_i2D res; res.x=lH*rH.x; res.y=lH*rH.y; return res; }; Vector_i2D operator/(const int rH)const{ Vector_i2D res; res.x=x/rH; res.y=y/rH; return res; }; const Vector_i2D Crossz(const int z){ Vector_i2D res; res.x=y*z; res.y=-x*z; return res; }; const double norm(){ return sqrt(x*x + y*y); }; friend ostream& operator<<(ostream& os, const Vector_i2D& v){ os<<v.x<<"\t"<<v.y; return os; }; }; double norm(const Vector_i2D v){ return sqrt(v.x*v.x + v.y*v.y); } double norm(const int x, const int y){ return sqrt(x*x + y*y); } int Cross(const Vector_i2D v1, const Vector_i2D v2){ int res; res = v1.x*v2.y - v1.y*v2.x; return res; } Vector_i2D Cross(const int z, const Vector_i2D v){ Vector_i2D res; res.x = -z*v.y; res.y = z*v.x; return res; } Vector_i2D Cross(const Vector_i2D v, const int z){ Vector_i2D res; res.x = v.y*z; res.y = -v.x*z; return res; } // class Vector_i2D (Vector int 2-Dimensional) : end // class Image : start class Image{ public: int right; int bottom; unsigned char *img; int *domain; int N_domain; // number of domains public: // Constructors Image(); Image(unsigned char* im, int ri, int bo); // Destructor ~Image(); // Operators void Domain(); int FillDomain(int x, int y, unsigned char color); Vector_d2D CenterofMass(int x, int y); double Length_to_Edge(double x0, double y0, double dx, double dy); void RemoveNoise(int noise_size); }; Image::Image(){ right = 1; bottom = 1; img = new unsigned char[1]; img[0] = 0; domain = new int[1]; domain[0] = 0; } Image::Image(unsigned char *im, int ri, int bo){ int i, img_max=ri*bo; right = ri; bottom = bo; img = new unsigned char[img_max]; domain = new int[img_max]; for(i=0;i<img_max;i++){ img[i] = im[i]; domain[i] = i; } //this->Domain(); } Image::~Image(){ delete[] img; delete[] domain; } void Image::Domain(){ int i, j, w, a, s; // w // a s int p, img_max=right*bottom; int *ref; ref = new int[img_max]; for(i=0;i<img_max;i++){ ref[i] = i; } // 1st row: start domain[0] = p = 0; for(i=1;i<right;i++){ if( img[i]==img[i-1] ){ domain[i]=p; } else{ p++; domain[i]=p; } } // 1st row: end // 2nd~ row: start for(j=1;j<bottom;j++){ w = (j-1)*right; s = j*right; if( img[w]==img[s] ){ domain[s]=ref[domain[w]]; } else{ p++; domain[s]=p; } for(i=1;i<right;i++){ w = i + (j-1)*right; a = i-1 + j*right; s = i + j*right; if( img[a]==img[s] ){ if( img[w]==img[s] ){ if( ref[domain[a]]<ref[domain[w]] ){ // following minimum domain# domain[s] = ref[domain[w]] = ref[domain[a]]; } else{ domain[s] = ref[domain[a]] = ref[domain[w]]; } } else{ domain[s]=ref[domain[a]]; } } else if( img[w]==img[s] ){ domain[s]=ref[domain[w]]; } else{ p++; domain[s]=p; } } } // 2nd~ row: end bool *exist; int n; exist = new bool[p+1]; for(i=0;i<=p;i++){ exist[i] = false; } for(i=0;i<=p;i++){ ref[i]=ref[ref[i]]; exist[ref[i]]=true; } n = 0; for(i=0;i<=p;i++){ if( exist[i]==true ) n++; } N_domain = n; for(i=0;i<=p;i++){ n = 0; for(j=ref[i];j>=0;j--){ if(exist[j]==false) n++; } ref[i]-= n; } for(i=0;i<img_max;i++){ domain[i]=ref[domain[i]]; } delete[] ref; delete[] exist; }// void Image::Domain int Image::FillDomain(int x, int y, unsigned char color){ int i, img_max=right*bottom, a, p, n=0; if( x>=0 && x<right && y>=0 && y<bottom ){ a = x + y*right; if(img[a] != color){ p = domain[a]; for(i=0;i<img_max;i++){ if( domain[i]==p ){ img[i]=color; n++; } } } } return n; }// int Image::FillDomain Vector_d2D Image::CenterofMass(int x, int y){ int i, j, a, p, n=0; Vector_d2D res(0,0), k; if( x>=0 && x<right && y>=0 && y<bottom ){ a = x + y*right; p = domain[a]; for(j=0;j<bottom;j++){ for(i=0;i<right;i++){ a = i+j*right; if( domain[a]==p ){ res += k.Set(i,j); n++; } } } } res /= n; return res; }// Vector_d2D Image::CenterofMass double Image::Length_to_Edge(double x0, double y0, double dx, double dy){ // Length from (x0,y0) to the direction (dx,dy) int x, y, i, p, k, kmax=1000; double z; Vector_d2D r(x0,y0), dr(dx,dy); dr /= norm(dr); x = int(x0); y = int(y0); if( x>=0 && x<right && y>=0 && y<bottom ){ i = x + y*right; p = domain[i]; for(k=0;k<kmax;k++){ r += dr; x = int(r.x); y = int(r.y); if( x>=0 && x<right && y>=0 && y<bottom){ i = x + y*right; if( domain[i]!=p ){ for(r-=dr/2.,z=4.;z<11;z*=2.){ i = int(r.x) + int(r.y)*right; if( domain[i]!=p ){r-=dr/z;} else {r+=dr/z;} } break; } } else{ if( r.x<0 ){ r.y+=-r.x/dx*dy; r.x=0;} else if( r.x>right ){ r.y+=(right-r.x)/dx*dy; r.x=right;} if( r.y<0 ){ r.x+=-r.y/dy*dx; r.y=0;} else if( r.y>bottom ){ r.x+=(bottom-r.y)/dy*dx; r.y=bottom;} break; } } } return norm(r.x-x0,r.y-y0); }// double Image::Length_to_Edge void Image::RemoveNoise(int noise_size){ // only for Black and White images, otherwise it will malfunction. int *size_Domain; // size of domain (number of points on domain) int img_max=right*bottom, i, j, p; size_Domain = new int[N_domain]; for(i=0;i<N_domain;i++){ size_Domain[i] = 0; } for(i=0;i<img_max;i++){ size_Domain[domain[i]]++; } // (0,0)-point: start i = 0; j = 0; p = i + j*right; if(size_Domain[domain[p]]<=noise_size){ do{ if( i==0 ){ i=j+1; j=0; } else{ j++; i--; } p = i + j*right; }while( p<img_max && size_Domain[domain[p]]<=noise_size ); img[0] = img[p]; } // (0,0)-point: end // 1st row: start j = 0; for(i=1;i<right;i++){ p = i; if(size_Domain[domain[p]]<=noise_size){ img[p]=img[p-1]; } } // 1st row: end // 2nd~ row: start for(j=1;j<bottom;j++){ p = j*right; if(size_Domain[domain[p]]<=noise_size){ img[p]=img[p-right]; } for(i=1;i<right;i++){ p = i + j*right; if(size_Domain[domain[p]]<=noise_size){ img[p]=img[p-1]; } } } delete[] size_Domain; // 2nd~ row: end }// void Image::RemoveNoise // class Image : end int Fill_Domain(unsigned char* image, int right, int bottom, // image info int x, int y, unsigned char color) // FillDomain(x,y) by color { int area, i, img_max=right*bottom; Image img(image, right, bottom); img.Domain(); area = img.FillDomain(x,y,color); for(i=0;i<img_max;i++){ image[i] = img.img[i]; } return area; } void Center_of_Mass(unsigned char* image, int right, int bottom, // image info int x, int y, double* x_cm, double* y_cm) // Domain(x,y) with Center(x_cm, y_cm) { Vector_d2D r_cm; Image img(image, right, bottom); img.Domain(); r_cm = img.CenterofMass(x,y); *x_cm = r_cm.x + 0.5; *y_cm = r_cm.y + 0.5; } double Length_to_the_Edge(unsigned char* image, int right, int bottom, // image info double x0, double y0, double dx, double dy) // Length of Domain from (x0,y0) to the direction (dx,dy) { double l; Image img(image, right, bottom); img.Domain(); l = img.Length_to_Edge(x0, y0, dx, dy); return l; } void Noise_Remove(unsigned char* image, int right, int bottom, // image info int noise_size) { int i, img_max=right*bottom; Image img(image, right, bottom); img.Domain(); img.RemoveNoise(noise_size); for(i=0;i<img_max;i++){ image[i] = img.img[i]; } } ```/
ImgP3.png ImgP3-1.png
분석된 거리와 시간, 속도(거리/시간), 자기장값, 이미지 밝기 등을 보여주는 프로그램.
데이터를 분석하면서 잘못된 것(프로그램의 오류나 측정시의 실수 등)이 없는지 여러가지로 확인을 해봐야 하기 때문에, 측정할 때 기록된 여러가지 데이터들(시간, 자기장값, 이미지)을 한눈에 보기위해 만든 프로그램 .
ImgP4.png ImgP4-1.png
자성물질들의 특성 변화를 현미경으로 관측하고 이렇게 모인 사진, 동영상 데이터를 처리하여 속도를 재거나 특성을 알기 쉽게 이미지를 취합하고 처리하는 프로그램. 이미지 구간을 선택하여 자기장값이나 시간 등을 화면에 입혀 동영상으로도 만들어 줌 .
Money0.png Money1.png
재산을 매년 공개하는 국회의원 및 고위공직자들의 재산 분석 프로그램. 정형화 된 text에서 원하는 부분을 추출해 내는 간단한 프로그램. "고위공직자 및 국회의원 정기 재산 신고 (2011~2013)" pdf 파일에서 text만 긁어다가 txt 파일로 옮긴뒤 (Crtl+C,V 이용), text pattern을 분석해서 이름, 소속, 직위, 재산총액만 꺼내왔고, 그것을 그래프로 그림 .
TBD.png
Truncated Boson Dynamics Simulation : 너무 복잡하고 변수들도 너무 많아서 완벽하게 푸는 것이 어려운 Boson들 (입자의 특성에 따라 크게 Boson, Fermion으로 분류) 의 시간에 따른 상태 변화를 여러가지 단순화 과정 및 근사를 통해 모델링해서 분석함. 이 모델들을 이용해 수치적으로 계산해 결과들을 보여주는 프로그램. 단순히 몇개의 식들을 프로그램으로 구현한 것이지만, 프로그램화하면서 이것저것 고려해야할 것들 (adaptive step size 등) 이 많아서 까다로웠던 프로그램. 각 객체 (네모난 것들, 객체 지향형 프로그래밍) 들도 직접 프로그램한 것들.
ImgP5.png ImgP5-1.png
자기장에 따른 Magnetic Domain 의 변화를 관찰해야 하는 경우가 많아서, 시간 및 자기장에 따른 사진 이동을 편하게 해주도록 만든 프로그램.
## RRA

    Recoeve.net

  1. https://recoeve.net/, and kipid's blog :: Introducing what we are making : Recoeve.net
  2. github.com/kipid/Recoeve
  3. kipid's blog :: Recoeve Database setup (0.1 version)
  4. kipid's blog :: 개인화 된 추천 시스템 (Personalized recommendation system)
  5. kipid's blog :: 기계 학습 (Machine Learning - Deep Learning)
  6. kipid's blog :: SNS 내보내기/공유하기 (Sharing a URI link through SNS)
  7. kipid's blog :: Delayed (Lazy) Loading in HTML by JavaScript (+jQuery)
  8. kipid's blog :: 공정한 경제란 무엇일까? - 1. 두 명만으로 구성된 사회에서의 경제성장
  9. kipid's google docu :: 개인 소득 공개
  10. As a Programmer and a Physicist.

  11. kipid's blog :: Conjecture about the Unification between Electro-Magnetic Lorentz force and Gravity
  12. kipid's blog :: Black Holes as Elementary Particles, and Elementary Particles as Mini Black Holes
  13. kipid's blog :: Truncated many-body dynamics of interacting bosons: A variational principle with error monitoring
  14. kipid's blog :: 여러가지 프로그래밍 언어들
  15. kipid's blog :: HTML docuK format ver. 2.0; 개인적으로 만들고 있는 LaTeX 비슷한 형태의 HTML document format.
    // docuK 문서 예제들: kipid's blog :: 텐서(Tensor)와 상대론(Relativity) - 0. 텐서(Tensor)란?, and kipid's blog :: 선형 대수학 간단한 정리들 (Linear Algebra), and kipid's blog :: 최적화, 라그랑지 승수법 (Optimization with the Method of Lagrange multipliers), and kipid's blog :: Method of Lagrange multipliers.
  16. kipid's blog :: LaTeX(라텍스, 레이텍) 소개 및 설명서(Guide)들
  17. kipid's blog :: 반응형 웹 만들기 (Responsible web design with css media query)
  18. kipid's blog :: 인터넷, Web, HTML, 블로그에서 수식 사용하기 (Equation or math in HTML, blog)
  19. kipid's blog :: Interactive graph and chart in HTML
  20. kipid's blog :: 인터넷에서 예쁘게 코드 입력하기 (google code prettify)
  21. kipid's blog :: Improving web performance; Delayed loading 관련.
  22. kipid's blog :: 고위공직자 및 국회의원 정기 재산 신고 사항 (2011~2013) and kipid's blog :: 당신은 상위 몇 % 입니까? (고위직 재산 통계 2013)
  23. kipid's blog :: To correct inaccurate location measured by GPS with Wi-Fi RSSI (Received Signal Strength Indicatior). (Wi-Fi 신호세기를 이용해 GPS 튀는거 잡는 방법.)
  24. Lab Homepage

  25. SNU :: Theory of Cold Atoms.
  26. SNU :: Ultrafast Nanoscopic Spin Dynamics Laboratory (극초고속 나노스핀현상 연구실)
  27. Papers (about Physics only)

  28. Truncated many-body dynamics of interacting bosons: A variational principle with error monitoring, Kang-Soo Lee and Uwe R. Fischer, arXiv:1301.2199 [cond-mat.quant-gas] (2013).
  29. Long-Range Domain Wall Tension in Pt/Co/Pt Films with Perpendicular Magnetic Anisotropy, Kyoung-Woong Moon, Jae-Chul Lee, Soong-Geun Je, Kang-Soo Lee, Kyung-Ho Shin, and Sug-Bong Choe, Appl. Phys. Express 4, 043004 (2011).
  30. Fractal Dimension of Magnetic Domain Walls in CoFe/Pt Multilayers, Kang-Soo Lee, Dong-Hyun Kim, Sug-Bong Choe, J. Magnetics 15(3), 99-102 (2010).
  31. Roughness Exponent of Domain Interface in CoFe/Pt Multilayer Film, Kang-soo Lee, Chang-won Lee, Young-jin Cho, Sunae Seo, Dong-Hyun Kim, Sug-Bong Choe, IEEE Trans. Magn. 45(6), 2548 (2009).
  32. Interdimensional Universality of Dynamic Interfaces, Kab-Jin Kim, Jae-Chul Lee, Sung-Min Ahn, Kang-Soo Lee, Chang-Won Lee, Young Jin Cho, Sunae Seo, Kyung-Ho Shin, Sug-Bong Choe & Hyun-Woo Lee, Nature 458, 740-742 (2009).
  33. Etc.

반응형