-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent.json
More file actions
1 lines (1 loc) · 36.4 KB
/
content.json
File metadata and controls
1 lines (1 loc) · 36.4 KB
1
{"pages":[{"title":"","text":"Introduction “Baby, keep on developing like you ain’t got a choice.” Software Engineer at Moloco. Interested in engineering (Backend & DevOps) and business development, with a keen interest in exploring emerging technologies and actively participating in discussions with others. Curriculum Vitae Contacts Email: sangjun.son at moloco.com Work & Research Interests Site Reliability Engineering Blockchain Web Development Business Development Machine Learning Data Mining Tensor Analysis Sports Interests Wind Surfing Table Tennis Calisthenics","link":"/about/index.html"},{"title":"","text":"Working ExperiencesMoloco, Site Reliability Engineer July 2022 - Now NFT Bank, Engineer Intern Decemeber 2021 - Febuary 2022 Google, Software Engineering Internship June 2021 - September 2021 Google Korea LLC., Desktop Search Team Paik’s Beer, Part-time Waiter December 2019 - March 2020 Republic of Korea Army, Obligatory Military Service Febuary 2018 - October 2019 Research ExperiencesData Mining Lab, Seoul National University November 2019 - Febuary 2021 Undergraduate Research Internship Advisor: Prof. U Kang Real-Time Ubiquitous Systems Laboratory, Seoul National University July 2017 - Febuary 2018 Undergraduate Research Internship Advisor: Prof. Chang-Gun Lee Teaching ExperiencesTutoring - International Students Integrated Peer Tutoring Program Spring 2021 Semester at SNUGRH Problem Solving (Data Structures & Algorithm Basic Concepts) T.A. - Digital Computer Concept and Practice Fall 2020 Semester at Seoul National University T.A. - Basic Computing: First Adventures in Computing Fall 2020 Semester at Seoul National University Tutoring - Basic Calculus 1 Spring 2020 Semester at Seoul National University Social ExperiencesSociety Member in Decipher Blockchain Research Group in Seoul National University March 2020 - August 2020 Table Tennis Trainer in KASTTC December 2016 - December 2017","link":"/experiences/index.html"},{"title":"","text":"Seoul National UniversityB.S. in Computer Science and Engineering and Entrepreneurship March 2016 - August 2022 Daegu Science High School March 2013 - Febuary 2016","link":"/education/index.html"},{"title":"","text":"[J1] DAO-CP: Data-Adaptive Online CP decomposition for tensor streamSangjun Son, Yong-chan Park, Minyong Cho, and U Kang PLOS ONE 2022 Paper | Homepage | Bibtex [C1] Gtensor: Fast and Accurate Tensor Analysis System using GPUsDawon Ahn, Sangjun Son, and U Kang ACM International Conference on Information and Knowledge Management (CIKM) 2020(Demo Paper) Paper | Homepage | Bibtex","link":"/publications/index.html"}],"posts":[{"title":"2048-NN","text":"Use your arrow keys or swipes to move the tiles. When two tiles with the same number touch, they merge into one! You can play 2048 by yourself or with the help of NN. You can get some hints from deep learning model by clicking Think button. This trained model can achieve 2048+ in > 94%, 4096+ in > 78% and 8192+ in > 34% of the games. 2048 References Template Codes are from mateuszsokola/2048-in-react Convolutional Neural Network Model is from tjwei/2048-NN","link":"/2023/09/18/2048/"},{"title":"Asciify your video","text":"Code References Template Codes are from CodingTrain/Coding-Challenges","link":"/2021/04/30/asciify-video/"},{"title":"Music Chords with Mathematics","text":".valuefrac { text-align: center; font-weight: bold; font-size: 3em; height: auto; vertical-align:middle; width: 100%; line-height: 60px; margin: 40px auto; letter-spacing: -.07em; cursor:pointer; } .valuefrac:hover { color: #3273dc; } .fraction { display: inline-block; width: 2em; } .numerator { text-align: center; border-bottom: 2px solid; } .denominator { text-align: center; } .f { font-size: 10pt; display: inline-block; width: 2em; } .n { text-align: center; border-bottom: 1px solid; } .d { text-align: center; } span { height: auto; vertical-align: middle; } span#small{ margin-left: 2px; font-size: 8pt; } Finding Consonance How can we distinguish euphony and cacophony? The quality of sound is determined by frequency, one of the main characteristics regarding a singular tone. A chord containing several tones can be harmonious and discordant depending on its frequency set. Tuning and temperament produce the desired pitch regarding a given pitch and modify that tuning to lessen dissonance. There is a simple and easy way to determine whether two tones are compatible. Consonance happens when there is little interference engendered by pulsations of sound waves. And it occurs only when the ratio between the frequencies of the two tones, so-called distance, is numerically simple. A distance between two pitches can be mathematically described as the ratio between the frequency of the first pitch and the second frequency. 23 Let's delve into an example of two pitches, 260 Hz and 390 Hz above. We can calculate the distance as 2:3, the consonant interval named the fifth (from C to G). The same process can reduce various frequency ratios. You can drag and modify each frequency value and check out the simplest integer ratio of two pitches. Clicking the fraction lets you hear a custom-made chord of two pitches. Musical Temperament (12 tones / 1 octave) Temperament is especially crucial for keyboard instruments, which allow players to play only the pitches assigned to the various keys. Thereby, altering a single note's pitch can spoil the whole performance. Different musical temperament methods like just intonation and meantone temperament have been developed to play reasonably well in all of the keys. We'll identify how those methods create 12 tones in 1 octave (12-TET) and whether their melodies are plausible. From articles in Wikipedia, Pythagorean tuning is a system of musical tuning in which the frequency ratios of all intervals are based on the ratio 3:2. Just intonation or pure intonation is the tuning of musical intervals as whole number ratios (such as 3:2 or 4:3) of frequencies. Equal temperament divides the octave into 12 parts, all of which are equal on a logarithmic scale, with a ratio equal to the 12th root of 2. Don't hesitate to click on each entry of the table below and check out how it sounds. Listen to random music composed on each temperament. Our aural sense would find that the most familiar is the equal temperament, now commonly used in piano tuning. .tg {border-collapse:collapse;border-spacing:0;} .tg td{border-color:black;border-style:solid;border-width:1px;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;} .tg th{border-color:black;border-style:solid;border-width:1px;font-size:13px; font-weight:bold;overflow:hidden;padding:10px 5px;word-break:normal;} .tg .tg-c3ow{ border-color:inherit;vertical-align:middle; } td.tg-c3ow { font-size: 10pt; cursor:pointer; } td.tg-c3ow:hover { background-color:#f7f7f7; } td.tg-c3ow.playing { background-color:#efefef; color:#3273dc; font-weight:bold; } 260 Hz P1 m2 M2 m3 M3 P4 TT P5 m6 M6 m7 M7 P8 Pythagorean Tuning 3020 2835 3223 2533 3426 2231 3629 3121 2734 3324 2432 3527 2130 Just Intonation 11 1211 98 65 54 43 75 32 85 53 74 116 21 Equal Temperament 20⁄12 21⁄12 22⁄12 23⁄12 24⁄12 25⁄12 26⁄12 27⁄12 28⁄12 29⁄12 210⁄12 211⁄12 212⁄12","link":"/2023/02/13/chord/"},{"title":"CKA & CKAD: Certified Kubernetes Administrator & Application Developer","text":"","link":"/2024/02/10/cka-ckad/"},{"title":"Dame Dane","text":"From an article in Kapwing Resources, Deepfakes are finding their way into meme culture more than ever before and one clip is leading the charge. The “Dame Dane” meme features a Japanese song from the popular video game series Yakuza. I will apply First Order Modeling method, which allows creating deep fakes in a few minutes. First Order Motion Model for Image Animation in NeurIPS 2019For further information, please refer to the video below and visit the website of the paper. .video-container { position: relative; padding-bottom: 56.25%; /* 16:9 */ height: 0; } .video-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }","link":"/2023/01/01/dame-dane/"},{"title":"DAO-CP - Data-Adaptive Online CP decomposition for tensor stream","text":"PONE-D-21-39294R1I’m pleased to inform you that your manuscript has been deemed suitable for publication in PLOS ONE. Congratulations! Your manuscript is now with our production department. How can we accurately and efficiently decompose a tensor stream? The problem of efficiently decomposing tensor streams has been of great interest because many real-world data dynamically change over time. Therefore, we propose DAO-CP, an accurate and efficient online CP decomposition method which adapts to data changes.","link":"/2021/06/13/dao-cp/"},{"title":"The Water Jug Riddle","text":".video-container { position: relative; padding-bottom: 56.25%; /* 16:9 */ height: 0; } .video-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } p.num-in { font-size: 20px; text-align: right; } .num-block { float: left; width: 49%; padding: 0px; } .skin-1 .num-in { display: inline-block; text-align: center; width: 49%; } .skin-1 .num-in span { display: inline-block; vertical-align: middle; width: 20px; height: 32px; line-height: 32px; text-align: center; position: relative; cursor: pointer; } .skin-1 .num-in span.dis:before { background-color: #ccc !important; } .skin-1 .num-in input { display: inline-block; width: 32px; height: 32px; border: 1px solid #6E6F7A; border-radius: 5px; color: #000; text-align: center; padding: 0; } .skin-1 .num-in span.minus:before { content: ''; position: absolute; width: 15px; height: 2px; background-color: #00A94F; top: 50%; left: 0; } .skin-1 .num-in span.plus:before, .skin-1 .num-in span.plus:after { content: ''; position: absolute; right: 0px; width: 15px; height: 2px; background-color: #00A94F; top: 50%; } .skin-1 .num-in span.plus:after { -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); } .diehard-container { width: 49%; align-items: center; justify-content: center; text-align: center; max-width: 1010px; margin: auto; position: relative; z-index: 10; display:inline-block; } h2.diehard-gal { text-align: center; position: absolute; bottom: 0px; color: #bbeddd; font-weight: bold; z-index: 20; font-size: 30px; writing-mode: horizontal-tb; } .diehard-shadow { position: relative; width: 70px; height: 10px; background: #e0f6ef; margin: 5px auto; margin-bottom: 0; padding: 0; top: 0%; left: 0%; border-radius: 30px; } .diehard-bottle { margin: 0 30px 0 30px; } .diehard-box { display: inline-block; position: relative; width: 60px; margin: 10px; margin-top: 0; padding: 0; border-left: 2px solid #80ab9d; border-right: 2px solid #80ab9d; border-bottom: 2px solid #80ab9d; border-radius: 0 0 60px 60px; overflow: hidden; color: rgba(255, 255, 255, 0.5); font-size: 14px; text-align: right; writing-mode: vertical-rl; } .diehard-box::after { content: \"\"; position: absolute; bottom: 5%; left: 55%; background: #e0f6ef; width: 300px; height: 320px; border-radius: 40%; box-sizing: border-box; transform: translateX(-50%) rotate(0); animation: wave 4s linear infinite; } .diehard-box::before { content: \"\"; position: absolute; bottom: 5%; left: 55%; background: rgba(255, 255, 255, 0.5); width: 370px; height: 350px; border-radius: 40%; box-sizing: border-box; transform: translateX(-50%) rotate(0); animation: wave 5s linear infinite -5s; } .diehard-box.ee::after { bottom: var(--bottomA); } .diehard-box.ee::before { bottom: var(--bottomA); } .diehard-box.ff::after { bottom: var(--bottomB); } .diehard-box.ff::before { bottom: var(--bottomB); } .diehard-bobble { position: absolute; background: rgba(255, 255, 255, 0.5); bottom: 120px; left: -10%; width: 20px; height: 5px; border-radius: 10px; } .diehard-bobble::before { content: \"\"; position: absolute; background: rgba(255, 255, 255, 0.5); left: 0; top: 800%; width: 20px; height: 5px; border-radius: 10px; } .diehard-bobble::after { content: \"\"; position: absolute; background: rgba(255, 255, 255, 0.5); left: 0; top: -800%; width: 20px; height: 5px; border-radius: 10px; } .diehard-box.ee { background: linear-gradient(107deg, #27a342, #b2edbf); background-size: 600% 600%; animation: GradientBackground 5s ease infinite; } .diehard-box.ff { background: linear-gradient(107deg, #b0288e, #f0c7e6); background-size: 600% 600%; animation: GradientBackground 5s ease infinite; } @keyframes wave { 50% { transform: reanslatex(-50%) rotate(0deg); } 100% { transform: translatex(-50%) rotate(360deg); } } @keyframes GradientBackground { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } Detective John McClane must measure out exactly 4 gallons of water and place the resulting weight on a scale to disable a bomb. His tools are yours: a 3-gallon and a 5-gallon jug—and a single fountain. McClane did it in less than 5 minutes. Can you also do it in time and provide a generalized solution for arbitrary gallons of both jugs? function changeJug(jugNum, delta) { let jug = document.getElementById(\"jug\"+jugNum); let newVal = parseInt(jug.value) + delta; if (newVal < 1 || newVal > 15) return; jug.value = newVal; if (jugNum == 1) init(newVal, -1); else init(-1, newVal); } Jug 1 Jug 2 gal   5 gal   3 Every step can be visualized as billiard moves in the coordinate system on a triangular lattice. The above hexagonal plot gives two solutions to the 5-gallon and 3-gallon puzzle. Each point on the boundary denotes combinations achievable with the jugs. Starting at two vertices (5, 0) and (0, 3), traces of the blue points show pourable transitions. We have measured 4 gallons in 6 and 7 steps concerning the starting points. Might it be possible to get a prime gallon of water from coprime gallon jugs (e.g., to yield 7 gallons from a 9-gallon jug and 15-gallon jug)?","link":"/2022/11/07/die-hard/"},{"title":"Embed YouTube in HTML","text":".mySlides {display: none} /* Slideshow container */ .slideshow-container { max-width: 1000px; position: relative; margin: auto; } /* Next & previous buttons */ .prev, .next { cursor: pointer; position: absolute; top: 50%; width: auto; padding: 16px; margin-top: -22px; color: white; font-weight: bold; font-size: 18px; transition: 0.6s ease; border-radius: 0 3px 3px 0; user-select: none; } /* Position the \"next button\" to the right */ .next { right: 0; border-radius: 3px 0 0 3px; } /* On hover, add a black background color with a little bit see-through */ .prev:hover, .next:hover { background-color: rgba(0,0,0,0.8); } /* The dots/bullets/indicators */ .dot { cursor: pointer; height: 10px; width: 10px; margin: 15px 5px; background-color: #bbb; border-radius: 50%; display: inline-block; transition: background-color 0.6s ease; } .active, .dot:hover { background-color: #717171; } /* Fading animation */ .fade { -webkit-animation-name: fade; -webkit-animation-duration: 1.5s; animation-name: fade; animation-duration: 1.5s; } @-webkit-keyframes fade { from {opacity: .4} to {opacity: 1} } @keyframes fade { from {opacity: .4} to {opacity: 1} } /* On smaller screens, decrease text size */ @media only screen and (max-width: 300px) { .prev, .next,.text {font-size: 11px} } .video-container { position: relative; padding-bottom: 56.25%; /* 16:9 */ height: 0; } .video-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } This is an example article showing how to embed YouTube videos. Due to COVID-19,I’ve started a YouTube channel and decided to upload practice videos while taking PE courses. Korean Traditional Martial Arts Long Staff Spinning Skills ❮ ❯ var slideIndex = 1; showSlides(slideIndex); function plusSlides(n) { showSlides(slideIndex += n); } function currentSlide(n) { showSlides(slideIndex = n); } function showSlides(n) { var i; var slides = document.getElementsByClassName(\"mySlides\"); var dots = document.getElementsByClassName(\"dot\"); if (n > slides.length) {slideIndex = 1} if (n < 1) {slideIndex = slides.length} for (i = 0; i < slides.length; i++) { slides[i].style.display = \"none\"; } for (i = 0; i < dots.length; i++) { dots[i].className = dots[i].className.replace(\" active\", \"\"); } slides[slideIndex-1].style.display = \"block\"; dots[slideIndex-1].className += \" active\"; }","link":"/2020/12/23/embed-youtube/"},{"title":"Friends😍","text":"These are my friends’ websites, which motivated me to create my own GitHub page.Go visit and find some interesting stuffs! mayshin10 darwinj07 bbb1293 vroomfan goldenhazard lego0901 janghyeok lgm0905 dawonahn vetobeen ligi214 ohahyoung suniipang elzino","link":"/2025/10/16/friends/"},{"title":"Introducing glnk.dev — Go-link for Developers","text":"Each shortcut points to any URL you want — docs, dashboards, repos, tools, blog posts, anything. It works entirely through GitHub and static hosting, which means: no server to maintain no database version-controlled links easy to sync across devices You can manage all your links in one place, and glnk handles the redirects automatically. 🌱 Getting startedSigning up is intentionally simple.Just connect with your GitHub account, choose your namespace, and you’re set. From there, you can start creating paths like: username.glnk.dev/docs username.glnk.dev/blog or topic-based hubs like: gcp.glnk.dev aws.glnk.dev It’s flexible and grows with your workflow. ✨ Final thoughtsThis project is still evolving, but it already fits nicely into my daily habits.If you’re someone who likes tidy tooling, lightweight systems, and having your own personalized link space, you might find glnk useful too. Give it a try and let me know what you think 😊","link":"/2025/12/10/glnk-dev/"},{"title":"Platform Engineering CTF with Akamai - KubeCon NA 2025","text":"","link":"/2025/11/13/kubeconna-akamai/"},{"title":"Cloud Runner 2049 - KubeCon NA 2025","text":"Welcome to Synth City! In the neon-drenched metropolis of Synth City, corporations battle for control of the cloud, the lifeblood of their digital empire. You are a Cloud Runner, a skilled developer navigating the intricate networks of Google Cloud. A mysterious meffntr sebz n ebthr NV anzrq “Flaguvn” unf fhesnprq, jneavat bs n ybbzvat plorenggnpx gung guerngraf gb qrfgnovyvmr gur ragver pvgl. Flaguvn arrqf lbhe uryc gb ohvyq n frpher naq fpnynoyr qrsrafr flfgrz hfvat Tbbtyr Pybhq. Ner lbh ernql gb orpbzr n Pybhq Ehaare?","link":"/2025/11/13/kubeconna-cloud-runner-2049/"},{"title":"LinkedIn Profile","text":"","link":"/2021/05/01/linkedin/"},{"title":"Desktop Screen Capturing Module for MopReM","text":"This is a part of image pre-processing module for MopReM: Moiré Pattern Removal for Mobile, Texts/Diagrams on Single-colored Background. Click the link to visit the project page of SNU-CV-PIP team. We first select the window to screen-capture and crop the shared screen with range selector. The module saves the screenshot surrounded with target frame as target.png. Re-capture the target photo and save as source.png. Only executable on desktop! Screen Share Image Crop #screenshot_mask { width: 100%; height: 100%; position: fixed; top: 0px; left: 0px; display: block; opacity: 0.3; text-align: center; box-sizing: border-box; z-index: 2147483647; border-color: black; border-style: solid; } #screenshot_focus:before, #screenshot_focus:after { border: none !important; content: \"\" !important; height: 100% !important; position: absolute !important; width: 100% !important } #screenshot_focus:before { border-right: 1px solid white !important; border-bottom: 1px solid white !important; left: -100% !important; top: -100% !important } #screenshot_focus:after { border-top: 1px solid white !important; border-left: 1px solid white !important; left: 0 !important; top: 0 !important } #screenshot_focus { height: 100% !important; position: fixed !important; width: 100% !important; z-index: 2147483648 !important } function capture(scaleFactor) { var video = document.getElementById('moprem_video'); if (scaleFactor == null) { scaleFactor = 1; } var w = video.videoWidth * scaleFactor; var h = video.videoHeight * scaleFactor; var canvas = document.createElement('canvas'); canvas.width = w; canvas.height = h; var ctx = canvas.getContext('2d'); ctx.drawImage(video, 0, 0, w, h); return canvas; } $(\"#moprem_capture\").on('click', function (e) { var height = window.innerHeight; var width = $(document).width(); var $mask = $('').css(\"border-width\", \"0 0 \" + height + \"px 0\"); var $focus = $(''); $(\"body\").append($mask); $(\"body\").append($focus); var selectArea = false; $(\"body\").one(\"mousedown\", function (e) { e.preventDefault(); selectArea = true; startX = e.clientX; startY = e.clientY; }).one('mouseup', function (e) { selectArea = false; $(\"body\").off('mousemove', mousemove); $(\"#screenshot_focus\").remove(); $(\"#screenshot_mask\").remove(); var x = e.clientX; var y = e.clientY; var top = Math.min(y, startY); var left = Math.min(x, startX); var width = Math.max(x, startX) - left; var height = Math.max(y, startY) - top; var canvas = capture(); var W = canvas.width; var H = canvas.height; var video = document.getElementById('moprem_video'); var rect = video.getBoundingClientRect(); y_off = rect.top; x_off = rect.left; y_size = rect.height; x_size = rect.width; width = width*W/x_size; height = height*H/y_size; try { var img = canvas.getContext('2d').getImageData((left-x_off)*W/x_size, (top-y_off)*H/y_size, width, height); let pad = 30; let w = img.width + pad*6; let h = img.height + pad*6; let arr = new Uint8ClampedArray(w*h*4); for (let i = 0; i < w; i++) { for (let j = 0; j < h; j++) { for (let k = 0; k < 4; k++) { arr[(j*w+i)*4+k] = 255; } } } for (let i = 0; i < img.width; i++) { for (let j = 0; j < img.height; j++) { let pad_idx = (j+pad*3)*w + (i+pad*3); let idx = j*img.width + i; for (let k = 0; k < 4; k++) { arr[pad_idx*4+k] = img.data[idx*4+k]; } } } for (let i = 0; i < img.width; i++) { for (let j = 0; j < pad; j++) { let pad_idx = (pad*3-j)*w + (i+pad*3); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; pad_idx = (pad*3+j+img.height)*w + (i+pad*3); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; if (i > img.width/4 && i < img.width*3/4) { pad_idx = (pad*2-j)*w + (i+pad*3); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; pad_idx = (pad*4+j+img.height)*w + (i+pad*3); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; } } } for (let i = 0; i < img.height; i++) { for (let j = 0; j < pad; j++) { let pad_idx = (pad*3+i)*w + (pad*3-j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; pad_idx = (pad*3+i)*w + (pad*3+img.width+j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; if (i > img.height/4 && i < img.height*3/4) { pad_idx = (pad*3+i)*w + (pad*2-j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; pad_idx = (pad*3+i)*w + (pad*4+img.width+j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; } } } for (let i = 0; i < pad; i++) { for (let j = 0; j < pad; j++) { let pad_idx = (pad*3-i)*w + (pad*3-j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; pad_idx = (pad*3-i)*w + (pad*3+img.width+j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; pad_idx = (pad*3+img.height+i)*w + (pad*3-j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; pad_idx = (pad*3+img.height+i)*w + (pad*3+img.width+j); arr[pad_idx*4] = arr[pad_idx*4+1] = arr[pad_idx*4+2] = 0; arr[pad_idx*4+3] = 255; } } img_pad = new ImageData(arr, w); console.log(img_pad); /* pad = 50 WHITE = (255,255,255) BLACK = (0,0,0) imPad = cv2.copyMakeBorder(imOrg, pad, pad, pad, pad, cv2.BORDER_CONSTANT, value=BLACK) imPad = cv2.copyMakeBorder(imPad, pad, pad, pad, pad, cv2.BORDER_CONSTANT, value=WHITE) height, width, _ = imPad.shape imPad[:pad, width//3:width*2//3] = BLACK imPad[-pad:, width//3:width*2//3] = BLACK imPad[height//3:height*2//3, :pad] = BLACK imPad[height//3:height*2//3, -pad:] = BLACK imPad = cv2.copyMakeBorder(imPad, pad*2, pad*2, pad*2, pad*2, cv2.BORDER_CONSTANT, value=WHITE) */ console.log(img); var c = document.createElement(\"canvas\"); c.width = img_pad.width; c.height = img_pad.height; c.getContext('2d').putImageData(img_pad, 0, 0); c.style.margin = \"auto\"; var output = document.getElementById('moprem_output'); output.innerHTML = ''; output.appendChild(c); save(c); } catch (e) { alert(\"No Area to Capture\"); } }).on(\"mousemove\", mousemove); function mousemove(e) { var x = e.clientX; var y = e.clientY; $focus.css(\"left\", x); $focus.css(\"top\", y); if (selectArea) { var top = Math.min(y, startY); var right = width - Math.max(x, startX); var bottom = height - Math.max(y, startY); var left = Math.min(x, startX); $mask.css(\"border-width\", [top + 'px', right + 'px', bottom + 'px', left + 'px'].join(' ')); } } function save(canvas) { if (navigator.msSaveBlob) { var blob = canvas.msToBlob(); return navigator.msSaveBlob(blob, 'target.png'); } else { var el = document.getElementById(\"moprem_target\"); el.href = canvas.toDataURL(\"image/png\"); el.download = 'target.png'; el.click(); } } });","link":"/2021/11/27/moprem/"},{"title":"Music player de lucetre","text":"Visit the page for the full-screen version; https://musicetre.vercel.app/.","link":"/2021/03/02/music-player/"},{"title":"Nim Game against Computer","text":"#canvas { width: 100%; height: auto; } #nim-controller { margin-left: 10px; } svg { float: center; } rect.match { stroke: #888267; rx: 10; ry: 10; } .heap rect.selection { fill: #888267; } .error { color: #e41a1c; } .success { color: #4daf4a; } From an article in Wikipedia, In another game which is commonly known as Nim (but is better called the subtraction game), an upper bound is imposed on the number of objects that can be removed in a turn. Instead of removing arbitrarily many objects, a player can only remove 1 or 2 or … or k at a time. The player taking the last object wins. How to PlayIn this game, we’ll slightly change the rule to get a certain number of stones. Now you can only grab as many stones as the number written inside colored circles. Drag and highlight the stones that you would like to remove. Click the Take button. Win the game against the computer.","link":"/2023/01/10/nim-game/"},{"title":"Paper Review: Multi-Aspect Streaming Tensor Completion","text":"This article is all about a recently-viewed paper, Multi-Aspect Streaming Tensor Completion in proceedings of the 23rd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (KDD ‘17). #tensor_completion, #MAST, #dynamic_tensor_decomposition,#online_algorithm, #streaming_data, #CP_factorization Abstract Completion of incremental tensors without sacrificing effectiveness remains a challenging task due to the uncertainty of tensor mode changes and complex data structure of multi-aspect streaming tensors. To bridge this gap, we propose a Multi-Aspect Streaming Tensor completion framework based on CANDECOMP/PARAFAC decomposition to track the subspace of general incremental tensors for completion. Relevance to My Research MAST is the 1st approach to online analysis that solved the multi-aspect streaming problem. I’m also working on streaming tensor and trying to develop my method. You can see the progress of my research on GitHub. More other topics on https://datalab.snu.ac.kr/seminar.","link":"/2021/12/26/paper-mast/"},{"title":"Piano API","text":"","link":"/2021/04/24/piano/"},{"title":"Scholar Resume","text":"Axie Infinity is a blockchain-based P2E game. Players purchase NFTs of cute monsters called Axies and then pit them against each other in battles. They can earn SLP tokens during gameplay and trade them for money at an exchange. The Axie scholarship program lets scholars willing to play the game possess one or more decks to play Axie infinity. Scholarship managers buy or provide decks of 3 axies, enabling the scholar to play battles. The scholar’s SLP revenue follows a 50/50 or 60/40 payout ratio depending on the scholars’ performance. We have launched a single page application “Scholar Resume“ for axie scholars to apply for a specific scholarship, providing achievement information, including their ranks, MMR, and earned SLP history via their playing accounts.","link":"/2022/12/27/scholar-resume/"},{"title":"Skulpt to use Python in Markdown","text":"// output functions are configurable. This one just appends some text // to a pre element. function outf(text) { var mypre = document.getElementById(\"output\"); mypre.innerHTML = mypre.innerHTML + text; } function builtinRead(x) { if (Sk.builtinFiles === undefined || Sk.builtinFiles[\"files\"][x] === undefined) throw \"File not found: '\" + x + \"'\"; return Sk.builtinFiles[\"files\"][x]; } // Here's everything you need to run a python program in skulpt // grab the code from your textarea // get a reference to your pre element for output // configure the output function // call Sk.importMainWithBody() function runit(prog) { var mypre = document.getElementById(\"output\"); mypre.innerHTML = ''; Sk.pre = \"output\"; Sk.configure({output:outf, read:builtinRead}); (Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'mycanvas'; var myPromise = Sk.misceval.asyncToPromise(function() { return Sk.importMainWithBody(\"\", false, prog, true); }); myPromise.then(function(mod) { console.log('success'); }, function(err) { console.log(err.toString()); }); } This is an example article showing how to embed Skulpt and Ace code editor to use Python. Skulpt is an entirely in-browser implementation of Python. Tutorial w. simple Python turtle code used while doing TA works. Try This #editor { display: block; width: 100%; height: 300px; } import turtle as t print(\"Drawing Ryan...\") t.shape(\"turtle\") t.speed(7) t.fillcolor(\"#f7aa1b\") t.pencolor(\"#111111\") t.pensize(10) print(\"Left Ear...\") t.penup() t.goto(-120, 120) t.pendown() t.begin_fill() t.circle(50) t.end_fill() t.penup() t.goto(120, 120) print(\"Right Ear...\") t.pendown() t.begin_fill() t.circle(50) t.end_fill() t.penup() t.goto(0, -200) print(\"Face...\") t.pendown() t.begin_fill() t.circle(200) t.end_fill() t.penup() t.pensize(15) t.goto(-120, 60) print(\"Left Eyebrow...\") t.pendown() t.goto(-50, 60) t.penup() t.goto(120, 60) t.pendown() print(\"Right Eyebrow...\") t.goto(50, 60) t.penup() t.goto(-80, 15) print(\"Left Eye...\") t.pendown() t.fillcolor(\"#111111\") t.begin_fill() t.circle(6) t.end_fill() t.penup() t.goto(80, 15) print(\"Right Eye...\") t.pendown() t.fillcolor(\"#111111\") t.begin_fill() t.circle(6) t.end_fill() t.penup() t.goto(-7, -25) print(\"Mouth...\") t.pendown() t.fillcolor(\"#ffffff\") t.begin_fill() t.left(135) t.circle(32, 290) t.right(130) t.circle(32, 290) t.end_fill() t.penup() t.home() t.goto(0, -30) print(\"Nose...\") t.pendown() t.begin_fill() t.circle(8) t.end_fill() print(\"Done!\") t.hideturtle() var editor = ace.edit(\"editor\"); editor.setTheme(\"ace/theme/xcode\"); editor.session.setMode(\"ace/mode/python\"); editor.commands.addCommand({ name: 'myCommand', bindKey: {win: 'Ctrl-Enter', mac: 'Command-Enter'}, exec: function(editor) { runit(editor.getValue()); }, readOnly: true // false if this command should not apply in readOnly mode }); editor.on('change', (arg, activeEditor) => { const aceEditor = activeEditor; const newHeight = aceEditor.getSession().getScreenLength() * (aceEditor.renderer.lineHeight + aceEditor.renderer.scrollBar.getWidth()); aceEditor.container.style.height = `${newHeight}px`; aceEditor.resize(); }); Run (Ctrl+Enter)","link":"/2020/12/23/skulpt/"},{"title":"ThereMINI","text":"Presentation Link","link":"/2022/06/11/theremini/"}],"tags":[{"name":"2048","slug":"2048","link":"/tags/2048/"},{"name":"game","slug":"game","link":"/tags/game/"},{"name":"nn","slug":"nn","link":"/tags/nn/"},{"name":"deep_learning","slug":"deep-learning","link":"/tags/deep-learning/"},{"name":"human_w_computer","slug":"human-w-computer","link":"/tags/human-w-computer/"},{"name":"opengraph-xyz","slug":"opengraph-xyz","link":"/tags/opengraph-xyz/"},{"name":"ascii","slug":"ascii","link":"/tags/ascii/"},{"name":"video_rendering","slug":"video-rendering","link":"/tags/video-rendering/"},{"name":"music","slug":"music","link":"/tags/music/"},{"name":"temperament","slug":"temperament","link":"/tags/temperament/"},{"name":"ratio","slug":"ratio","link":"/tags/ratio/"},{"name":"math","slug":"math","link":"/tags/math/"},{"name":"chord","slug":"chord","link":"/tags/chord/"},{"name":"harmony","slug":"harmony","link":"/tags/harmony/"},{"name":"cka","slug":"cka","link":"/tags/cka/"},{"name":"ckad","slug":"ckad","link":"/tags/ckad/"},{"name":"kubernetes","slug":"kubernetes","link":"/tags/kubernetes/"},{"name":"linux","slug":"linux","link":"/tags/linux/"},{"name":"cncf","slug":"cncf","link":"/tags/cncf/"},{"name":"video","slug":"video","link":"/tags/video/"},{"name":"damedane","slug":"damedane","link":"/tags/damedane/"},{"name":"meme","slug":"meme","link":"/tags/meme/"},{"name":"deepfake","slug":"deepfake","link":"/tags/deepfake/"},{"name":"plosone","slug":"plosone","link":"/tags/plosone/"},{"name":"journal","slug":"journal","link":"/tags/journal/"},{"name":"tensor","slug":"tensor","link":"/tags/tensor/"},{"name":"decomposition","slug":"decomposition","link":"/tags/decomposition/"},{"name":"data","slug":"data","link":"/tags/data/"},{"name":"stream","slug":"stream","link":"/tags/stream/"},{"name":"graduation","slug":"graduation","link":"/tags/graduation/"},{"name":"strategy","slug":"strategy","link":"/tags/strategy/"},{"name":"die_hard","slug":"die-hard","link":"/tags/die-hard/"},{"name":"water_jug","slug":"water-jug","link":"/tags/water-jug/"},{"name":"number","slug":"number","link":"/tags/number/"},{"name":"youtube","slug":"youtube","link":"/tags/youtube/"},{"name":"korean_martial_arts","slug":"korean-martial-arts","link":"/tags/korean-martial-arts/"},{"name":"2020S","slug":"2020S","link":"/tags/2020S/"},{"name":"friend","slug":"friend","link":"/tags/friend/"},{"name":"profile","slug":"profile","link":"/tags/profile/"},{"name":"go-link","slug":"go-link","link":"/tags/go-link/"},{"name":"devops","slug":"devops","link":"/tags/devops/"},{"name":"kubecon","slug":"kubecon","link":"/tags/kubecon/"},{"name":"akamai","slug":"akamai","link":"/tags/akamai/"},{"name":"gcp","slug":"gcp","link":"/tags/gcp/"},{"name":"myself","slug":"myself","link":"/tags/myself/"},{"name":"computer_vision","slug":"computer-vision","link":"/tags/computer-vision/"},{"name":"image_processing","slug":"image-processing","link":"/tags/image-processing/"},{"name":"moire","slug":"moire","link":"/tags/moire/"},{"name":"demoire","slug":"demoire","link":"/tags/demoire/"},{"name":"vercel","slug":"vercel","link":"/tags/vercel/"},{"name":"firestore","slug":"firestore","link":"/tags/firestore/"},{"name":"nextjs","slug":"nextjs","link":"/tags/nextjs/"},{"name":"jsmediatags","slug":"jsmediatags","link":"/tags/jsmediatags/"},{"name":"iconv_lite","slug":"iconv-lite","link":"/tags/iconv-lite/"},{"name":"nim","slug":"nim","link":"/tags/nim/"},{"name":"minmax","slug":"minmax","link":"/tags/minmax/"},{"name":"baskin_robbins_31","slug":"baskin-robbins-31","link":"/tags/baskin-robbins-31/"},{"name":"human_vs_computer","slug":"human-vs-computer","link":"/tags/human-vs-computer/"},{"name":"research","slug":"research","link":"/tags/research/"},{"name":"2022S","slug":"2022S","link":"/tags/2022S/"},{"name":"socket.io","slug":"socket-io","link":"/tags/socket-io/"},{"name":"nestjs","slug":"nestjs","link":"/tags/nestjs/"},{"name":"herokuapp","slug":"herokuapp","link":"/tags/herokuapp/"},{"name":"railway","slug":"railway","link":"/tags/railway/"},{"name":"axie","slug":"axie","link":"/tags/axie/"},{"name":"scholar","slug":"scholar","link":"/tags/scholar/"},{"name":"resume","slug":"resume","link":"/tags/resume/"},{"name":"nftbank","slug":"nftbank","link":"/tags/nftbank/"},{"name":"python","slug":"python","link":"/tags/python/"},{"name":"turtle","slug":"turtle","link":"/tags/turtle/"},{"name":"TA","slug":"TA","link":"/tags/TA/"},{"name":"2020F","slug":"2020F","link":"/tags/2020F/"},{"name":"esp32","slug":"esp32","link":"/tags/esp32/"},{"name":"arduino","slug":"arduino","link":"/tags/arduino/"},{"name":"potentiometer","slug":"potentiometer","link":"/tags/potentiometer/"},{"name":"ir_receiver","slug":"ir-receiver","link":"/tags/ir-receiver/"},{"name":"theremin","slug":"theremin","link":"/tags/theremin/"},{"name":"ultrasonic","slug":"ultrasonic","link":"/tags/ultrasonic/"},{"name":"firebase_rtdb","slug":"firebase-rtdb","link":"/tags/firebase-rtdb/"},{"name":"demo","slug":"demo","link":"/tags/demo/"}],"categories":[{"name":"Hobby","slug":"Hobby","link":"/categories/Hobby/"},{"name":"Study","slug":"Study","link":"/categories/Study/"},{"name":"Research","slug":"Research","link":"/categories/Research/"},{"name":"Social","slug":"Social","link":"/categories/Social/"},{"name":"Work","slug":"Work","link":"/categories/Work/"}]}