[{"content":"My inactivity on my website and my laziness towards actually making it look better is justified by the fact that it\u0026rsquo;s exam season, and I do the IB diploma program. It is very rigorous, they torture you with the exam, the exam board itself is\u0026hellip;very questionable, and I have to do 6 very heavy weight subjects, all with coursework.\nMath I picked the hardest math that the IBDP (or just the IB) has to offer, Higher Level Math: Analysis and Approaches, or just HL Math AA, or HLAA. Analysis and Approaches means that it has more pure math content and less of the weird statistical graph theory geometry stuff that Applications and Interpretations has to offer. It\u0026rsquo;s also because universities love HLAA students, especially for Computer Science.\nIn the final exams, you are given 3 papers, paper 1 being non-calculator, paper 2 being calculator, and paper 3 being the super abstract wack paper where they throw you some random concept in the field of mathematics, a short text describing how it works, and then expect you to answer a bunch of questions on it.\nToday was the day of my math exam. It\u0026rsquo;s just a semester exam, the first one in fact. It tests you on 6 months\u0026rsquo; worth of content, and it goes to your IB DP predicted grade (at least here in my school), which is sent to universities as a part of the application process. We are only given a 1 hour long paper 1 and a 1 hour long paper 2 in the same exam room, where you put your calculator on the floor face-down for the first part.\nI prepared a hell of a lot for it, 12 past papers (6 paper 1\u0026rsquo;s and 6 paper 2\u0026rsquo;s), and two fat calculus worksheets (300something marks in total), and some textbook questions. I felt pretty confident until I left home. I remembered that the exam started at 12:45pm, so I left home at around 12:00 pm, so that I could have some time to breathe at school.\nThe lift of realization I went in the lift, going to put my exam timetable in the favorites folder of my phone\u0026rsquo;s photo gallery. I look at the time stated where the exam would begin, just because I wanted to make sure that it did start at 12:45\u0026hellip;\nwhoops, it actually starts at 11:45am.\nDon\u0026rsquo;t ask me how I didn\u0026rsquo;t check. It was 12:03 in the lift, and my mind started racing before my heart could catch up. Oh shit, oh shit, I would be late.\nAs I cycled to school, my mind raced with all that could happen in the exam. Would I get the full 1 hour for paper 1? could I sit the exam alone, or would I have to join everyone else? The cycle was insane, I never cycle on my bike\u0026rsquo;s max gear, but I did, for the whole journey. I live quite close to the school, so I just had to churn out all the power that I could through my legs into my bike. I got stopped by 2 red lights, the last of which was near my school, where my mom called saying that the secretaries wanted me to go to the 6th floor (the floor of my school where the high school office was. Whoops. I was cooked. That was 12:09.\nI reached the office floor, where I was greeted by the timetabler. He was the one in charge of escorting students who are late into exam halls, and I bumped into him just as he was walking into a lift. He told me to come.\nThe exam hall Pin drop silence. That lift ride was hilarious, he asked me how long I\u0026rsquo;ve been in the school for, and kind of very slightly ridiculed me for mistaking 11:45 for 12:45. IGCSE Exams did in fact start at 12:45, but oh well. At the door, he told me to just go sit in the far corner by the window, and just start writing.\nI ducked and speedwalked to my seat the moment I entered the hall. It must have been after 12:15, because I remembered that I had 40 minutes to sit the paper. Apparently, they actually started the exam 10 minutes late, at 12:55. I don\u0026rsquo;t know if they were waiting for me. If they were, thanks to them, because that meant I would have only missed 20 minutes worth of time (I did) and not 30 minutes.\nI almost threw my calculator on the ground and I just started writing my paper 1. I was severely dehydrated and both my legs and butt hurted from that cycle. The invigilator put my bottle on a table out of arm\u0026rsquo;s reach. Thanks.\nThe questions started flying off the pages, it was as if the whole world was in slo-mo as my 160bpm+ heart supplied the side of my brain panicking to calm it down and the other half who actually had to sit the paper simultaneously. The equations started levitating off the pages; I couldn\u0026rsquo;t think of anything but the paper. I didn\u0026rsquo;t even lay my eyes off the pages. For one of the questions I got confused as I got a really really weird fraction, whereas the question asked for an integer, but I just pressed on.\nI ended up finishing paper 1, the entire thing, and fixed 2 questions where I knew I went wrong. Phew, that was surely crazy.\nThe rest of the exam I still had to sit paper 2. The adrenaline still pumped through my veins, I couldn\u0026rsquo;t even comprehend where I was, physically and mentally. I finally had access to my water bottle since it was during the time between the two papers, where we had to grab paper 2 and our calculators off the floor. I just did the paper, I was in a state of hyperfocus, albeit calmer than when I sat the first paper. The questions seemed far easier than I thought; the teacher who wrote this paper previously wrote one of our unit tests; that paper still gave nightmares to my friends for lets say\u0026hellip; a long time. This time around though, it wasn\u0026rsquo;t that bad.\nI drank water as usual, and my shit-slow TI-84 Plus CE equipped with a 48MHz 8/16/24 bit eZ80 CPU was my bottleneck. It still carried the rest of the exam though, I applied my usual optimizations (like turning off detect asymptotes off) and things went by far faster.\nHow?? I attribute this to the clutch factor. Speedrunners and athletes use this term to describe when someone performs better than expected under extreme pressure. I was under pressure; I knew that this whole fiasco would bring my grade down a good chunk, but I had to push through, and I did. Adrenaline saved me, thank you very much adrenaline, I owe you a cookie.\nAfter After the test, I rushed out of the exam hall. I was still disoriented. As of writing this article (right now it is around 3:57pm), I still have no idea as to what really happened. It really felt like I was in spectator mode. After the exam, I eventually did find my friends and talk to them; they thought that paper 1 was far easier than the warzone that paper 2 was. I personally think that P1 was harder, just because I was in a very disoriented state. Paper 2 was so much better, because I actually had the whole hour to sit it.\nMoral of the story, please don\u0026rsquo;t be late to your exams. But if you are, use your quick thinking. The clutch factor was what carried me, it will carry you too.\n","permalink":"http://ezntek.com/personal/adrenaline-the-clutch-factor-and-math-20231127t1532/","summary":"\u003cp\u003eMy inactivity on my website and my laziness towards actually making it look better is justified by the fact that it\u0026rsquo;s exam season, and I do the IB diploma program. It is very rigorous, they torture you with the exam, the exam board itself is\u0026hellip;very questionable, and I have to do 6 very heavy weight subjects, all with coursework.\u003c/p\u003e\n\u003ch2 id=\"math\"\u003eMath\u003c/h2\u003e\n\u003cp\u003eI picked the hardest math that the IBDP (or just the IB) has to offer, Higher Level Math: Analysis and Approaches, or just HL Math AA, or HLAA. Analysis and Approaches means that it has more pure math content and less of the weird statistical graph theory geometry stuff that Applications and Interpretations has to offer. It\u0026rsquo;s also because universities \u003cem\u003elove\u003c/em\u003e HLAA students, especially for Computer Science.\u003c/p\u003e","title":"Adrenaline, the Clutch Factor and Math"},{"content":"Prelude Check out the first part of this series, of course. This article won\u0026rsquo;t feature too much on the interpreter design, but how to effectively use it to your own benefit.\nTL;DR, I tried to write an IGCSE pseudocode interpreter a while ago, and I finished! Find it here at https://github.com/ezntek/beancode. Or, install it directly with pip install beancode --break-system-packages (this will not break your system packages, because beancode has no system dependencies, and will not break anything despite the scary flag)\nJump here if you only want to learn about the special and extra features of the interpreter and functional quirks.\nIntro I published my first article almost a year ago; on the 18th of September, 2024. It is now the 13th September, 2025. What\u0026rsquo;s happened since then?\nWell, a lot of school stuff. I was in grade 10 at the time, with quite a bit of spare time. However, I just didn\u0026rsquo;t get around to doing much of anything!\nOriginally I wanted to write a pseudocode compiler in C, but I got stuck at the parser. If you look at my really old code somewhere in https://github.com/ezntek/beanwarehq, I actually tried to write a bottom-up parser. Young ezntek really did discover another parsing technique just then, however implemented horribly and barely functional.\nI then tried to write one in Zig. In one afternoon I ported the lexer over, but that didn\u0026rsquo;t end up going anywhere. Sometime during march of this year, I just had enough waiting; I had a bunch of other projects and a lot of schoolwork to do (I am, after all, a leader of the computer programming club at my school, and the author of a bunch of IGCSE CS revision resources), but I really just wanted to get something done.\nI tried to follow Crafting Interpreters\u0026hellip;in Python. I knew the language, it was slow, horrible, but great for doing hacky stuff like the thing I envisioned (just a single top-down recursive-descent parser), and that ended up going\u0026hellip;really well.\nSo what do we have now?\n\u0026hellip;what? By the way, yes, it is running on my interpreter. It\u0026rsquo;s called beancode. Grab it here; it\u0026rsquo;s called beancode. Here\u0026rsquo;s the source code for the demo:\nINCLUDE_FFI \u0026#34;beanray\u0026#34; CALL InitWindow(800, 600, \u0026#34;hello, world!\u0026#34;) CALL SetTargetFPS(60) WHILE NOT WindowShouldClose() DO CALL BeginDrawing CALL ClearBackground(RAYWHITE) CALL DrawFPS(20, 20) CALL DrawRectangleRec({ 100, 100, 200, 150 }, RED) CALL DrawRectangleRec({ 175, 150, 225, 150 }, GREEN) CALL DrawRectangleRec({ 125, 200, 175, 150 }, BLUE) CALL DrawText(\u0026#34;Hello from Pseudocode!!!\u0026#34;, 200, 400, 40, BLACK) CALL DrawText(\u0026#34;Pseudocode to Python Raylib Bindings by ezntek\u0026#34;, 200, 450, 20, BLACK) CALL EndDrawing ENDWHILE CALL CloseWindow Architecture This program is actually very simple. Now, I will elaborate on the architecture in a later post, and post design-related shotcomings. This is the overall structure:\nLexer Parser Interpreter For those who know, this is a tree-walking interpreter. Basically, the source file is parsed into a tree-like data strcuture which represents the source file\u0026rsquo;s layout and structure. Then, the structure is traversed by Python to evaluate expression adn to do stuff.\nLexer The lexer is quite stupid. You can find it in beancode/lexer.py. It is so stupid and scuffed that it doesn\u0026rsquo;t even support streaming tokens properly (although I could hack it in, in theory). It also does really weird stuff. There\u0026rsquo;s logic in the lexer that actually does some \u0026ldquo;parsing\u0026rdquo; because this was a hasty AF fix. -4 is treated as a single literal -4 and not minus, literal(4). Wow! I forgot why I did this honestly\u0026hellip;\nOtherwise, it works\u0026hellip;barely. It is also really bad at detecting unterminated string literals. At some point it just screams and gives up on reporting proper position data.\nParser The parser is equally as cursed, if not more than the parser. It is recursive-descent and does not use any precedence tables (what the hell are those). Position data reporting is cursed as hell, but whatever. It cannot detect many parsing errors at once, it will stop whenever it sees an error. It also doesn\u0026rsquo;t use the consume and expect pattern that I later learned about, its more like:\ntoken = self.consume() if token.kind != \u0026lt;wanted kind\u0026gt;: raise BCError(f\u0026#34;expected \u0026lt;token kind\u0026gt;, but got {token}\u0026#34;, token.pos) You will see this pattern literally everywhere :\u0026gt;\nInterpreter This is super scuffed as well. Intrinsics (i.e. \u0026ldquo;Library Routines\u0026rdquo; as Cambridge calls them) are implemented literally as Python functions, dispatched with a massive switch-case. The number of arguments are literally just stored in a global hash map. I could go on for hours regarding the cursedness of this thing and how many hacks this thing has implemented. It does literally no optimizations, and global and local variables behave VERY WEIRDLY.\nThe REPL The REPL works on a bunch of input statements. Since each component so far was a reusable class that I could call intermediate methods on, I just stitched them together to make a REPL. I abused Python\u0026rsquo;s readline module a lot for basic REPL features like shell history, and moving around in the current input buffer.\nEach line is fed into the lexer, and then parser, and run in a global interpreter context. If EOF is reached during parsing or lexing, the parser throws an exception with the eof flag set to True. The REPL then catches the exception and enters continuation mode. The usual prompt is \u0026gt;\u0026gt; , but for continuation mode, it is .. . The current input buffer before the continuation is saved in a StringIO, and every time a new line is entered, the parser tries to analyze the entire input so far, and then keeps going if EOF is reached. Otherwise, it returns back to the parent main REPL runner. Position reporting actually works! (Surprisingly, errors work fine for the most part). Some errors report as having position line 0, column 0, which is a really annoying feature I left in because I didn\u0026rsquo;t want to null the position field in the error class. I\u0026rsquo;ll fix it if it\u0026rsquo;s actually that bad. Extension Features I will from now assume that you know how to write Pseudocode.\nYou can use lowercase keywords! Begone the days of screaming your code, you can just write lowercase words like for, next, if, while, etc. You can include other beancode files with INCLUDE \u0026quot;filename\u0026quot;, which is the file name you want to include, with the extension. Mark a symbol (variable declaration, constant, procedure or function) with EXPORT to dump it into the current scope. There are no namespaces! You can even include FFI modules with INCLUDE_FFI. They have to be the bundled modules, though. beanray is an incomplete set of raylib bindings that supports some basic examples. beanstd is a very small std library with some basic functinoality. demo_ffimod is just a demo FFI module as a proof-of-concept. Mark custom scopes with SCOPE and ENDSCOPE. You can also export from them. There are a bunch of added intrinsics. Check them out in the README on the GitHub repo. You can type cast with TYPE(expr) You can declare and assign on the same line, if you really need to. You don\u0026rsquo;t even have to specify the type: DECLARE Num: INTEGER \u0026lt;- 5 DECLARE Num \u0026lt;- 4 I added a bunch of neat type inference features. Num \u0026lt;- 4 is equal to DECLARE Num: INTEGER \u0026lt;- 4. If you have a declared variable, it will be able to guess the type too. You can INPUT into an undeclared variable, and it will \u0026ldquo;insert a declaration\u0026rdquo; and then store your input into the new variable. Array literals! Arr \u0026lt;- {1, 2, 3, 4, 5} is an ARRAY[1:5] OF INTEGER Matrix literals! Mat \u0026lt;- {{1, 2}, {4, 5}, {7, 6}} is an ARRAY[1:3,1:2] OF INTEGER There is some introspection/reflection. You can get the type of any variable with TYPE(value) or TYPEOF(value) (case-insensitive) Quirks You cannot have multiple lines in a CASE OF statement. You have to put your code into a procedure. File I/O does not work at all. Some errors report as unused expression or invalid statement or expression. Reported errors will look a little different on Windows (ASCII only chars), thanks to its horrible unicode support. F*** you, Micros*ft! Scope All variables are global. They will infect all sub-scopes. For example:\nDECLARE A: INTEGER // In scope: A SCOPE DECLARE B: INTEGER // In scope: A, B SCOPE DECLARE C: INTEGER // In scope: A, B, C ENDSCOPE ENDSCOPE When a new block is created, all the pointers to outside variables are copied to the current sub-interpreter\u0026rsquo;s variable pool. This works the exact same for procedures. You cannot have truly local variables, and you cannot shadow a declaration of an outside variable with a local variable.\nThe REPL The REPL is a truly life-changing innovation. Simply launch beancode without any arguments and you will be dropped in a REPL, and you can start typing code. Expressions will be printed.\nThe REPL also has special features which lets you see the state of the interpreter. You can talk to the REPL and not the interpreter with dot commands. Here are the very important ones.\n.var gets information regarding an existing variable. It prints its name, type, and value. .vars prints information regarding all variables. .func gets information regarding existing functions or procedures. .funcs prints information regarding all functions and procedures. Delete a variable if you need to with .delete [name]. (Version 0.3.4 and up) Or, reset the entire interpreter\u0026rsquo;s state with .reset. History is saved to ~/.beancode_history.\nPerformance Performance is at the mercy of the Python implementation. From my GitHub page:\nIt\u0026rsquo;s really bad. However, PyPy makes it a lot better. Here\u0026rsquo;s some data for the PrimeTorture benchmark in the examples, ran on an i7-14700KF with 32GB RAM on Arch Linux:\nLanguage Time Taken (s) beancode (CPython 3.13.5) 148 beancode (PyPy3 7.3.20) 11 beancode (CPython Nuitka) 185 Python (CPython 3.13.5) 0.88 Python (PyPy3) 0.19 C (gcc 15.2.1) 0.1 Am I done? NO! Of course not. This is just my foray into compiler engineering. I will not be making any more of these IGCSE Pseudocode interpreters; I will continue to maintain this one till the day I die. Please send bug reports! It will help all of us!\nI will be working on a proper compiler that lowers an AST down to assembly, and a proper interpreter with a bytecode VM.\nOh also, my Computer Science teacher said that he\u0026rsquo;ll use this to teach Pseudocode to his grade 10 class, and by extension, the cohort. Yay! I\u0026rsquo;m not useless anymore, I guess. Stay tuned for a part 3 where I actually roast my code\u0026hellip;if I find the motivation to write it.\n","permalink":"http://ezntek.com/posts/creating-an-igcse-pseudocode-interpreter-pt-2-20250913t1349/","summary":"\u003ch2 id=\"prelude\"\u003ePrelude\u003c/h2\u003e\n\u003cp\u003eCheck out the first part of this series, of course. This article won\u0026rsquo;t feature too much on the interpreter design, but how to effectively use it to your own benefit.\u003c/p\u003e\n\u003cp\u003eTL;DR, I tried to write an IGCSE pseudocode interpreter a while ago, and I finished! Find it \u003ca href=\"https://github.com/ezntek/beancode\"\u003ehere\u003c/a\u003e at \u003ca href=\"https://github.com/ezntek/beancode\"\u003ehttps://github.com/ezntek/beancode\u003c/a\u003e. Or, install it directly with \u003ccode\u003epip install beancode --break-system-packages\u003c/code\u003e \u003cem\u003e(this will not break your system packages, because beancode has no system dependencies, and will not break anything despite the scary flag)\u003c/em\u003e\u003c/p\u003e","title":"Creating an IGCSE Pseudocode Interpreter (part 2)"},{"content":" (This dog has committed some naughty crimes!)\nI aspire for this series of articles to be a lighthearted insight into the more interesting/noteworthy parts of my life\u0026hellip;beginning with part 1, the tale of an injured pigeon.\nTW: injured animals\nI was walking my dog this evening (around 6:45). It\u0026rsquo;s a small Bichon Frise, but I suspect it might be a bolognese. Anyway, when I was walking it, It came acrosss a pigeon walking around the residential areas near my house.\nIt seemed to walk slower than usual, but I didn\u0026rsquo;t think much of it. My dog started chasing it, like usual, like any dog would when they see a bird (usually it likes to chase chickens, but a pigeon works). However, when it charged at the pigeon in an attempt to kill it, it actually managed to rip two feathers off its tail, which is very strange considering that pigeons are usually agile enough in these situations.\nYet despite how hard the pigeon tried to flap its wings after it got ambushed, it didn\u0026rsquo;t manage to fly away. It helplessly and silently hopped and sprinted1 for its life while my dog continued to chase it. I let my dog chase it, because if I didn\u0026rsquo;t let it, it would go back to licking the floor and licking light poles with dog piss on it2.\nIt eventually tried to take a bite of the disabled pigeon once again, where the pigeon then stumbled (literally) into a very low corner with a staircase on top of it. There was a little bookcase in the corner, where it hid. My dog yanked its leash and went to corner, effectively putting the poor pigeon in a standoff.\nThe pigeon was glued to the wall; it stared out with all the fear a pigeon could express in its eyes, barely moving and ever so slightly shaking. I didn\u0026rsquo;t let my dog attack it further.\nI grabbed my dog and held it up as I went over to reach the pigeon to grab it. Pigeons\u0026rsquo; wings are actually quite loose, they aren\u0026rsquo;t really balls of cute fur. I gently picked it up to examine the damage and to investigate why it couldn\u0026rsquo;t fly.\nClick here for image 1\nOn the surface it didn\u0026rsquo;t look too injured, its wings were still loose and it was clearly able to flap. I petted the pigeon gently, but it didn\u0026rsquo;t coo. It was just warm, still trembling slightly. I could hear its heartbeat quite loudly, which I didn\u0026rsquo;t expect.\nBut when I turned it around\u0026hellip;\nClick here for image 2\nIt was injured very badly. The skin and feathers below its heart and vital organs were all ripped off, somehow. It had smelly goo from a dumpster nearby stuck onto it too, it didn\u0026rsquo;t smell very good. I could see its poor little heart beating at max speed, literally holding onto dear life.\nI petted it a little bit more, and attempted to gently release it. However, it scrambled away from my hand before I could, and it fell to the ground whilst flapping its wings; it clearly couldn\u0026rsquo;t fly.\nI really didn\u0026rsquo;t know what to do, I didn\u0026rsquo;t consider calling a helpline or anything, this was just a street pigeon, and there are many, many more injured ones like this. It is however a shame I didn\u0026rsquo;t constrain my dog enough while it chased it. It was just 2 feathers, however. Peace be upon this poor pigeon.\nOn the way home I realized my hands felt absolutely repulsively disgusting; that trash goo was legit.\nMy dog will not be allowed to chase any more pigeons after this.\nThis is actually the fastest I\u0026rsquo;ve seen a pigeon walk.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nIt\u0026rsquo;s a dog, don\u0026rsquo;t question it.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/personal/easons-life-chronicles-part-1-20250728t2007/","summary":"\u003cimg src=\"/img/dogspecimen.jpg\" width=\"50%\" /\u003e\n\u003cp\u003e\u003cem\u003e(This dog has committed some naughty crimes!)\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eI aspire for this series of articles to be a lighthearted insight into the more interesting/noteworthy parts of my life\u0026hellip;beginning with part 1, the tale of an injured pigeon.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003eTW: injured animals\u003c/strong\u003e\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eI was walking my dog this evening (around 6:45). It\u0026rsquo;s a small Bichon Frise, but I suspect it might be a bolognese. Anyway, when I was walking it, It came acrosss a pigeon walking around the residential areas near my house.\u003c/p\u003e","title":"Eason's Life Chronicles Pt. 1: Disabled Pigeon"},{"content":"\nI have been living in Singapore for 10 years by now. Eight long years ago, I moved into the house I am currently in.\nI was assigned the second bedroom in my house, counting from the beginning of a long corridor that began in the living room. I had no desk, just a piano and a 90cm bed. I also had a large, long windowsill that spanned the width of my room; a large concrete slab with nothing on it.\nI decided to put my computer there, the empty area between my piano and bed, and used it like a makeshift desk; I brought a little stool for me to sit on. My mac was an 11.6 inch, early 2014 MacBook Air, with an i7-4650U, 8gb of RAM, and a 512gb SSD. I still have it.\nMonths later, at the age of around 10 (my memory is very faint), I was gifted a custom PC that I was supposed to build\u0026hellip;but I didn\u0026rsquo;t know how to build one at all. I asked my dad to do it.\nI put it on the windowsill, and that\u0026rsquo;s where my computing journey really started to kick off. It was the windowsill where I did all the virtualization I did to run modern and ancient OSes. It was the windowsill where I had set up my first file servers (SMB, AFP when that was more common, and even FTP), and my first http server. It was the windowsill where I set up my first linux server, had all the emotional breakdowns I had as a young asian boy, and the windowsill where I taught myself simultaneous equations in 5th grade.\nAnd as I grew up, the windowsill grew up with me. It wore off, the things on it got dusty, and I eventually grew out of it; I needed a better desk setup.\nAnd years later\u0026hellip;\nI am now one of the best programmers1 in my whole high school. I am now fluent in all the programming languages I\u0026rsquo;ve dreamt of learning; C, Python, Rust2, and exen x86_64 linux assembly; name whatever. I have written real software; many pieces of real software. I\u0026rsquo;ve even made it onto hacker news, which made my dad pretty proud3.\nAnd just 30 minutes ago, that same Eason who, many years ago, sat at that windowsill for hours exploring the world of computing; going from Eason Tech Reviews to ezntek, visited said room. There is now a new bed inside for my father, who\u0026rsquo;s out of the country. I sat on the bed, and looked at the windowsill, where there were some books, some other assorted items, a fan and some plants.\nAnd I realized. That was the exact same windowsill from all those years ago, where I explored computing as an elementary school computer enthusiast; where I ran my old YouTube channel. I am the same person as the Eason from all those years ago, still with that same passion for computing, just grown up a little, with a far more mature mind than the typical 16 year old4. I am clearly changed, I am now ezntek.\nBut that windowsill will only be accessible to me for the next 2 years. In 2027, I graduate; I leave Singapore. In a mere two years, I will not be able to see the birthplace of the new me ever again. A slab of concrete with so many memories, like how I\u0026rsquo;d used to put my MacBook underneath my bed next to run it as a file server, or where I miserably failed at learning Python.\nI attribute all my success and my new passion to that windowsill, that isolated corner away from all the commotion in my family. It proved to me what I was really good at. And yet it will only be a faint memory, seen through just a few pictures taken on my iPhone SE in gold, one that I\u0026rsquo;ll only tell my kids, because they will never be able to see it, and I\u0026rsquo;ll never see it again very soon. Needless to say, I will miss my windowsill very much.\nCherish your time, cherish your memories; the things that you love will eventually become one too. Just a mere thought that will fade until your eventual demise.\nFortunately, I have an adulthood ahead of me. Unfortunately, I have an adulthood ahead of me. Sometimes I wish I could live as a teenager with free will a little longer, in this house a little longer, because I will miss this silly little apartment, and my silly little windowsill.\nI still hope that someone secretly better than me shows up, but unfortunately, noone has. I am THE computer scientist in the high school. I am well known. Despite my contributions and work, I still do not like to think of myself as the best.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nTried to learn it in the seventh grade in mid 2022, that didn\u0026rsquo;t go well.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\npsst! check out my libreboot\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nI do not also like to claim I am wiser than everyone else. I have been told this my numerous people. Even judging by how the typical 16 year old kid in my high school behaves (similar to American High School students, exceptions of course exist but are not a major departure), this is a fair argument.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/personal/memories-20250711t2129/","summary":"\u003cp\u003e\u003cimg alt=\"The windowsill\" loading=\"lazy\" src=\"/img/windowsill.png\"\u003e\u003c/p\u003e\n\u003cp\u003eI have been living in Singapore for 10 years by now. Eight long years ago, I moved into the house I am currently in.\u003c/p\u003e\n\u003cp\u003eI was assigned the second bedroom in my house, counting from the beginning of a long corridor that began in the living room. I had no desk, just a piano and a 90cm bed. I also had a large, long windowsill that spanned the width of my room; a large concrete slab with nothing on it.\u003c/p\u003e","title":"Memories"},{"content":"So\u0026hellip; These earbuds are kinda meh. TL;DR: the mids are strong, the high end is muddy, the case feels kinda cheap but are actually decent for the price.\nThe good These are cheap. Despite how the label says S$79, these actually only costed S$65, which are actually a steal. These are Sony earbuds, so you do get the Sony software and support, with all the EQ magic they have. The noise cancellation is insanely good. Even without active noise cancellation, the ear tips themselves do absolute magic on any surrounding noise, whether if its wind from a fan, the air conditioner, or whatever else. Having used AirPods Pro gen 1\u0026rsquo;s previously, I must say that these are 95-98% the strength, without all the head pain from the noise ANC generates. The eartips fit very tightly within the ears, they do not fall out easily. The range is great. The mids are great. If you listen to genres like ChillSynth1 these are perfect. The \u0026lsquo;ambient sound mode\u0026rsquo; is incredible (the sound passthrough feature), it really sounds as if you are not wearing earbuds at all and even thhe little details like the volume your earbuds play the ambient sound back at matches the volume of your actual surrounding environment. These things are unfazed by wind. The bad The case feels cheap. The earbuds also feels cheap. There is no ANC, which may annoy some. The case does not actually have any magnets, making opening and closing feel much cheaper. The ugly The trebles are kinda muddy, if you have ever used better headphones you will know what I\u0026rsquo;m talking about. Say goodbye to vocal clarity, they will be slightly muddy. The EQ only somewhat fixes it. In normal use, it isn\u0026rsquo;t all that bad. The drivers are only 6mm. Coming from my Pixel Buds A-series\u0026rsquo;, it is a massive, massive downgrade. The sound isn\u0026rsquo;t particularly \u0026ldquo;room filling\u0026rdquo; nor \u0026ldquo;full\u0026rdquo;, it\u0026rsquo;s just sound. Verdict This was just a quick review, I\u0026rsquo;m not in the mood of writing anything exciting. Avoid these if you have money, I tried to not burn my wallet this time around but man if I just splurged a bit more, would I have gotten much better sound. If these are the only budget option available, these are not bad, but coming from better audio devices, these aren\u0026rsquo;t the best.\nThese are 90-95% as good as AirPods Pro 1\u0026rsquo;s for EDM (complextro/electro house/bass house/future bass/future bass), Hardstyle sounds fine on these (not painful enough), and ChillSynth sounds pretty damn good (no it sounds awesome). I would still rather my Pixel Buds A-series, but oh well.\nI also took them outside today (May 25), outdoor performance was excellent. The fit (again) is absolutely incredible, and sound quality was not sacrificed at all.\nIf you are looking for similarly priced earbuds in asia, look to sudio, I\u0026rsquo;ve heard great things about them, and products similarly priced to these sonies (At least here) have at least bigger drivers, ANC, and a longer battery life.\nI would describe these as utilitarian. Not too much flair, no BS, just-works earbuds that deliver good enough sound quality to make the typical bloke happy.\nshoutout to guyfrom beacuse he really likes this genre and introduced chillsynth to me. Chillsynth is not lofi.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/posts/a-review-of-the-sony-wf-c510-earbuds-20250524t1919/","summary":"\u003ch2 id=\"so\"\u003eSo\u0026hellip;\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"The earbuds\" loading=\"lazy\" src=\"/img/earbuds.jpg\"\u003e\u003c/p\u003e\n\u003cp\u003eThese earbuds are kinda meh. TL;DR: the mids are strong, the high end is muddy, the case feels kinda cheap but are actually decent for the price.\u003c/p\u003e\n\u003ch2 id=\"the-good\"\u003eThe good\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eThese are cheap. Despite how the label says S$79, these actually only costed S$65, which are actually a steal.\u003c/li\u003e\n\u003cli\u003eThese are Sony earbuds, so you do get the Sony software and support, with all the EQ magic they have.\u003c/li\u003e\n\u003cli\u003eThe noise cancellation is \u003cstrong\u003einsanely good\u003c/strong\u003e. Even without active noise cancellation, the ear tips themselves do absolute magic on any surrounding noise, whether if its wind from a fan, the air conditioner, or whatever else. Having used AirPods Pro gen 1\u0026rsquo;s previously, I must say that these are 95-98% the strength, without all the head pain from the noise ANC generates.\u003c/li\u003e\n\u003cli\u003eThe eartips fit very tightly within the ears, they do not fall out easily.\u003c/li\u003e\n\u003cli\u003eThe range is great.\u003c/li\u003e\n\u003cli\u003eThe mids are great. If you listen to genres like \u003ca href=\"https://chillsynth.com\"\u003eChillSynth\u003c/a\u003e\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e these are perfect.\u003c/li\u003e\n\u003cli\u003eThe \u0026lsquo;ambient sound mode\u0026rsquo; is incredible (the sound passthrough feature), it really sounds as if you are not wearing earbuds at all and even thhe little details like the volume your earbuds play the ambient sound back at matches the volume of your actual surrounding environment. These things are unfazed by wind.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"the-bad\"\u003eThe bad\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eThe case feels cheap.\u003c/li\u003e\n\u003cli\u003eThe earbuds also feels cheap.\u003c/li\u003e\n\u003cli\u003eThere is no ANC, which may annoy some.\u003c/li\u003e\n\u003cli\u003eThe case does not actually have any magnets, making opening and closing feel much cheaper.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"the-ugly\"\u003eThe ugly\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eThe trebles are \u003cstrong\u003ekinda muddy\u003c/strong\u003e, if you have ever used better headphones you will know what I\u0026rsquo;m talking about. Say goodbye to vocal clarity, they will be slightly muddy. The EQ only somewhat fixes it. In normal use, it isn\u0026rsquo;t all that bad.\u003c/li\u003e\n\u003cli\u003eThe drivers are only 6mm. Coming from my Pixel Buds A-series\u0026rsquo;, it is a massive, massive downgrade.\u003c/li\u003e\n\u003cli\u003eThe sound isn\u0026rsquo;t particularly \u0026ldquo;room filling\u0026rdquo; nor \u0026ldquo;full\u0026rdquo;, it\u0026rsquo;s just sound.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"verdict\"\u003eVerdict\u003c/h2\u003e\n\u003cp\u003eThis was just a quick review, I\u0026rsquo;m not in the mood of writing anything exciting. \u003cstrong\u003eAvoid these\u003c/strong\u003e if you have money, I tried to not burn my wallet this time around but man if I just splurged a bit more, would I have gotten much better sound. If these are the only budget option available, these are not bad, but coming from better audio devices, these aren\u0026rsquo;t the best.\u003c/p\u003e","title":"A Review of the Sony WF-C510 Earbuds"},{"content":"WhatsApp is bad. WhatsApp is evil, and they do not deserve a spot in anybody\u0026rsquo;s lives. They hate their users.\nNote that this article will contain swear words. If you can\u0026rsquo;t handle them, look away :)\nTL;DR WhatsApp is evil. Meta is evil. They steal your data, they have control over you. This is just a case study; for a change, use Signal.\nBackstory. Yesterday morning (13th May, around 9am GMT+8) I tried to create a new community on WhatsApp, on my desktop, for an up-and-coming mathematical society at my school.\nThis is completely fair. Nothing weird. Nothing suspicious. I create the community. No problem. But when I try to add an existing group chat, a feature given by WhatsApp, it says that there was some mysterious error, and that I could try again.\nSo I did. I tried again. And I got kicked back to the login screen on my computer. I check my phone, and see this:\nWhatsApp suspended my account for doing absolutely nothing.\nThe rabbit hole Nothing got better after that. I requested for help on the form they had provided. It said that it would take upwards of 24 hours, but only after around 8 hours was it restored.\nIn the meantime, I could not communicate with anybody. Nobody used Signal. Some of my friends do not use Instagram1, therefore the only way I could communicate with them was through\u0026hellip;SMS. Good-ol\u0026rsquo; SMS saved the day, I was able to notify my mom and dad about the issue.\nIt was really baffling. I didn\u0026rsquo;t even do anything, what was WhatsApp going to say? What, I talked too much shit about them?\nAfter a while, my account was restored. Apparently, they just fucked up! And that was good enough of an excuse to keep using their shitty bots to save costs, or something.\nProminently standing on the homescreen was a button. Verify account.\nIt kicked me back to the login screen, the typical login screen, where I was told to enter my phone number and go through the typical verification steps. Okay. Nothing seemed off\u0026hellip;until\u0026hellip;\nApparently, I was using a custom ROM\u0026hellip;or maybe a hacked version of WhatsApp\u0026hellip;or had a rooted phone. I HAD NONE OF THOSE THINGS! It\u0026rsquo;s baffling how horrible this proprietary piece of shitware is. I was on stock Android 16 Beta, on my Pixel 8a, without any software mods, with a locked bootloader.\nE-mails to support This is the part that infuriates me the absolute most.\nI went on WhatsApp\u0026rsquo;s help page, in the app, accessible on the top right. I typed up my message, elaborating that I actually was NOT using a custom ROM or any modified software.\nAfter my account was restored after it was falsely flagged as spam, I am unable to log back in I am not using a custom ROM, and I have tried both the official and play store builds of WhatsApp. What steps should I take to logging back in?\nI sent it off, hoping I would get a reply within a few hours.\nHi,\nYour attempt to register your phone number failed because you appear to be using an unofficial version of the WhatsApp app. We don’t support unofficial apps because they put your privacy and security at risk. They also put your data and device at the risk of malware.\nCustom ROMs and rooted phones also aren\u0026rsquo;t supported by WhatsApp, learn more in this article.\nWhat to do next\nSave your chat history. Uninstall the unofficial app. Download WhatsApp or the WhatsApp Business app from official app stores or our website. Register your phone number. If you see an error that the app isn’t available in your country, visit this page to download WhatsApp.\nNeed more help?\nTry registering on a different phone. Upgrade the operating system on your phone. Troubleshoot why you can’t download or update WhatsApp. That\u0026rsquo;s the reply I got. At first I thought,\nDamn. Why is this guy on the support side so insanely illiterate?\nBecause they would have seemed very illiterate. I literally stated that I am not using a custom ROM, and whatnot. But no, this stupid person clearly did not read that I am not using one.\nI sent a reply, like any sane person would, hoping that a person would answer.\nHi,\nI am definitely using the official WhatsApp App, I have downloaded it from the play store. I am not using a custom ROM. This is an unmodified, unrooted, Google Pixel 8a on Android 15 beta. The APK on your website does not work. My phone is running the latest update.\nI believe my phone number may be falsely detected as a toll-free number. When I try to enter my phone number on the mobile app, it spaces it out as XXX XXX XX__, and not XXXX XXXX, as per Singapore standards. However, it is not a toll-free number, I purchased this number from my carrier.\nMay I please have more assistance? It would be much appreciated. This issue occurred from after my account was falsely flagged for spam. I am trying to re-register my phone number at this stage.\nSincerely, Eason Qin\nI got,\nHi,\nPlease contact us in our app\nThis enables us to collect information that’s necessary to understand and resolve your issue. Learn more.\nContact us\nIf you can’t contact us from the app, you can send us your question through our support form or browse our Help Center.\nThanks for your understanding and cooperation.\nMind you, no data had to be collected. All data was present, I had sent it in the same E-mail thread, and any sane human would be able to open the file, and read it.\nI got the first reply. FOUR TIMES. In a row. Yes. I was convinced by the third time that it was an LLM, it clearly was; on the contact form on WhatsApp\u0026rsquo;s official website, it said that it might use Meta AI to answer my requests:\nBy continuing, you allow WhatsApp to review technical information about your account to help answer your question. Messages from WhatsApp Support may be generated by AI using a secure technology from Meta. Your personal messages and calls remain end-to-end encrypted.\nWhich it clearly did.\nThe crux of the issue is that Meta is so damn lazy and incompetent that they cannot pull shit together to hire employees to respond to these E-mails. My situation clearly is unique. I am not using a custom ROM or anything, but I have been told that I am, and that meant that my chats weren\u0026rsquo;t secure anymore, not like they really are in the first place. They can decrypt them anytime2.\nIn many of my requests I had included \u0026ldquo;I would like to speak to a human about this matter\u0026rdquo;, but to no avail. Instead, the same LLM, maybe even an Expert System3, would answer my messages, with the same response, accusing me of doing something I don\u0026rsquo;t do.\nI tried every fix on the internet. On YouTube, on random tech websites; I even had to resort to random Indian/Indian-sounding tech guys who are known to post inaccurate content 50% of the time4, to no avail. And there are no manuals. No piece of documentation exists on this specific case of this issue, on an app that over 3 billion users use, per month!5. I am a programmer, I am used to reading manuals), because they actually help. But instead, all I get are stupid YouTube videos, stupid articles that were written by a chatbot, or stupid LLM E-mails.\nI tried to contact them over Twitter6 (now known as X), and Instagram:\nBut to no avail.\nAnd look at the same thread I tweeted on! Verified influencers flood the top:\nand commoners like us, requesting for help, sit right below. No matter how hard Elon M*sk tries to hide it, we can see it.\nThere are more instances; I can\u0026rsquo;t get it to fit on one screenshot.\nI also got no response on Instagram.\nThe harsh reality. All WhatsApp cares for is money, publicity, and users to milk data from. We are not users. We are useds. We do not in fact use the software.\nThink about it, we are not given any instructions to recover our accounts. We cannot talk to the company. We have no transparency as to how the operate. We are not given the source code of the app; if we had the damn source code, maybe I would have been able to read it. And maybe I would have been able to do all the debugging work for them.\nBut instead, WhatsApp controls us. They can mess up by banning innocent users, and not talking about it. They can force people to plead, disrupt lives, and communications. What happens if somebody was discussing an important business deal on their accounts, an important school event, or anything of the likes?\nI hate to bring him up due to his status of possibly liking children, but the wise man Richard Stallman once said in his TEDx speech that having freedom over your software, i.e. you controlling it, is a human right. It indeed is, we should not be used like this by these companies, we should take control; our data is ours, the program deserves to be ours; nobody should be able to take it away from us.\nI don\u0026rsquo;t want to rant about Free Software all that much, free as in freedom, not free beer. It is software that you own; you have access to the source code, you can study it, you can change it, you can reshare it, and you can use it however you want, how software is supposed to be.\nDissecting the WhatsApp ToS (Terms of Service) It can be found at the following web link: https://www.whatsapp.com/legal/terms-of-service?lang=en, I may call it a EULA (you-lah), or end-user license agreement, too.\nHere are some interesting things that it says:\n\u0026ldquo;We collect device and connection-specific information when you install, access, or use our Services.\u0026rdquo; This means that they can collect any information they want about your device, whenever the hell they feel like it. What phone you use, your operating system, your public IP, and even installed apps and such. \u0026ldquo;As part of the Facebook Companies, WhatsApp receives information from, and shares information with, the other Facebook Companies.\u0026rdquo; This means that WhatsApp can share the data they collect to you to any other branch of facebook they want, whenever the hell they feel like it. \u0026ldquo;We may modify, suspend, or terminate your access to or use of our Services\u0026hellip;\u0026rdquo; This means that they can do whatever the hell they want to your account, like suspending it for unjust reasons. Basically, you don\u0026rsquo;t even own your own account. How lovely! It\u0026rsquo;s almost like you actually want to use it.\nOther privacy concerns WhatsApp also steals and sells your data whenever they feel like it. Of course, nobody will tell you this. Search engines have already been ce,nsored. This article is the tip of the iceberg, you can access it on https://removepaywalls.com if you don\u0026rsquo;t have a medium account.\nNo source will tell you the truth, that they could technically decrypt your chats and leak them. There is a reason that criminals don\u0026rsquo;t actually use WhatsApp, or journalists; because they know their data will be compromised and that they can be tracked. I can\u0026rsquo;t be assed to find 50 articles for you on this. However, a good starting point for your own discussion is that, if it\u0026rsquo;s so private, why can\u0026rsquo;t we prove it with cold, hard evidence, that being the code that WhatsApp runs on?\nThe solution Use Signal.\nThis is the real deal, a genuinely private messenger. Private Android variants like CalyxOS use it, and there\u0026rsquo;s a reason. It was created by the original creator of WhatsApp, who left the company after it was bought by Facebook. Its encryption algorithms are identical to WhatsApp\u0026rsquo;s, which is a great starting point; they don\u0026rsquo;t actually collect your message metadata, and have better privacy practices.\nFeatures are almost identical to WhatsApp\u0026rsquo;s. The apps are equally as polished. Communication is equally as good. There is no reason why you shouldn\u0026rsquo;t be using it. It is a truly private messenger that can\u0026rsquo;t just randomly terminate your account for no reason.\nI\u0026rsquo;ve used Signal for years, and other privacy-respecting services. I don\u0026rsquo;t even use Google Drive for serious purposes, nor Google Workspace, I self-host Nextcloud and use LibreOffice for basic document processing on Linux. If you want to know what I really use, you can comment below.\nThe truth is that I am not a criminal, in fact, I don\u0026rsquo;t have anything major to hide. It\u0026rsquo;s just that I do not want to feel watched and controlled; this is the perfect case study. I am exhausted. I sat a bunch of exams, and as of writing this article, I am both infuriated and sleepy. I got my account back, after FACTORY RESETTING MY PHONE 4 TIMES AND LOCKING THE BOOTLOADER, which is something I should not have had to do, but I had to, thanks to Meta.\nDon\u0026rsquo;t accuse me of being a cybercriminal, a hacker, or a terrorist; I\u0026rsquo;ve been called suspicious since Grade 7 and I\u0026rsquo;m tired of hearing it. Do you want your neighbors to know your exact activity and position, if you\u0026rsquo;re wearing clothes, showering, or sleeping naked? They don\u0026rsquo;t know all my secrets; but if Meta can point a telescope at my digital life that they promise is private (it\u0026rsquo;s not), and my neighbors can\u0026rsquo;t, this makes no sense. It is eerie knowing someone can detect your messaging patterns and what you say, at any time, with this data being sold to actual cybercriminals.\nLiberate yourselves. Start with a better chat app. Use Signal.\nI use it because I want friends. Everyone else uses it, and with it, I can actually reach a certain demographic of people.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nDon\u0026rsquo;t worry, this will be addressed in later sections.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nigcse comp sci lore™\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nThis is not racist. Many of them post fake videos demonstrating fixes that ruin your phone, or make you turn off your phone\u0026rsquo;s security for no reason. This applies for many IT topics, half of them actually post real fixes, the other half scam you. I am not going to put up a citation, you can search \u0026ldquo;you need the official whatsapp to log in fix\u0026rdquo; on DuckDuckGo; all the initial responses are from sketchy YouTubers who don\u0026rsquo;t actually help. If you think I\u0026rsquo;m still being racist, you can stop reading.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nhttps://techcrunch.com/2025/05/01/whatsapp-now-has-more-than-3-billion-users/\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nI made an account just for this!\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/posts/whatsapp-is-bad-move-to-signal-20250514t1714/","summary":"\u003cp\u003eWhatsApp is bad. WhatsApp is evil, and they do not deserve a spot in anybody\u0026rsquo;s lives. They hate their users.\u003c/p\u003e\n\u003cp\u003eNote that this article \u003cem\u003ewill contain swear words. If you can\u0026rsquo;t handle them, look away :)\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003eWhatsApp is evil. Meta is evil. They steal your data, they have control over you. This is just a case study; for a change, use Signal.\u003c/p\u003e\n\u003ch2 id=\"backstory\"\u003eBackstory.\u003c/h2\u003e\n\u003cp\u003eYesterday morning (13th May, around 9am GMT+8) I tried to create a new community on WhatsApp, on my desktop, for an up-and-coming mathematical society at my school.\u003c/p\u003e","title":"WhatsApp is Bad, Move to Signal"},{"content":"Finally?? Yes, this is a little bit delayed, but 3 days before the final computer science paper 1, I\u0026rsquo;m releasing this guide to help you all study.\nWhat is this? This is essentially a bank of notes for IGCSE computer science, the theory part. I will chop up my CSRG G2 semester 1 guide, which has extensive coverage of logic gates and programming, and release it independently, later. These notes are very, very detailed, so it is also a guide to some extent.\nFor more info, read the Information section at the front of the guide.\nPLEASE CONTACT ME IF YOU SPOT ANY MISTAKES OR TYPOS!\nDOWNLOAD Revision 5 (May 13, 2025) Alternatively, view the source code on Github.\nCHANGELOG Revision 2: Added Cloud Storage, fix spelling mistakes, improve wording across chapter 2. Revision 3: Add IPv6, fix minor errors in the intro, improve wording in chapter 5. Revision 4: Fix RAM access time, add ISBN-13/Modulo 11 syllabus omission notices, add SSL in chapter 5. Revision 5: Fix spelling errors, formatting errors, add note about possible inclusion of errors. ERRATA This details the factual, content-based errors that I may have made.1\n(fixed in revision 4): SRAM/DRAM access time is in nanoseconds, not milliseconds (pages 38, 39) (fixed in revision 5): DRAM consumes less power (page 39) and not SRAM, the program counter holds the next instruction (page 50) Idea suggested by Ved Jaggi. Added to the credits list.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/posts/igcse-computer-science-theory-revision-guide-20250509t2256/","summary":"\u003ch2 id=\"finally\"\u003eFinally??\u003c/h2\u003e\n\u003cp\u003eYes, this is a little bit delayed, but 3 days before the final computer science paper 1, I\u0026rsquo;m releasing this guide to help you all study.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"cover page\" loading=\"lazy\" src=\"/img/finalcsrgcover.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"what-is-this\"\u003eWhat is this?\u003c/h2\u003e\n\u003cp\u003eThis is essentially a bank of notes for IGCSE computer science, the theory part. I will chop up my CSRG G2 semester 1 guide, which has extensive coverage of logic gates and programming, and release it independently, later. These notes are very, very detailed, so it is also a guide to some extent.\u003c/p\u003e","title":"IGCSE Computer Science (Theory) Revision Guide (Full)"},{"content":"ezntek, you broke a promise? Yes! i said that would finish a full syllabus revision guide for all the chapters and for all the content covered, but I was not motivated to finish it all, below is a link to an incomplete coverless version with a bunch of inconsistencies, mid explanations and typos, but it surely is better than nothing.\nFind it here\n","permalink":"http://ezntek.com/posts/igcse-incomplete-computer-science-revision-guide-csrg-20250506t1130/","summary":"\u003ch2 id=\"ezntek-you-broke-a-promise\"\u003eezntek, you broke a promise?\u003c/h2\u003e\n\u003cp\u003eYes! i said that would finish a full syllabus revision guide for all the chapters and for all the content covered, but I was not motivated to finish it all, below is a link to an incomplete coverless version with a bunch of inconsistencies, mid explanations and typos, but it surely is better than nothing.\u003c/p\u003e\n\u003cp\u003eFind it \u003ca href=\"https://ezntek.com/doc/csrg_incomplete.pdf\"\u003ehere\u003c/a\u003e\u003c/p\u003e\n\u003cscript src=\"https://utteranc.es/client.js\"\n        repo=\"ezntek/ezntek.github.io\"\n        issue-term=\"title\"\n        label=\"comments\"\n        theme=\"github-dark\"\n        crossorigin=\"anonymous\"\n        async\u003e\n\u003c/script\u003e","title":"IGCSE Incomplete Computer Science Revision Guide (CSRG)"},{"content":"What? IGCSEs. Cambridge-assessed final examinations. As of writing this article, it is the 5th of May, the night before my IGCSE Coordinated Science (0654) paper 41. They are quite stressful, as you can tell by the title, but it really isn\u0026rsquo;t all that much.\nIGCSEs are simple! All you need to do is memorize the markschemes, do past papers and you\u0026rsquo;re good. Even if you aren\u0026rsquo;t comfortable with 5 entire topics, you can watch a few YouTube videos and cram all of it the night before! Such an easy life, no?\nSome Spice There\u0026rsquo;s a reason why I haven\u0026rsquo;t updated the site in a while. Trust me, I am working on great things to post and to show off! Writing this article is already a testament to my procrastination; I have 5 (minor) topics to revise, and yet I am working on this article. I\u0026rsquo;m an intelligent human being!\nIf I didn\u0026rsquo;t just have to deal with IGCSEs, I would be cruising. Minimal studying, minimal effort; I\u0026rsquo;d still get A*\u0026rsquo;s anyway (as had happened with mocks). However, I am a programmer, I have external responsibilities and projects I want to work on, and a shiny new mathematical society at my school! My math teacher, who just came to our school after being dragged out of her previous school where she had legendary, math jesus2-like status, wanted to start a Math Society.\nI told her that day, that our school had never seen a mathematical society ever before. The look on her face was shocking, but also amusing. I laughed on the inside, not at her, but at our school; our school\u0026rsquo;s demographic consists of just medicine, law, bio/chem, and humanities students. Nobody here liked math enough to start a math society! And nor did anybody have the idea. But she brought it up, and I was slightly enlightened. Being a computer scientist cosplaying as a mathematician, it was hard to announce to this teacher so passionate about math that she started a massive math journal publication with many, many, many contributions (I don\u0026rsquo;t have an exact page count, but the document was massive), the same person who openly said that she would marry math if it were a person3, and dedicated her effort to serving the people and the math society at her old school; that I was not a true mathematician.\nBut I am ready to become one. (i still wanna do compiler engineering :P)\nMore details are to come; this article just announces my existence, but if you are in OFS (Singapore) and are in High School, look out for some amazing things next year. I just did a bunch of planning work, it was fun, but I really have to study for science now.\nBye, and good luck to all Cambridge IGCSE students sitting the May/June 2025 exam series!\nFootnotes A long-answer paper, regarded as the hardest one and the longest.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nNo offense intended.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nI think she likes math.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/posts/stressful-times-20250505t2133/","summary":"\u003ch2 id=\"what\"\u003eWhat?\u003c/h2\u003e\n\u003cp\u003eIGCSEs. Cambridge-assessed final examinations. As of writing this article, it is the 5th of May, the night before my IGCSE Coordinated Science (0654) paper 4\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e. They are quite stressful, as you can tell by the title, but it really isn\u0026rsquo;t all that much.\u003c/p\u003e\n\u003cp\u003eIGCSEs are simple! All you need to do is memorize the markschemes, do past papers and you\u0026rsquo;re good. Even if you aren\u0026rsquo;t comfortable with 5 entire topics, you can watch a few YouTube videos and cram all of it the night before! Such an easy life, no?\u003c/p\u003e","title":"Stressful Times, with a Math Society on The Side"},{"content":"DOWNLOAD! here\nLong time no see! Sorry for not posting so much. My workloads been very very heavy; working on projects like this one. IGCSE CS students, look out for the comprehensive whole-syllabus comp sci revision guide soon! I will release it before mocks.\nWhat is this workbook? I wrote it because my comp sci teacher let me volunteer to teach. I happily took the offer due to everybody\u0026rsquo;s cluelessness (they still cannot assign variables). So far I taught 2d arrays in front of the class, and technically this is an assignment only I was set; to make a worksheet on iteration and arrays. It is now a workbook as people need explanations.\n","permalink":"http://ezntek.com/posts/igcse-computer-science-arrays-and-iteration-workbook-20250208t2108/","summary":"\u003ch2 id=\"download\"\u003eDOWNLOAD!\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://ezntek.com/doc/igcse_cs_arrays_iteration_workbook.pdf\"\u003ehere\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"long-time-no-see\"\u003eLong time no see!\u003c/h2\u003e\n\u003cp\u003eSorry for not posting so much. My workloads been very very heavy; working on projects like this one. IGCSE CS students, look out for the comprehensive whole-syllabus comp sci revision guide soon! I will release it before mocks.\u003c/p\u003e\n\u003ch2 id=\"what-is-this-workbook\"\u003eWhat is this workbook?\u003c/h2\u003e\n\u003cp\u003eI wrote it because my comp sci teacher let me volunteer to teach. I happily took the offer due to everybody\u0026rsquo;s cluelessness (they still cannot assign variables). So far I taught 2d arrays in front of the class, and technically this is an assignment only I was set; to make a worksheet on iteration and arrays. It is now a workbook as people need explanations.\u003c/p\u003e","title":"IGCSE Computer Science: Arrays and Iteration Workbook"},{"content":"NOTE Am I a tech nerd who blogs about technical stuff? YES!\nBut do I have a life? yes. This post is not technical, and I will only continue writing this format when I feel like it.\nScroll down if you wish.\nA long time ago\u0026hellip; When I was 11 or 12 or so (back in 6th grade), I had one of the most amazing math teachers ever. She was great at her job, but most importantly, every time the class and her had an interaction everybody would burst out in happy laughter; there was never one negative moment in that room.\nWe talked about birthdays and such, and the term \u0026ldquo;Sweet 16\u0026rdquo; popped up somewhere. While we were laughing hysterically from something mentoned previously, I nicely tried to ask (I was very awkward at the time and was not as social as now), I asked what it was. Turns out that\u0026hellip;it\u0026rsquo;s just a special birthday\u0026hellip;for some reason?\nPeople get insane things (rich people, of course), like cars (why the hell), phones (you only need one when LineageOS stops supporting it, M*cBook Pro Max Ultra Extras or whatever that costs 6 grand\u0026hellip;whatever. And I was told that everyone throws massive parties on that day, as if they were turning 18 or something.\nTo this day I still do not understand the appeal of calling this birthday so special. It doesn\u0026rsquo;t grant you any more rights in the eyes of most western/western-influenced/sane governments (you must wait till 18 for an actually important birthday), and I also do not understand why it is such a major event for so many people. Lavish parties, crazy celebrations, but what for?\nWhat\u0026rsquo;s so sweet about 16?\nAchievements I\u0026rsquo;d like to reminisce over the things I was able to pull off in the past year.\nCompletely unrelated, but my age is now 0b1000, it no longer fits in a 4 bit register. I won second place in a hackathon, doing web development (something I never do) in a toolkit i have never touched previously (Vue). I got very good at C, and convinced a good amount of my friends to either look into C or to learn C. I have made many projects in the language, one is in the works, namely askthing. I taught C at school in the form of a club. 2 of my \u0026ldquo;students\u0026rdquo; are now programming in C for fun and enjoying it. I also taught Python at school, 19 students fully understood my course and I am now able to teach them more complex topics this school semester :) I wrote a grand total of 3 IGCSE comp sci guides (find them under the revision tab of my site), the Pseudocode Reference, the G1 Semester 2 guide I wrote last may, and the G2 semester 1 guide that I wrote this year, along with an abridged version with G1. My ThinkPad addiction began in february. I bought way too many ThinkPads. Ended up corebooting all of them, learning BIOS programming was very fun. whatever this is. I learned and actually got pretty good at the zig programming language. Although my skills have gotten rusty :( I can confidently write a lexer for literally anything, although I still have to learn how to do recursive-descent parsing properly. Stay tuned. I made so many friends :) They are all supportive, and are very sweet people (maybe not why 16 is sweet). I found community in the computer nerd group at my school, and in the Minecraft community I am in (Sitaku); I am relied on to build core infrastructure in our humongous city/nation. I made some other silly projects, like tpfanctl to control ThinkPad fan speeds. Got better at raylib. Got better grades in school, slightly. Other stuff. I can\u0026rsquo;t remember, for me these achievements make me happy enough. Thank you for reading this post, this blog site actually expanding also makes me very happy. Thank you, all my readers and my supporters (there are a few that I am aware of), I wish you have a wonderful day.\n","permalink":"http://ezntek.com/personal/nothings-sweet-about-16-20250109t0730/","summary":"\u003ch2 id=\"note\"\u003eNOTE\u003c/h2\u003e\n\u003cp\u003eAm I a tech nerd who blogs about technical stuff? YES!\u003c/p\u003e\n\u003cp\u003eBut do I have a life? yes. \u003cem\u003e\u003cstrong\u003eThis post is not technical\u003c/strong\u003e\u003c/em\u003e, and I will only continue writing this format when I feel like it.\u003c/p\u003e\n\u003cp\u003eScroll down if you wish.\u003c/p\u003e\n\u003ch2 id=\"a-long-time-ago\"\u003eA long time ago\u0026hellip;\u003c/h2\u003e\n\u003cp\u003eWhen I was 11 or 12 or so (back in 6th grade), I had one of the most amazing math teachers ever. She was great at her job, but most importantly, every time the class and her had an interaction everybody would burst out in happy laughter; there was never one negative moment in that room.\u003c/p\u003e","title":"Nothing's Sweet About 16"},{"content":"Introduction yes I really should clean it. shhh!\nThis is the story of how I librebooted my ThinkPad T480, less than 24 hours after support was added to lbmk\u0026rsquo;s tree.\nNote that this is not meant to be a comprehensive tutorial! Please always read the official documentation if you want to carry out this process for yourself, the steps for you and I will not necessarily be the same (as I had to build the ROM from source).\nIf you want to follow along with what I do, that is fine; I will provide generic instructions, but this is not a way of me saying that you should not check out the official docs here!.\nFor some of my own quirks while using libreboot, go here\nBackstory Some legendary figure called Mate Kukri wrote this to exploit a bug in the Intel Management Engine (you can read up on why it is evil here). Originally, it was just for a Dell OptiPlex desktop (if I remember correctly), and it abused a bug in the ME firmware to allow for arbitrary code execution (which allows one to disable Intel Boot Guard, therefore allowing me_cleaner and coreboot).\nHe ported it to the T480 after a little rewrite a few days ago, which is why he got this working (this was my genuine reaction I posted to my friends):\nHowever, this commenter revealed that it was already in the libreboot tree, only after a day or two. Maybe leah rowe is just magic.\nSupplies you need:\na SOIC-8 clip. Some sort of thing that allows you to run a serial programmer on it. I used a Raspberry Pi Pico W for this, I just had it lying around one day.\nAny Philips-head screwdriver. Not too small, not too big, use what is sensible and available to you.\nA spudger, it is generally good to have one, but you could use your nails if you are careful.\nUpdate the stock BIOS The process is relatively simple. I assume that you are already on some Linux distribution or a BSD, if you are on Windows, you can do it via the EXE file.\nHead over here, and choose the ISO download.\nIf you have a DVD/CD burner, just use something like xorriso or cdrecord to burn the ISO to a CD, and you\u0026rsquo;re good\nOPTIONAL: using a USB stick I assume that not many of you have blank DVDs/CDs lying around, along with a reader. To write the ISO to a USB, you must extract the El Torito image within the ISO, as it is not a hybrid ISO that can be dded to a USB stick.\nGo to this link and fetch the geteltorito.pl script, and save it somewhere on your computer. Then, make it executable. The below commands does this:\ncurl -fL -o geteltorito https://raw.githubusercontent.com/rainer042/geteltorito/refs/heads/main/geteltorito.pl chmod +x geteltorito Then, extract the El Torito image by running the utility, like so:\n./geteltorito -o t480_bios_update.img /path/to/your/downloaded.iso Do replace the downloaded ISO path with the actual path to your ISO.\nWrite it to a USB stick however you want, I use dd:\n(this command should be as root)\ndd if=t480_bios_update.img of=/dev/sdX bs=4M conv=fsync status=progress where sdX is your storage device.\nBooting the BIOS updater Apologies for the lack of images!\nMake sure that you allow the BIOS to be end-user-flashed in the stock BIOS, and also enable legacy boot.\nBoot from the device stick by spamming \u0026lt;F12\u0026gt; and choose the appropriate entry. Make sure you have at least one battery in your system charged, and the AC connected! The program will not let you continue if you do not have both of those things satisfied.\nSelect Option 2, and follow the instructions. Your computer will reboot into a flash utility, make sure you do not unplug your BIOS update storage device!\nIt should look something like so:\nWhen you have rebooted your machine, you\u0026rsquo;re good.\nDumping the stock BIOS It generally is a good idea to have a backup of the stock BIOS, unless if things go seriously wrong. If you are somehow following this \u0026ldquo;guide\u0026rdquo; to coreboot your machine, you will need that as a part of the build process (but not for libreboot!)\nWiring the flasher This will vary depending on the microcontroller/flashing device you use. For the Pi Pico and Pico W, you must have pico-serprog installed on it first.\nTo wire the SOIC-8 to the programmer, use the following diagram:\nPink corresponds to the pin on the Raspberry Pi, Bright red indicates the pin number on the chip and the dark red indicates what the pin is.\nHere\u0026rsquo;s a table:\nChip Pin Chip Pin Number Raspi Pin Raspi GPIO Pin number CS 1 GP5 7 MISO 2 GP4 7 WP 3 Unused Unused GND 4 GND 38 MOSI 5 GP3 5 CLK/SCK 6 GP2 4 HOLD 7 Unused Unused VCC 8 3V3 36 After wiring, they form this, what I\u0026rsquo;d like to call my BIOS flashing jig.\nThe back sohuld look something like this:\nTaking some dumps No, not excretion.\nNOTE: flashrom. Libreboot standardizes on flashprog, but I cannot find a good reason as to why leah does this (I was on IRC yesterday, somebody brought it up but to my knowledge, leah did not respond).\nConnect the flasher to the chip, simply press on the plastic portion of the SOIC-8 clip open, and make sure the bottom portion of the clip is completely flush with the board, with all pins contacting the chip.\nONLY THEN, do you connect the power. NEVER CONNECT YOUR FLASHER TO YOUR COMPUTER BEFORE CONNECTING THE CLIP TO THE CHIP! YOU MIGHT FRY YOUR CHIP!\nDetermine the model of flash chip you have. I have a Winbond W25Q128.V, but you may have a macronix chip. Use your phone\u0026rsquo;s flash to take a zoomed in picture of the chip, and try to decipher the code.\nIssue the flashrom command. As root:\nflashrom -p yourprogrammer -c \u0026#34;your chip model\u0026#34; -r t480_stockbios_1.bin Since I use a raspberry pi pico and pico-serprog, and I have a W25Q128.V chip, I issued\nflashrom -p serprog:dev=/dev/ttyACM0 -c \u0026#34;W25Q128.V\u0026#34; -r t480_stockbios_1.bin Repeat until you have 3 dumps. Change the filename between dumps, i.e. -r t480_stockbios_1.bin to -r t480_stockbios_2.bin, etc.\nRun the following command:\nsha256sum t480_stockbios*.bin you should see some checksums, like so:\na7742cedf85706cafad984e555c0dc3dda9854855fcd131aadb4dd92a320ab00 t480_oldbios_a.bin a7742cedf85706cafad984e555c0dc3dda9854855fcd131aadb4dd92a320ab00 t480_oldbios_b.bin a7742cedf85706cafad984e555c0dc3dda9854855fcd131aadb4dd92a320ab00 t480_oldbios_c.bin If they are not all identical, remove all of your dumps and try steps 3-5 again until all your checksums match. this is to make sure you have 3 clean dumps.\nCompiling with lbmk NOTE: you might as well use the libreboot docs for the T480 and inject vendor firmware into a prebuilt tarball. As of writing this, release 20241206 is already out, which has T480 binaries. Even if you want to build a rom with lbmk, you might as well use the docs. They are really good! This section will highlight my unique experiences, becuase I compiled the rom before leah even released the tarballs.\nNOTE: go here to skip compilation to the part where I change the MAC address\nThings began simple. I just cloned lbmk:\ngit clone https://codeberg.org/libreboot/lbmk cd lbmk and followed the instructions on the site.\nI had used lbmk before, so I did not need to ./mk dependencies arch (I was building on my Artix god-PC, with an i7-14700KF. I really did not want to build it on one of my older ThinkPads).\nLike a good and sane person who likes reading the f*****g manuals™, I read the f*****g manuals™.\nThis is what the guide said after I read all the other sections:\nBuild ROM image from source The build target, when building from source, is thus:\n./mk -b coreboot t480_fsp_16mb ./mk -b coreboot t480s_fsp_16mb NOTE: The T480 and T480S may be similar, but they do have several critical differences in their wiring, so you MUST flash the correct image. Please choose one of the above build targets accordingly.\nI was aware of the pitfalls, like no thunderbolt, no brightness keys, etc. But due me having done all this prep (and me generally loving libreboot as a project), I continued anyways.\nI issued\n./mk -b coreboot t480_fsp_16mb as I was told. Things went smoothly.\n\u0026hellip;until I hit this error.\n--- TRUNCATED --- Not a supported Inno Setup installer! Done with 1 error. Dell PFS Update Extractor v6.0_a16 *** df735a24242792bf4150f30bf0bd4fdbdc0fb6bf0f897ea533df32567be8e084006d692fb6351677f8cc976878c5018667901dbd407b0a77805754f7c101497c Extracting Dell PFS 1 \u0026gt; df735a24242792bf4150f30bf0bd4fdbdc0fb6bf0f897ea533df32567be8e084006d692fb6351677f8cc976878c5018667901dbd407b0a77805754f7c101497c \u0026gt; Firmware Done! config/data/deguard/mkhelper.cfg missing Downloading project \u0026#39;deguard\u0026#39; to \u0026#39;src/deguard\u0026#39; src/deguard missing fatal: repository \u0026#39;/home/ezntek/Sources/apps/lbmk/cache/repo/deguard\u0026#39; does not exist ERROR script/trees: !clone /home/ezntek/Sources/apps/lbmk/cache/repo/deguard /home/ezntek/Sources/apps/lbmk/tmp/gitclone Cached clone failed; trying online. Cloning into \u0026#39;/home/ezntek/Sources/apps/lbmk/tmp/gitclone\u0026#39;... remote: Total 181 (delta 0), reused 181 (delta 0) Receiving objects: 100% (181/181), 62.47 KiB | 120.00 KiB/s, done. Resolving deltas: 100% (46/46), done. HEAD is now at de176a7 Add note about DCI bit Applying: t480s delta Traceback (most recent call last): File \u0026#34;/home/ezntek/Sources/apps/lbmk/src/deguard/./finalimage.py\u0026#34;, line 76, in \u0026lt;module\u0026gt; with open(args.input, \u0026#34;rb\u0026#34;) as f: ^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [Errno 2] No such file or directory: \u0026#39;/home/ezntek/Sources/apps/lbmk/tmp/me.bin\u0026#39; ERROR ./vendor: Error running deguard for /home/ezntek/Sources/apps/lbmk/vendorfiles/t480/me.bin ERROR ./vendor: Error running deguard for /home/ezntek/Sources/apps/lbmk/vendorfiles/t480/me.bin ERROR script/trees: Unhandled non-zero exit: ./vendor download t480_fsp_16mb ERROR ./mk: excmd: script/trees -b coreboot t480_fsp_16mb Alright I guess. It complained about missing vendor files such as the ME. maybe I had to extract it with ifdtool?\n\u0026hellip;so I ran ifdtool --platform sklkbl -x wherever/the/bios/was.bin\nand copied flashregion_2_intel_me.bin to vendorfiles/t480. But then it gave me a new error.\n(sorry for not having a proper text log for it, I couldn\u0026rsquo;t find the pastebin paste I had it on :/)\nThe ME region was too big. At this point, I was completely confused and dumbfounded; which is why I took to IRC.\nNOTE: go here to skip my encounters on IRC\n#libreboot on libera.chat: oh dear On the libreboot website, they recommended people to come to #libreboot on IRC for help\u0026hellip;which is what I did. FYI, I almost never use IRC (although I am planning to become more active on IRC networks).\nI expected at least a slightly nice greeting from the IRC people, but that was when I found out that these people are RTFMers. Mad respect for that, but I already read the manual(s) back to back for each applicable thing, and I was sure I knew what I was doing.\nHere were the things they told me:\nRTFM (but I already did!) Install dependencies (but I already installed them!) Install dependencies again (but I just did a full system update?) I think at that point, everyone was clueless. I could tell that fuel (a mod) was a bit clueless and started asking leah. They did eventually discover that I used Artix and not arch, and they immediately denied further assistance (expected, they are 2 different distros, arch supported and Artix not).\nBut I was still skeptical. Those distros literally share the same repos (at least I made it do so), and I have successfully used lbmk on Artix once or twice before. Still, no luck.\nPSA Don\u0026rsquo;t paste raw output on IRC! horrible idea, you will get people barking at you. I did not know, but they could have reminded me a little better (because I am not an IRC user!!)\nJust use pastebin—\nBack to IRC shenanigans They began telling me to try it on debian. I said that I did not want to and I was certain that my distro was not the problem. They insisted. Alright, I would try on debian sid. No luck! I got missing candidate errors (my favorite!).\nI then started bargaining, which really does make sense in this case. Sure, it is an unsupported distro, but why are the dependencies causing me.bin to not be present? the typical process for obtaining any ME dump would be\nsomehow get an official BIOS image (in this case, download) chop the rom up to extract the binary copy it to vendorfiles/t480 Why would the dependencies (like GCC libraries and other coreboot dependencies) matter? The process would literally just be\ncurl -fL -o bios.bin https://some.shady/link magicalextractionutility -o me.bin bios.bin cp me.bin vendorfiles/t480 I suspected that the magical extraction utility would be bundled with coreboot. They did say no, however (which is true, but one utility that is used, innoextract was in the dependencies).\nThey then told me void was a supported distro, so I tried it again. Same error.\nat that point, even leah became confused, so they decided it was a good idea to clone a fresh lbmk tree1.\nTurns out they made a commit that tried to do a shortcut to copy me.bin, but that didnt work! one local git revert later, it built!\nBack to compiling libreboot Libreboot does not provide a MAC address for the Gigabit Ethernet (gbe) ROM, which means that you cannot have many librebooted machines on the same network. Therefore, it is advised to change it.\nLibreboot has documentation for this.\nThis is the process:\nHave ifdtool and nvmutil compied somewhere ifdtool --platform sklkbl -x libreboot.rom to extract the gbe region nvm flashregion_3_gbe.bin setmac aa:bb:cc:dd:ee:ff where aa:bb:cc:dd:ee:ff. I recommend you take the first 3 parts of the MAC address, but leave the rest as ??, like so:\nnvm flashregion_3_gbe.bin setmac aa:bb:cc:??:??:?? To keep the correct network card vendor, but change the device specific address. I did not do this, but I will the next time I flash the computer.\nFlash! This process will take a while, as flashrom does not tell you when it starts writing the flash chip. Run the following as root:\nflashrom -p yourprogrammer -c \u0026quot;your chip model\u0026quot; -w your_libreboot_variant.rom\nAnd make sure your chip clip is sat on the chip tightly! If the bottom of the clip appears to not have crimped the chip at the very bottom anymore, but has slid up and crimpeed the top, that means your clip is about to die, and you have to hold the chip clip in place after you put it on, and press down with force to make sure it does not fly off.\nUsage report That is about as simple as librebooting gets.\nIn terms of using the T480 (for buyers who want to try it out):\nCPU performance is good. I recommend the i5-8350U, as it has the best CPU performance to price ratio, if buying used. It will be a large jump from a haswell/ivy bridge M series dual core i5 and a relatively good jump from a dual core i7.\nIf you are using a quad-core i7 (MQ or QM series chip from Ivy Bridge/Haswell), the performance boost is not very noticeable and is marginal. Either way, power efficiency will skyrocket, as these are U series chips after all.\nGet 16GB of RAM: tihs is basically a given, make sure you have at least 16. 8 will bottleneck the CPU, and 32 is too much for ost tasks.\nIf youre lucky and get a T480 with the 2280 SSD bracket, you will see a boost in disk speeds, but if you only do tasks such as office work/programming, a normal SATA SSD will have an identical performance. If you want, you can put an M.2 A+E key 2242 SSD into the WWAN slot for extra storage.\nAVOID TN PANELS LIKE THE PLAGUE: If buying used and you are not planning to upgrade the panel, please avoid the TN panels, because they will make your T480 experience horrendous and near unbearable. I recommend the following panels if you upgrade it:\nNE140FHM-N62: no mounting brackets, has enough clearance and is 96%DCI-P3 (1.07 billion colors!), 30 pin eDP, non-touch, IGZO low power, 500 nit and is 1920x1080. It should have 60 and 48hz support. I have not tested it, but in theory this should be the best panel. NE140FHM-N61: no mounting brackets, has enough clearance and is 100%sRGB, 30pin eDP, non-touch, IGZO low power, 400 nit and is 1920x1080. Supports 60 and 48hz and is quite bright. I have tested this one. N140HCG-GQ2/GR2: no mounting brackets, has enough clearance, 100%sRGB, 30pin eDP, non-touch, IGZO, has pretty damn bad backlight bleed, is 400 nit but quite dim, and is 1920x1080. I have tested this one. B140HAN01.0/.1/.2/.3: has mounting brackets, has enough clearance, and is 45%NTSC, 30pin eDP, non-touch, not low power, 250~300 nits and is 1920x1080. Colors are quite washed out and is okay-bright. All \u0026ldquo;compatible\u0026rdquo; panels are acceptable, much better than a TN. I have tested the B140HAN01.3 and the N140HCE-EAA (a compatible). you could go for more exotic options, including 2.5k panels like the B140QAN02.0 (which I used, but swapped out, because it has clearance issues and creates 2 bulges on the bezel. Colors are amazing though) or 4k ones. Any panel higher than 1080p requires a 40 pin cable; and swapping the cable out is quite painful as you have to disassemble the hinge.\nDo the glass trackpad mod if you like using the trackpad.\nMake sure you have the internal battery! the PowerBridge system is extremely useful, and even if you do not intend to hotswap batteries, the extra mileage you get is quite important at times. I have a 72wH (in reality, 68 due to it being aftermarket) external 6 cell and an internal 24Wh 3 cell, which gives me 9 total cells around ~90wH. My T480 did not even come with an internal battery because Lenovo did not ship these batteries in colder countries due to chemistry™ reasons.\nFor daily tasks, the T480 smashes all of them, and most definitely can handle video editing, even with just the iGPU. Speaking of which, it gets over 80fps on 22 ren/22 sim chunks medium settings with sodium in a Minecraft Singleplayer world. It is portable, quite light, definitely 1-handable and is a great daily driver.\nThe keyboard does only have ~1.8-2mm of travel, which is unlike the classic keyboards and first gen island keyboards on Ivy Bridge ThinkPadswhich have anywhere between 2 and 2.3mm of travel. There are 3 T480 keyboard manufacturers:\nLiteOn (FRU 01HX459 for backlit): This one has the snappiest keyfeel, relatively short travel and slightly MacBook keyboard like, but still very comfortable to type on. The bottom-out is quite harsh. Chicony (FRU 01HX419 for backlit): This one is soft but not too soft, has a shorter tactile peak that is more drawn out, and is not that heavy. Travel is definitely deeper than the LiteOn but still with a hard bottom-out. Darfon (FRU 01HX449 for backlit): This one is the worst, mushy, not very tactile and keytravel is not that long either. I definitely do not recommend this one, either go with Chicony if you want the more balanced option or LiteOn if you want a snappier keyfeel. I personally use the LiteOn and have used the chicony, and do prefer the LiteOn simply because of the tactile bump. If you have ever tried to do the classic keyboard mod, LiteOn is the equivalent to the NMB keyboards, the best-regarded within the community; and LiteOn and NMB are related (I think one bought the other, or one NMB used LiteOn switches in their classic keyboards, because apart from the keytravel, they feel very similar).\nSome libreboot quirks thinkpad_acpi does not load correctly, just like on haswell ThinkPads. You must put the following:\noptions thinkpad_acpi force_load=1 inside a file named anything inside /etc/modprobe.d for the module to load correctly on boot. Else, you do not get temperature monitoring and fan control.\nAs per the T480 libreboot page, thunderbolt does not work as of now, and the brightness keys do not register keysyms within Linux. The settings, bluetooth, kekyboard and star keys on top of F9-F12 register a NoSymbol keysym within wev.\nSuspend works as expected.\nBluetooth is slightly wonky, as it does not automatically turn on, at least for Void Linux; despite the service being enabled. Sometimes I have to restart the bluetooth service (with doas sv restart bluetoothd) to get things to work. Auto-pairing also does not work.\nThe installation process is far easier than compiling a custom coreboot payload (duh)\nleah added support for UEFI through U-boot, which means that you can do an EFI install of linux (I still use good-ol\u0026rsquo; BIOS boot).\nnot just normal confused, leah was quite pissed off because they were trying to port libreboot to Alder lake motherboards, but things were going well.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/posts/librebooting-the-thinkpad-t480-20241207t0933/","summary":"\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cimg src=\"/img/lb_t480/glory.jpg\" alt=\"glorious!\" width=\"100%\" /\u003e\n\u003cp\u003e\u003cem\u003eyes I really should clean it. shhh!\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThis is the story of how I librebooted my ThinkPad T480, less than 24 hours after support was added to \u003ccode\u003elbmk\u003c/code\u003e\u0026rsquo;s tree.\u003c/p\u003e\n\u003cp\u003eNote that \u003cem\u003e\u003cstrong\u003ethis is not meant to be a comprehensive tutorial!\u003c/strong\u003e\u003c/em\u003e Please always read the official documentation if you want to carry out this process for yourself, the steps for you and I will not necessarily be the same (as I had to build the ROM from source).\u003c/p\u003e","title":"Librebooting the ThinkPad T480"},{"content":"DOWNLOAD The OFS IGCSE Computer Science G1 Guide to Programming and Logic Gates, Revision Three What is this? I have already released this guide for the G2 students, and since your examination has so much overlap with mine, I have abridged my guide to make it so that you can use some content for your exam as well.\nThis guide covers:\nThe programming stuff The logic gate stuff This guide doesn\u0026rsquo;t cover:\nSystems lifecycle stuff The binary and data representation stuff I don\u0026rsquo;t have time to write anything extra for you, please remember to use your own notes too! I am not liable.\n","permalink":"http://ezntek.com/posts/the-ofs-igcse-computer-science-g1-guide-to-programming-and-logic-gates-20241106t0845/","summary":"\u003ch2 id=\"download\"\u003eDOWNLOAD\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://ezntek.com/doc/CSRG_G1_Rev3.pdf\"\u003eThe OFS IGCSE Computer Science G1 Guide to Programming and Logic Gates, Revision Three\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"what-is-this\"\u003eWhat is this?\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"Cover\" loading=\"lazy\" src=\"/img/csrgg1cover.png\"\u003e\u003c/p\u003e\n\u003cp\u003eI have already released \u003ca href=\"https://ezntek.com/posts/the-ofs-igcse-computer-science-g2-exam-revision-reference-guide-20241105t2152/\"\u003ethis\u003c/a\u003e guide for the G2 students, and since your examination has so much overlap with mine, I have abridged my guide to make it so that you can use some content for your exam as well.\u003c/p\u003e\n\u003cp\u003eThis guide covers:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe programming stuff\u003c/li\u003e\n\u003cli\u003eThe logic gate stuff\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003eThis guide doesn\u0026rsquo;t cover:\u003c/strong\u003e\u003c/em\u003e\u003c/p\u003e","title":"The OFS IGCSE Computer Science G1 Guide to Programming and Logic Gates DOWNLOAD"},{"content":"DOWNLOAD The OFS IGCSE Computer Science G2 Exam Revision Reference Guide, Revision Four After much anticipation\u0026hellip; It is finally ready, yes, the new CSRG!\nThe TRUE Sequel to the previous one (you can find it here), where I wrote a ~40 page reference to all the topics that would be covered in the upcoming exam.\nHowever, that only did so much; this semester we are being tested on a crap ton of stuff:\nEmerging Technologies 1 Expert Systems and machine learning and stuff Automated systems and stuff robots and stuff Logic gates lotsa lotsa gates lotsa lotsa diagrams lotsa lotsa truth tables lotsa lotsa expressions and stuff programming some other stuff i think ..which is why the new 75 page guide aims to address all these topics. Read the PDF for more information!\nCheck out this article for more info as to why I hate the IGCSE examiners so much. Of course they have to have a unit on emerging technologies; it is completely useless and bull\u0026hellip;crap!\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/posts/the-ofs-igcse-computer-science-g2-exam-revision-reference-guide-20241105t2152/","summary":"\u003ch2 id=\"download\"\u003eDOWNLOAD\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://ezntek.com/doc/CSRG_G2_Rev4.pdf\"\u003eThe OFS IGCSE Computer Science G2 Exam Revision Reference Guide, Revision Four\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"after-much-anticipation\"\u003eAfter much anticipation\u0026hellip;\u003c/h2\u003e\n\u003cp\u003eIt is finally ready, \u003cem\u003e\u003cstrong\u003eyes, the new CSRG\u003c/strong\u003e\u003c/em\u003e!\u003c/p\u003e\n\u003cimg src=\"/img/newcsrgcover.png\" width=\"100%\" /\u003e\n\u003cp\u003eThe \u003cem\u003eTRUE\u003c/em\u003e Sequel to the previous one (you can find it \u003ca href=\"/posts/comp-sci-revision-20240509t0944\"\u003ehere\u003c/a\u003e), where I wrote a ~40 page reference to all the topics that would be covered in the upcoming exam.\u003c/p\u003e\n\u003cp\u003eHowever, that only did so much; this semester we are being tested on a crap ton of stuff:\u003c/p\u003e","title":"The OFS IGCSE Computer Science G2 Exam Revision Reference Guide DOWNLOAD"},{"content":"Important Information! If you actually take IGCSE comp sci, ignore everything I say, because the examiners love seeing overcommented code for whatever reason, and they will even give you subjective marks based on if they think there are enough comments or not.\nTo them, \u0026ldquo;well commented code\u0026rdquo; is of higher quality, despite if 80% of the code is just paragraphs and paragraphs talking about the meaning of life.\nYes, I do have beef with these people. Write better code, comments are not an excuse to write bad code!\nThe Problem People are overcommenting their code nowadays; we are even taught to do this due to the stupid IGCSE Examiners giving marks for \u0026ldquo;good\u0026rdquo; commenting practices 1. Here\u0026rsquo;s an example from our computer science teacher:\nTo me, this looks like a completely fine set of code. I was asked by my teacher (because I think he knows that I\u0026rsquo;m quite the Good Programmer and he wanted my input). I said that:\nThe code looks completely fine to me, its good enough, readable, all I would do is run the code through a formatter and rename the variables.\nInstead, I was told that I was Wrong for saying that, and that this was a badly written program. The biggest problem that was highlighted to me was that there were no comments, and therefore the program was unmaintainable.\n(Written by my Comp Sci teacher)\nI do agree that that having better variable names is objectively better, but this is clearly an example of overcommenting.\nWhy not comment? Consider this code:\n# grab the response after the message is sent r = send_message(m) # check if the message sent correctly if r.status() == 9: # mark as sent m.sent = True Adapted from CodeAesthetic\u0026rsquo;s Video\nAll these variable names, m, r, and the random 9 floating around isn\u0026rsquo;t very legible to anyone else who may be maintaining your code.\nThis is why there are many comments explaining what my code does. Future maintainers of my code would ideally read those comments and understand what the code is doing.\nBut do we really need all this many comments? If your code is unreadable and you need comments to fix it, why not just adapt the code?\nWe could easily rewrite this section like so:\n# ...somewhere at the top of the file MESSAGE_SENT = 9 # ...later response = send_message(msg) if response.status() == MESSAGE_SENT: message.sent = True Now the code reads itself. Everything is clear, and the code is self commenting; it reads like natural human language.\nHere\u0026rsquo;s another example:\ndef get_time_from_server(server): response = request_for_time(server) if response.status == 1: return -1 else: return response.result Now what happens if you didn\u0026rsquo;t have access to the contents of this function (if this were in a library); how would you know what the format of \u0026ldquo;server\u0026rdquo; should be, is it a list of values for an IPv4 address, is it an URL or URI, is it a string or a custom class? And how do you know what the return values mean?\nHere\u0026rsquo;s the naïve solution implemented with some ✨comments✨\n# grabs the time from a server. # the server argument takes in a tuple with 4 integers, # representing an IPv4 address. def get_time_from_server(server): response = request_for_time(server) # If the value is 1, return -1 to mean an error if response.status == 1: return -1 # return the actual result else: return response.result Unclean, right? Here\u0026rsquo;s some issues:\nNow what happens if the server actually sends -1 as some useful value, like representing a server-side error; would the caller of the function even know? What happens if we want to support IPv6? The parameter type would completely change, but if we forget to update the comment in a rush, that wouldn\u0026rsquo;t be very nice for the caller, right? We are, again, rewriting the code itself in English, which provides no extra worth to the reader.2 Here\u0026rsquo;s how I would fix it:\nIPv4Address = tuple[int, int, int, int] def get_time_from_server(server: IPv4Address) -\u0026gt; int | None: response = request_for_time(server) if response.status == 1: return None else: return response.result Now the function is a lot clearer, even without comments. Here, we use types to make it clear to the caller what data is supposed to come in and out, without ever needing to consult documentation (although that\u0026rsquo;s a bad idea!)\nThe only other thing that I would do in this case would be to annotate what None represents, i.e.\nIPv4Address = tuple[int, int, int, int] # returns None if there\u0026#39;s an error def get_time_from_server(server: IPv4Address) -\u0026gt; int | None: response = request_for_time(server) if response.status == 1: return None else: return response.result but again, we could just make a type alias.\nExample Refactor Looking at the above example from my Computer Science Teacher, here\u0026rsquo;s the before:\nx = int(input(\u0026#34;Enter a number: \u0026#34;)) y = int(input(\u0026#34;Enter a number: \u0026#34;)) f1 = [] for i in range(x, 0, -1): if x % i == 0: f1.append(i) f2 = [] for i in range(y, 0, -1): if y % i == 0: f2.append(y) i = 0 while f1[i] not in f2: i += 1 print(\u0026#34;The GCF of\u0026#34;, x, \u0026#34;and\u0026#34;, y, \u0026#34;is\u0026#34;, f1[i]) Messy, right?\nYou could tell which part of the program does that, though:\nthe first portion of the code that deals with f1 gets all the factors of x. the second portion of the code that deals with f2 gets all the factors of y the last portion of the code checks each factor of f1 and sees if it\u0026rsquo;s also a factor of f2. Since the list is in reverse order, i.e. largest factor goes first, the first common factor it finds should be the greatest. But this is quite hard to decipher for a person that doesn\u0026rsquo;t know the algorithm; let\u0026rsquo;s refactor it.\nx = int(input(\u0026#34;Enter a number: \u0026#34;)) y = int(input(\u0026#34;Enter a number: \u0026#34;)) x_factors = [] for possible_factor in range(x, 0, -1): if x % possible_factor == 0: x_factors.append(i) y_factors = [] for possible_factor in range(y, 0, -1): if y % possible_factor == 0: y_factors.append(y) index = 0 while x_factors[i] not in y_factors: index += 1 print(\u0026#34;The GCF of\u0026#34;, x, \u0026#34;and\u0026#34;, y, \u0026#34;is\u0026#34;, x_factors[index]) The identifier names make it a bit easier to understand. Now the reader of the code can understand that the first part is at least related to finding the factors of a number.\nHowever, we can do better; since these are all repeatable and generic sections of code, we might as well extrapolate them into functions and use an f-string:\nx = int(input(\u0026#34;Enter a number: \u0026#34;)) y = int(input(\u0026#34;Enter a number: \u0026#34;)) def get_factors(num: int) -\u0026gt; list[int]: result = [] for possible_factor in range(num, 0, -1): result.append(possible_factor) return result def get_gcf(num1: int, num2: int) -\u0026gt; int: factors_num1 = get_factors(num1) factors_num2 = get_factors(num2) index = 0 while factors_num1[index] not in factors_num2: index += 1 result = factors_num1[index] return result gcf = get_gcf(x, y) print(f\u0026#34;the GCF of {x} and {y} is {GCF}\u0026#34;) Now what makes this code so much better than before?\nTypes: It is so much easier to track the flow of data simply by noting down the types. It is also easier to run type-specific operations on parameters as you know for sure what the type is and don\u0026rsquo;t need to backtrack. Good identifier names: Now the code reads like human language! There are no weird array indexes, all lines have some sort of human-legible meaning to them. No redundant comments: There are no comments, as the code simply reads like English, given that you know how Python Syntax works. Notice how there\u0026rsquo;s no need for comments to explain what the code does?\nNow, let\u0026rsquo;s say if we changed the algorithm in the future. If we had used comments, they may slowly become outdated and not reflect what the code says. If we write our code in more human-friendly form with nicer identifiers, the code immediately gets clearer, just by reading function names. When should I comment? In the previous example, I (or my teacher) uses a set algorithm to get the greatest common factor, some widely-known set algorithm that doesn\u0026rsquo;t need to be changed. If we were trying to teach how that algorithm worked; this would be a sub-optimal example:\n# Grab the greatest common factor between 2 integers def get_gcf(num1: int, num2: int) -\u0026gt; int: # Get the factors of both numbers factors_num1 = get_factors(num1) factors_num2 = get_factors(num2) # Define an index index = 0 # Keep iterating through the first list while there a given # factor is not in the other list while factors_num1[index] not in factors_num2: index += 1 # when we find the common factor, return it to the call # site result = factors_num1[index] return result We are annotating as to what the code does. That\u0026rsquo;s bad; as programmers we know the syntax of the language we program in, why is there a need to rewrite the syntax?\nThis still doesn\u0026rsquo;t help your understanding of the algorithm; one could ask:\nWhy are we iterating through one list and checking it with the other; wouldn\u0026rsquo;t the condition be met on the first iteration because both lists are in ascending order?\nAnd other such questions. A better way to comment your code could be:\ndef get_gcf(num1: int, num2: int) -\u0026gt; int: # both lists are in descending order factors_num1 = get_factors(num1) factors_num2 = get_factors(num2) index = 0 # the lists are in reverse, biggest goes first, so the # first hit would be the greatest common factor. while factors_num1[index] not in factors_num2: index += 1 result = factor_num1[index] return result Instead, we use comments here to provide missing information that is not immediately clear; it says why the code is written in a certain way.\nThe takeaway Commenting is bad; there is always some way to make your code cleaner and more organized without comments. The only times where you should comment is to say why the code is there, not what it does. Commenting is not an excuse to write bad code, write good code that reads itself later on.\nComments can lie, any compiler/interpreter or even linter will not statically analyze your comments to see if they match your code. However, code doesn\u0026rsquo;t lie, because it has to follow rules. There is no use for commenting if there is a tool that can tell if your code is correct or not.\nOne of the many reasons as to why I have beef with the examiners.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nBefore you bring up how beginner programmers who are not good at programming will not be able to read this, that is their problem. Code is meant to be read by programmers, they should learn how to code well before they try to decipher other people\u0026rsquo;s code as in trying to work with them.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"http://ezntek.com/posts/dont-write-comments-write-better-code-20241105t2141/","summary":"\u003ch2 id=\"important-information\"\u003eImportant Information!\u003c/h2\u003e\n\u003cp\u003eIf you actually take IGCSE comp sci, ignore everything I say, because the examiners love seeing overcommented code for whatever reason, and they will even give you subjective marks based on if they think there are enough comments or not.\u003c/p\u003e\n\u003cp\u003eTo them, \u0026ldquo;well commented code\u0026rdquo; is of higher quality, despite if 80% of the code is just paragraphs and paragraphs talking about the meaning of life.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eYes, I do have beef with these people. Write better code, comments are not an excuse to write bad code!\u003c/em\u003e\u003c/p\u003e","title":"Don't Write Comments, Write Better Code!"},{"content":"\nLibreOffice does not know my full name. What a shame!\nDOWNLOAD Revision Seven\nChangelog Revision two fixed minor syntax highlighting errors, and added details to the Python half of the functions section for consistency. Revision three added a License, the CC-BY-SA-ND 4.0 International License. all previous versions are also licensed under the same license, if you have it. Revision four fixed inconsistencies in the notes, and fixed minor syntax highlighting errors. Revision five fixed an error in the for loops section where I iterate from a list beginning from 1 not 0. Revision six fixed errors relating to if statements and arrays. Revision seven contains final fix-ups and rephrasing. What??? Yes, count this as a sequel to my last epic guide, which was for the suffering G1 students under magic man\u0026rsquo;s leadership.\nThis one is for everyone! a FULLY SYNTAX HIGHLIGHTED (manually done with blood sweat and tears!) reference with side-by-side examples of common programming tasks in both Pseudocode and Python. Revision One covers:\ncomments values conditional branching loops procedures functions arrays file handling and more to come if you nicely ask!\nThis is NOT A comprehensive programming guide! Please do not assume that this will actually teach you how to code in-depth! When exam season rolls around, I will be authoring a programming tutorial and a theory reference guide just like last year.\nstay tuned!!!\n(Update as of August 09, 2025: I ended up not finishing the programming guide.)\n","permalink":"http://ezntek.com/posts/the-igcse-pseudocode-to-python-reference-guide-for-g1-and-g2-computer-science-20241018t2049/","summary":"\u003cp\u003e\u003cimg src=\"/img/pseudoguidecover.png\" width=\"100%\"\u003e\u003c/img\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eLibreOffice does not know my full name. What a shame!\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"download\"\u003eDOWNLOAD\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://ezntek.com/doc/pseudocodereference_rev7.pdf\"\u003eRevision Seven\u003c/a\u003e\u003c/p\u003e\n\u003ch3 id=\"changelog\"\u003eChangelog\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eRevision two fixed minor syntax highlighting errors, and added details to the Python half of the functions section for consistency.\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eRevision three added a License, the CC-BY-SA-ND 4.0 International License. \u003cstrong\u003eall previous versions are also licensed under the same license, if you have it\u003c/strong\u003e\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eRevision four fixed inconsistencies in the notes, and fixed minor syntax highlighting errors\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eRevision five fixed an error in the for loops section where I iterate from a list beginning from 1 not 0\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eRevision six fixed errors relating to if statements and arrays\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eRevision seven contains final fix-ups and rephrasing\u003c/em\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"what\"\u003eWhat???\u003c/h2\u003e\n\u003cp\u003eYes, count this as a sequel to my \u003ca href=\"https://ezntek.com/posts/comp-sci-revision-20240509t0944/\"\u003elast epic guide\u003c/a\u003e, which was for the suffering G1 students under \u003cem\u003emagic man\u003c/em\u003e\u0026rsquo;s leadership.\u003c/p\u003e","title":"The IGCSE Pseudocode to Python Reference Guide (for IGCSE G1 and G2 students)"},{"content":"Time for the compiler engineer to manifest\u0026hellip; For the longest time, I have loved compiler engineering.\nIt just sounded so mesmerizing. Being able to take code and analyze it in a multitude of ways to generate something based off of logical reasoning\u0026hellip;all done through an automated program.\nThe possibilities of a pseudocode runtime is endless, I can even self host a compiler on it, eventually!\nOrigins of the idea + Rationale I take 0478 CS at my school.\nMy teacher, Let\u0026rsquo;s call him Magic man. Magic man is quite inexperienced for his profession, he is quite good at teaching all topics but actual programming. He is alright at pseudocode, which is why from day 1, he absolutely obliterated our innocent minds with this mess:\nPROCEDURE CanDrinkBeer(Age : INTEGER) IF Age \u0026gt; 18 THEN OUTPUT \u0026#34;you can drink beer!\u0026#34; ELSE OUTPUT \u0026#34;do not drink beer! ENDIF ENDPROCEDURE DECLARE Age : INTEGER OUTPUT \u0026#34;what is your age? \u0026#34; INPUT Age CALL CanDrinkBeer(Age) (Without types of course. Let us say that he cannot comprehend those very well).\nPuzzle Piece 1 You can\u0026rsquo;t run pseudocode. That is a given, pseudo is in the name.\nSketchy web interpreters and even desktop interpreters exist, such as this one and another one called pcse. However there are some issues.\nNormal programming concenpts cannot even be implemented. Since not all data types are first class citizens, code like so won\u0026rsquo;t even work: PROCEDURE BubbleSort(Data : ARRAY[1:5] OF INTEGER) FOR i \u0026lt;- 1 TO LENGTH(Data) - 1 FOR j \u0026lt;- 1 TO LENGTH(Data) - i - 1 IF Data[j] \u0026gt; Data[j+1] THEN temp \u0026lt;- Data[j+1] Data[j+1] \u0026lt;- Data[j] Data[j] \u0026lt;- temp ENDIF NEXT j NEXT i ENDPROCEDURE DECLARE Data : ARRAY[1:5] OF INTEGER Data[1] \u0026lt;- 5 Data[2] \u0026lt;- 1 Data[3] \u0026lt;- 6 Data[4] \u0026lt;- 9 Data[5] \u0026lt;- 4 CALL BubbleSort(Data) OUTPUT Data In the case of pcse, This code simply complains about a missing assignment operator. Strange.\nI am not even sure if the specification was implemented properly, as omitting the parameter list in a procedure or function doesn\u0026rsquo;t even parse properly. There is a big lack of convenience features. Array initialization syntax, i.e. Array \u0026lt;- [1, 2, 3, 4, 5] Doesn\u0026rsquo;t even exist, one must spell out each index and each value. There are a few more I could come up with, but at the time of writing (I am in class), I can\u0026rsquo;t think of any more reasons.\nPuzzle Piece 2 Cambridge actually has quite a detailed syllabus, where in the 4th section of the document there exists a concretely defined but loosely phrased grammar for the language. This would actually be quite convenient, I would be able to have a guaranteed-to-be-correct and accurate reference to write a parser for.\nThe end? This is just the rationale, and the beginning steps. I really want to get an article out, and I have no clue how this project will grow and progress over time.\nI have already commenced the creation of a more formal grammar for the language. Stay tuned.\n","permalink":"http://ezntek.com/posts/creating-an-igcse-pseudocode-interpreter-pt-1-20240918t1045/","summary":"\u003ch2 id=\"time-for-the-compiler-engineer-to-manifest\"\u003eTime for the compiler engineer to manifest\u0026hellip;\u003c/h2\u003e\n\u003cp\u003eFor the longest time, I have loved compiler engineering.\u003c/p\u003e\n\u003cimg alt=\"A compiler's structure, represented by a cow\" src=\"/img/cowcompiler.png\" width=\"100%\" /\u003e\n\u003cp\u003eIt just sounded so mesmerizing. Being able to take code and analyze it in a multitude of ways to generate something based off of logical reasoning\u0026hellip;all done through an \u003cem\u003eautomated program\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003eThe possibilities of a pseudocode runtime is endless, I can even self host a compiler on it, eventually!\u003c/p\u003e","title":"Creating an IGCSE Pseudocode Interpreter (part 1)"},{"content":"Foreword Yes, this will take you very long to read because this really should have been 5 parts. These reading time calculations are also quite messed up. Not my fault, click away if you don\u0026rsquo;t have patience :p\nRecap As of the last post, I was on day 2, right before the lunch break. I had just (almost) finished writing my article display, and I am now ready to start connecting the API. Everything else works just fine.\nLunch Lunch first before work. However this time, I didnt realyl have too much time on me to properly enjoy lunch sat down sipping my drink, etc. I really had to cook.\n\u0026hellip;well the lunch suited this perfectly. A depressing chicken wrap!\nIt was not far less the length of my schlong when it is active; in layman\u0026rsquo;s terms, around 15 centimeters. The diameter was also miniscule, coming in at around 3-5 centimeters. Overall, a very depressing lunch, but the good thing would be that I was able to shove it in my mouth within ~3 bites, which is great.\nThe final coding session This is where I really felt the energy in the room rising. Tensions were high amongst people who came here to chase excellence, not the complementary Mario Kart stations, myself included.\nWe were to submit our work at 2:15 PM, it was around 1:20 when I returned, Keep that in mind.\nI didn\u0026rsquo;t really have time to deal with any sort of API errors, which majorly backfired later on. I just worked on my recipe cards just a little further.\nAs mentioned in the previous article, the paragraph would cut off outside the recipe bubble, like so:\nTherefore I had to figure out how to chop it off. overflow: hidden; didn\u0026rsquo;t really work that well, so I had to set the max-height, meaning that the page resizing would break, too.\nAfter that, API hell commenced.\nAPI hell I started by making a basic request to\nhttps://api.spoonacular.com/recipes/complexSearch?apiKey=\u0026lt;API Key Goes Here\u0026gt;\u0026amp;ranking=2\u0026amp;number=50\u0026amp;addRecipeInstructions=true\u0026amp;addRecipeInformation=true\nto get a bunch of recipes in JSON format. They displaed just fine on the homepage.\nThen, I got to compiling the API options. List arguments were separated by ,, and each option would be in the format \u0026amp;key=value.\nI started with an empty string:\nlet options = \u0026#39;\u0026#39;; I began with the dietary restrictions, which was simple:\nlet diet = window.localStorage.getItem(\u0026#39;diet\u0026#39;) if (diet === null) { diet = \u0026#39;Non-Vegetarian\u0026#39; } options += `\u0026amp;diet=${diet.replace(\u0026#39;-\u0026#39;, \u0026#39; \u0026#39;).toLowerCase()}` Note that I have to replace - with , which is what the API requires. I set the enum members to enumerate strings in the second post, with dashes for display purposes. But for querying, I had to do the above. I do also set a default just in case the user did not set anything prior, but a settings class would streamline this process of having a default, along with other null-safety things. I didn\u0026rsquo;t have time to mess with TypeScript (a completely foreign language to me) at the time, which is why I just stuck with it.\nI then did the allergies:\nlet intolerances = window.localStorage.getItem(\u0026#39;allergies\u0026#39;) if (intolerances !== null \u0026amp;\u0026amp; intolerances !== \u0026#39;\u0026#39;) { let newOption = `\u0026amp;intolerances=${intolerances.replace(new RegExp(\u0026#39;;\u0026#39;, \u0026#39;g\u0026#39;), \u0026#39;,\u0026#39;).toLowerCase()}` options += newOption } Note the RegExp constructor. I had to construct a RegExp class to properly replace every occurence of ; with g which stood for global, meaning to replace every occurence in a line, not just the first one. (vim users would know).\nI also only do the find and replace only if the intolerances variable\u0026rsquo;s value is set, which honestly could only happen with JavaScript (and therefore TypeScript). Oh well.\nI did the same with the pantry:\n// get pantry from local storage let includeIngredients = window.localStorage.getItem(\u0026#39;pantry\u0026#39;) if (includeIngredients !== null) { let newOption = `\u0026amp;includeIngredients=${includeIngredients.replace(new RegExp(\u0026#39;;\u0026#39;, \u0026#39;g\u0026#39;), \u0026#39;,\u0026#39;).toLowerCase()}` options += newOption } I was then ready to construct the URL:\nlet url = `https://api.spoonacular.com/recipes/complexSearch?apiKey=${apikey}\u0026amp;ranking=2\u0026amp;number=200\u0026amp;addRecipeInstructions=true\u0026amp;addRecipeInformation=true${options}` Simple enough. I then wrote some basic code with the fetch API I just learned (XMLHttpRequest was too old and complicated for me):\ntry { let response = await fetch(url, { method: \u0026#39;GET\u0026#39; }) let result = await response.text() } catch (error) { console.error(error) } which would save the text to the result. Response would return a promise (a future because I\u0026rsquo;m a rust dev), and I\u0026rsquo;d then parse the text and append every new Recipe class to a reactive list (in the try block).\nlet results: Array\u0026lt;AnyObject\u0026gt; = JSON.parse(result)[\u0026#39;results\u0026#39;] results.forEach((recipeObj: AnyObject) =\u0026gt; { recipes.value.push(new Recipe(recipeObj)) }) All of this would be in an async closure, keep that in mind.\nNow, the spoonacular API doesn\u0026rsquo;t actually randomize the recipes that it gets, only by relevance. I didn\u0026rsquo;t know that, so I set the load more button on the bottom of the page to just run this callback again, which would result in the recipes duplicating.\nNot good. So I decided to actually clear the array of recipes when the user hit the load more button, and load, say, 20 more recipes than the previous number of recipes.\nThe code should have looked like this:\nlet results: Array\u0026lt;AnyObject\u0026gt; = JSON.parse(result)[\u0026#39;results\u0026#39;] recipes.value = [] results.forEach((recipeObj: AnyObject) =\u0026gt; { recipes.value.push(new Recipe(recipeObj)) }) but instead, on my initial run, I got ratelimited. I scrambled to make another account to get a fresh API key, but I got insta-rate-limited once again. One more key? Ratelimited again.\nSee, the spoonacular API has this points limit. Not requests, but points. To this day, I still do not know how these points are calculated, but basically, if you try to make too many requests, the API would rate limit you and refuse to give you more recipes, instead asking you to pay some cash to get the more premium tiers.\nAt this point, it was too much for me to handle. It was around 2:13 PM when I began testing and I really couldn\u0026rsquo;t hit the submission deadline of 2:15.\nI approached a volunteer for help. Turns out his name was Tagore, keep that name in mind. He suggested using tempoary e-mails which would be fair, if only if spoonacular allowed you to spam keys with tempoary e-mails. Things were looking grim, meaning that I had to revert the commit that I worked on back to the version with duplicating entries.\nIt was only after the event that I realized that there was some sort of recursion without a predicate happening, but I scanned through the code not to find anything useful.\nMy hands were stone cold, I was shaking, jittering and thinking aobut everything that could go wrong in the next 3 hours, wondering if I had done all this for nothing. I could barely even type on my keyboard while rushing my submission into the Google Form because I was so stressed yet pissed that spoonacular really rate-limited me at this time. Oh well.\nThe aftermath (of the coding sessions) So what have I made? A recipe scroller. You can tailor search results to your dietary needs and the ingredients you have at home to get a curated list of food that you could make.\nCool enough for a small side project, but genuinely, in a professional and more mature setting in front of more experienced programmers, this would not be anything. If anything, I genuinely thought I was going to go dead last.\nBut I kept thinking; maybe all those small children weren\u0026rsquo;t secretly senior developers.\nEither way, there was nothing to lose, nothing to give up on the table. I am competing against small children and a few professional developers, what could they do to me?\nThese two conflicting thoughts flooded my mind as I went back into ICT lab S3-06, the very first room I entered in this competition; a day ago I had nothing but now I have a semi-broken app, and my fate were to be decided.\nIt was like 2:30, I was ready for the worst.\nThe room The not cold enough air coming out of the air conditioner settled on me as I slowly inched my way into the room, to pull a red chair with an armrest and a headrest, the only one of its kind in the lab.\nAs I sat there and waited for the judges to discuss something (which I still do not know), I decided to put on some Wii Shop Channel music on through my right earbud to try to make the situation less tense.\nYou may even join me in listening as I describe the rest of the event.\nOh, and before presentations actually started, of course there had to be a false fire alarm. Only in the Global International Indian School :)\nBut wait. Take a look at the first video.\nYou may see a man, a figure wearing a tan shirt with an IdeaPad (ew why not a ThinkPad) with a slightly goofy face.\nLet\u0026rsquo;s zoom in.\nThis guy would play a pivotal part in my journey, nothing would have ever happened without the presence of Judge Tagore. More on him later.\nThe Judges and the Pitches There were 2 judges. One had a clean shave and one still had facial hair. Let as call the one with facial hair \u0026ldquo;facial hair\u0026rdquo;. The clean shaved one I know the name of, which is why he will be referred to as Judge Tagore.\nRevisiting part 1 and the judging system, this is what it was:\ncriteria marks description Creativity 25% How innovative it is, and Technical complexity 25% The complexity, with comments and documentation Functionality and usability 25% User-friedliness and real-life applications Pitching 15% Being able to answer questions regading the code Software-dependent marks 10% AI would be data representation, Game development would be game design, app development would be the UI, and web dev would be the layout. all I had to do is make my product as presentable as possible to the judges and just rely on trusting myself with the quality of my app in order to not lose that boldness.\nI was quite far down the list, but here we go~\nPitches Before every pitch, the judges would always tell the room to shut their mouths, else they would deduct points from the team for being too noisy and disrespectful.\nHuge respect to those guys, they tried their best to keep the kids in check and they kinda did it.\nPitches were done via Apple\u0026rsquo;s AirPlay (proprietary wifi screen casting between iDevices, basically) to an Apple TV mounted on the back of a massive television, connected by HDMI.\nThey didn\u0026rsquo;t have an HDMI cable available for other devices, so we kind of had to use the school computer at the desk to pitch to the whole room, else we had to just present to the judges and two supervising teachers. As I\u0026rsquo;d soon find out, everybody who pitched to the audience got to use their public speaking skills more and draw attention from the whole room. This, along with other usually leads to people who can AirPlay to get higher scores.\nBasically, we had to have some sort of iDevice in order to pitch like a champ. I genuinely thought the iCult of iDevices didn\u0026rsquo;t extend to my fate in a hackathon, but it did. I love you Apple, and your overly loyal customers! You should suck my d-\nNot-so-honorable mention #1 a scratch game. I almost laughed out loud when I saw a scratch game. At myself, I stressed so much about this competition but this scratch game completely got rid of all my stress. It was a Junior team and they were literally just getting started, but my mood immediately rose as I came to see a glorious green flag on the screen with the 3 team members, who basically just dragged blocks around and relied on how simple scratch is to make a game. Wonderful, I wish I could do that ;(\nI posted this on my story:\nas I waited my turn.\nIt was some kind of game, I forgot what it was. I just kept listening to Wii Shop Channel music while waiting my turn, waiting for all the teams\u0026rsquo; submissions to fly by.\nAs I both eagerly and scarily stared at the presenting order, slowly seeing the contestants present their scratch and thunkable apps, I only became slightly more hopeful.\nHonorable Mention #1 First honorable mention. I forgot this guy\u0026rsquo;s team name (I think Ubistrong? not sure) but he made a completely bespoke website in HTML, with a little bit of JS and a lot of CSS. It was not custom and there was no name prefixing (LMAO IMAGINE), he just copied a lot from past projects, but it was still cool.\nIt was about water conservation and it was meant to raise awareness on a core element of life (life on all elements), and he had quite a lot of information jam-packed inside. The layout and style was very pretty to look at, and the programmer art was respectable on the background.\nUnfortunately I don\u0026rsquo;t have any photos (I have this terrible habit of not having any) but this one was still very cool.\nNot-so-honorable mention #2 I forgot how many pitches went by after the first one, but this one was also from a Junior team. I really do not want to bash them, but this one was a very cursed scratch flappy bird clone. The sprites were (of course) random PNGs and Emojis (not even programmer art, what a shame), and all the obstacles were on the floor.\nThis one barely related to the theme at all, the pitch was terrible, and I still will not ever understand the appeal of playing flappy bird when all the obstacles are on the floor. Oh well, not my fault-\nEverything up to this point were Junior teams if I remember correctly, nothing was cool and my confidence was quite high. A multitude of teams were missing for no reason whatsoever; the order went absolute bonkers as teams randomly spawned in.\nEventually it was my turn.\nMy Pitch I got up from my seat and approached the school computer. It had failed a little while ago, it lost power during a pitch and it had been really unstable.\nThey did warn me that this could very much happen again, but I persisted.\nAfter a few reboots, it appeared to be stable enough for a presentation.\nMy plan was to run vite --host to host my app on the local network, and then make the iMac visit my server on the local network to get the site. Simple enough. After a simple WiFi Network change (WHY NOT ETHERNET) it worked like a charm.\nMy heart was pounding, but I was ready. As Tagore and Facial Hair Man proceeded to tell everyone to shut their mouths up, I quickly changed the iMac to dark mode to ensure the color scheme would load properly, and when they were done, I began.\nWith a bold voice,\nSee, there are many elements required for any living organism including humans to survive. They include air, (pause) water (pause) and food. However, we are not cows or sheep. We cannot simply lie down on the floor and munch on grass and call it a day, we require something more than that. We must prepare our food in a way that it will taste good to us and also provide adequate nutrition to meet our dietary needs.\nI opened the minimized browser, and I begain, while worrying about me getting ratelimited.\nI gave them a demo similar to this (I didn\u0026rsquo;t rehearse this one, but I did on pitch day):\nOf course I had a commentary going on, with large hand gestures and pointing to the display to highlight important features, and EVERYBODY seemed to love it.\nAnd about Judge Tagore. His face lit up in awe after I showed him the dynamism of my program. His eyes broadened line a blooming flower, he attempted to standd up while in awe. He froze mid-stand with his hand covered and decided to sit back down.\nTurns out, he went to call Aditya Bairy, the head of the tech club. While the commotion in the room grew, my legs started becoming soft due to shock and confusion- was all this custom CSS that cool? I started making some of the weirdest screams that sounded more like whines as I stood there shook, Magic Mouse in hand.\nDespite how I listed out all the app\u0026rsquo;s shortcomings, like the lack of a search and filter feature, everybody was still in utter shock.\nA loud round of applause filled the air to the brim, as Aditya approached. Tagore demanded him give me a demo. Everybody wanted me to play with the app more. I felt like all the knots tied up in my heart were undoing themselves as I let out a huge, massive sigh of relief; even. I couldn\u0026rsquo;t believe my eyes.\nThis had to be one of the highest energy moments in my programming life. Everybody was convinced I was gonna win; a Junior team of all girls had even started a conversation with me. They complimented me and said that my app was so cool, and they really were rooting for me, and they insisted that I would win first place. They even recognized me as the person who had his computer out coding in the opening ceremony; IT WAS ME writing my blog post, the first one, the very one that I published a couple of days ago.\nThe teachers even asked me which school I went to after I sat back down.\nHAHAHAHAHA.\nI go to OFS, I said, and they were convinced that the teachers would teach us all this at grade 9. All the OFSers should know about the tragedies that we encounter. I really should write about Mr. Hubbard\u0026rsquo;s atrocities. A man who doesn\u0026rsquo;t even know what a function is who plaigarizes his teaching material from random books who taught us SQL a year early due to lack of skill was our course leader, one who I had to constantly correct because of idiotic mistakes like saying that you can cast a function to run the code inside, not call.\nI really couldn\u0026rsquo;t let Mr. Hubbard\u0026rsquo;s lack of skill ruin this moment. I just told the teachers that our school does not teach this at all and I had to learn all this myself from the start of the hackathon. I said that I did programming since 6th grade.\nThey asked which curriculum we did, I said we did IGCSE and MYP together. They then asked if I took computer science, I said I did just for the academic credit because I already knew most of the syllabus. They asked if this was my first hackathon, I said yes, because I did more niche things and that I prefer to stay in my own cave and code instead of coding outside.\nMy energy level was high, but I couldn\u0026rsquo;t be too hopeful. There were still pitches left.\nI actually think that they were much cooler than mine.\nHonorable Mention #2 Immediately after my pitch, came core.\nThis team is cracked, to say the least.\nA group of two quite dark skinned people who go to Singapore Polytechnic. This was their 52nd hackathon. FIFTY-SECOND.\nThey took gardening, which is the act of maintaining living plants\u0026rsquo; health (theme) to a whole new level, They used an esp32 as their µController, loaded 6 AI models on it and hooked up a camera to detect if a plant were healthy or not. Depending on that, along with a humidity and temperature sensor all mounted below the plant pot that they 3D printed, it will water the plant and also send the plant\u0026rsquo;s state to the user via Telegram and a Telegram bot, all running on the esp32 with network access.\nThis project was crazy; Judge Tagore had already been fazed and exposed to skill, so he wasn\u0026rsquo;t as shocked, but this one was even crazier than mine because Core incorporated so many fields of Computer Science and even some biology into this hackathon project.\nAlmost all of this was written in C++, also very impressive.\nHonorable Mention #3 This one is from the Destiute Dingbats, a team actually from our school, those very kids from places far and wide. They decided to not AirPlay for whatever reason despite having a MacBook Air on hand, but I digress.\nThey took the theme and adapted it to a mood tracker/calendar thingy. They interpreted elements as in elements of life, and made it very simple and minimalistic, stating life on its core elements. A very neat concept for sure.\nAgain, I forgot what they did exactly, but it definitely had elements of dynamism, it was very clean and minimal and it actualy functioned quite well. There were no CSS animations, which was understandable because it isn\u0026rsquo;t easy anyways.\nComing from students who were only taught IGCSE ICT at school (HTML4 and CSS2) and without knowledge of component based design or any more advanced frontend design concepts, this was very impressive. They should have done programming outside of ICT before though, if I remember correctly.\nHonorable Mention #4 This team of 4 made a whole role-playing game, simulating the contsruction of a civilization, including the process of taking control of the native people, along with other concepts such as the construction of housing and sustainable fishing and farming all in this small package. They have had experience doing game jams before as I asked, but it was still quite cool.\nThe animations were wonky. The characters just rotated around a pivot situated around the middle-ish of their body at a smooth rate of 10° ish each side, which did not look very good. The programmer art was nice though.\nThe controls were quite interesting as I saw. The judges interacted with the game a bit (which was written in Godot unfortunately, I\u0026rsquo;m using SDL and OpenGL with C next year haha.), and the demo was quite cool although I did forget many aspects of it. They did also preach Fish and Chips as a very sustainable food source though.\nI dont want to eat bland food despite how sustainable it could be. Let me eat my red braised pork and samosas.\nHonorable Mention #5 This team of pure Asian talent cooked together an extremely complicated algorithm to figure out sleep timings.\nGiven a schedule, the algorithm would find out which sleep pattern (monophasic, biphasic or polyphasic sleep) the user is best suited to, and a new schedule would be denegrated with optimal sleep times and with regard to their activities.\nThey had an insanely long presentation, which toured each part of the codebase. Unfortunately, the judges did not really want to look at it for some reason despite all the effort they put into the presentation, incuding all the math needed to figure out the time complexity. The C++ they wrote was not the best at all (not expecting anything crazy, no formatter and no C++ features were even used, it could have easily been done in C), but its still very cool what they pulled off.\nThey also wrote a schedule parser which would let you write a custom syntax to describe your schedule (which would be very annoying to test and implement being a compiler engineer wannabe), and they even trained a custom GPT-4 to optimize the results of their algorithm further. Unfortunately, it did not translate too well to their website, as it was mostly informative, the UI did not look very good and it was quite shotty overall.\nThe End? I nervously waited for the closing ceremony to commence while eating some mystery potato and chaat in yogurt sauce with ketchup.\nI really didn\u0026rsquo;t think I would win first place because Core did such a good job with their plant, but maybe I\u0026rsquo;d win second, or third, or maybe nothing. I didn\u0026rsquo;t know.\nThe closing ceremony began with speech after speech as I nervously watched as the Juniors claimed their awards.\nThey did have 2 honorable mentions which I both also shouted out, but I forgot which teams exactly. I waited anxiously as they announced at third place was Code Lovers (i forgor what they made)\nhats off to them.\nAnd after a little more anxious waiting, came\nAnd at second place, we have\u0026hellip;ezntek!\noh yes.\nI won.\nUsually I look like a scarecrow. Dead serious face with perpetually tired looking eyes and zero smile, but here I couldn\u0026rsquo;t hide it. I won second place while at my FIRST hackathon! Very nice.\nSecond place was fair, which meant at first place there had to be\u0026hellip;\nCORE!\nThose guys were actually cracked, and they definitely deserved it. Considering how I rawdogged TypeScript and Vue as a low level systems enthusiast/dev who uses C and Rust more than anything, and how Core had attended over 50 hackathons prior to this event, I really did not expect anybody but them to win.\nThis is the end of a journey; of random ass roadblocks, 2 rides on the PGLRT that I am looking forward to not riding again, an API rate limit and Judge Tagore completely saving me and flabbergasting me with that face. God, you did NOT have to open your mouth that wide, you could have gotten lockjaw ;)\nI thank everyone who made this event possible, including the president Aditya Bairy, designer Ashwath who demanded an appearance (make sure your friends dont bully you for demanding for an appearance on this site who noone visits), the VP of the club whose name I do not know, Judge Tagore and Mr. Facial hair who yelled at the kids, Akshat and all the other people.\nNot to mention the MC\u0026rsquo;s which I believe were Twisha Metha and some other guy. Too many names, SORRY IF I GET ANY WRONG (please correct me in the comments)\n(You really should have put your names in some credits sheet so people can shout you out smh)\nRandom ass other shit To the photographer who took this photo, please take a look at this:\n(do not meme me)\nMY USERNAME ITS EZNTEK. yeah right.\nE as in Feed. ZN as in Zin, with an I. Similar to the Sin in Singapore. TEK as in Tech.\nNo capitalization required. Pronouncing it\n/ɛznt̪ɛk/ is a bit of a crime. sorry-\n","permalink":"http://ezntek.com/posts/the-giis-hackathon-x-a-review-part-4-20240803t1857/","summary":"\u003ch2 id=\"foreword\"\u003eForeword\u003c/h2\u003e\n\u003cp\u003eYes, this will take you very long to read because this really should\nhave been 5 parts. These reading time calculations are also quite\nmessed up. Not my fault, click away if you don\u0026rsquo;t have patience :p\u003c/p\u003e\n\u003ch2 id=\"recap\"\u003eRecap\u003c/h2\u003e\n\u003cp\u003eAs of the last post, I was on day 2, right before the lunch break. I had just\n(almost) finished writing my article display, and I am now ready to start\nconnecting the API. Everything else works just fine.\u003c/p\u003e","title":"The GIIS Hackathon X - My Experience (the finale)"},{"content":"Intro \u0026amp; Recap As of August 1st, I have been quite busy over the past few days. I went out with friends, and a lot of new hardware parts arrived, such as SOIC-8 clips (that I had to assemble), my T440p keyboard (finally!!), and other such things. This explains why I haven\u0026rsquo;t uploaded part 3 yet, but here it finally is!\nSome source code examples might deviate from the actual source code at https://github.com/ezntek/foodscroller for clarity sake.\nIf you haven\u0026rsquo;t really read the first and second parts, I urge you to do so here and here. To summarize the second article, I met some pretty cool people and almost teamed up with them, but ended up not in the end. I didn\u0026rsquo;t have any ideas until I had a samosa during breaktime, and I started implementing my app in Vue.js.\nI finished the navbar, and worked on the settings page.\nGoing home This took about an hour. I had 3 choices for a bus, bus 3, 39 and 81. 81 would take the longest, as I\u0026rsquo;d have to ride the wonderfully engineered Punggol LRT (which is more like an Airport shuttle train, not a tram. It\u0026rsquo;s called an Automated People Mover System) with wonderful acceleration curves that are not jarring (sarcasm); for 2 stops, then only walking for another 10 minutes to get to the bus stop after crossing 4 crossings to board the bus. The Bus 3 bus would have taken over 10 minutes to arrive at the bus stop I had to go to, so I decided on 39.\nTurns out that was quite a bad idea, I had to walk the distance of 2 LRT stops, and Google Maps routed my journey wrong. it told me to cross at a crossing that doesn\u0026rsquo;t even exist! (I had to walk back and take 2 sets of crossings, don\u0026rsquo;t ask.)\nIt took me an hour to get home, double that than if bus 3 came earlier. Oh well!\nThe nighttime programming session This is when I got the majority of my work done. I slept at 1:30 and stopped programming at 1 and only at 1 (I came back at 9, which meant a 5 hour programming/ procrastination session), but oh well.\nFinishing the settings page I lied in the previous article. I actually only finished the settings bubble up to that point, and I did not have any of the settings stuff working.\nI worked on the component props to decide the color of the bubble and whether or not to show the plus icon or not, which took a while.\nTo get the color to change, I had to conditionally switch out a CSS class based on JS (TypeScript) state. Luckily, Vue.js has this thing called the v-bind directive, where you can write something like\n\u0026lt;a v-bind:href=\u0026#34;$props.activeLink\u0026#34;\u0026gt;My Link\u0026lt;/a\u0026gt; to actually bind JS state to an HTML prop. Its short form looks as follows:\n\u0026lt;a :href=\u0026#34;$props.activeLink\u0026#34;\u0026gt;My Link\u0026lt;/a\u0026gt; which is what I used to conditionally swap CSS.\nInterlude: CSS Naming Conventions Despite how you may have a scoped CSS block in Vue, like\n\u0026lt;style scoped\u0026gt; .title { font-weight: 800; } \u0026lt;/style\u0026gt; For some reason, on my end, If I defined this CSS class in a child SFC, it would still apply the CSS class in the parent, which was very annoying.\nTherefore, I had to prefix everything the C style which basically meant\ncomponent-name-class-name\njust like how you have to prefix functions and typedefs in C for \u0026ldquo;namespacing\u0026rdquo;.\nMore settings page I had defined a base class for the div, which is as follows:\n.diet-bubble-container { display: flex; border-radius: 8px; padding: 0.3em; margin: 0.3em; } .diet-bubble-container-blue { background-color: var(--vt-c-blue); } .diet-bubble-container-green { background-color: var(--vt-c-green); } and in the template section, I used the v-bind directive to conditionally change the color by doing something like this:\n\u0026lt;div class=\u0026#34;diet-bubble-container\u0026#34; :class=\u0026#34;$props.showPlus ? \u0026#39;diet-bubble-container-green\u0026#39; : \u0026#39;diet-bubble-container-blue\u0026#39;\u0026#34;\u0026gt; \u0026lt;!-- contents --\u0026gt; \u0026lt;/div\u0026gt; where every DietBubble container would have the base CSS class assigned to it, and a prop would change what the second class would be (either a green bubble or a blue bubble).\nAnd to show the icon, I did\n\u0026lt;FontAwesomeIcon v-if=\u0026#34;$props.showPlus\u0026#34; :icon=\u0026#34;far.faSquarePlus\u0026#34; class=\u0026#34;diet-bubble-container-tick-icon\u0026#34; style=\u0026#34;color: var(--vt-c-white-soft)\u0026#34; /\u0026gt; to conditionally render the FA icon. I then assigned a CSS class to it that would set display: none; but display: inline-block; when the parent div was hovered like so:\n.diet-bubble-container-tick-icon { display: none; /* other styles */ } .diet-bubble-container:hover .diet-bubble-container-tick-icon { display: inline-block; } Allergies The story is basically the same, the components are also identical. However, I also display a Font Awesome cross icon when hovering the green bubble, as one should be able to freely remove their allergies.\nI just used the v-else directive, like so:\n\u0026lt;FontAwesomeIcon v-if=\u0026#34;$props.showXmark\u0026#34; :icon=\u0026#34;far.faCircleXmark\u0026#34; class=\u0026#34;allergy-bubble-container-x-icon\u0026#34; style=\u0026#34;color: var(--vt-c-white-soft)\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else :icon=\u0026#34;far.faSquarePlus\u0026#34; class=\u0026#34;allergy-bubble-container-x-icon\u0026#34; style=\u0026#34;color: var(--vt-c-white-soft)\u0026#34; /\u0026gt; Showing the icon for each allergy was also trivial, I just used v-if and v-else-if chaining to get it done:\n\u0026lt;span class=\u0026#34;allergy-bubble-container-icon\u0026#34;\u0026gt; \u0026lt;FontAwesomeIcon v-if=\u0026#34;$props.allergy == Allergy.Dairy\u0026#34; :icon=\u0026#34;fas.faCow\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.allergy == Allergy.Egg\u0026#34; :icon=\u0026#34;fas.faEgg\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.allergy == Allergy.Gluten\u0026#34; :icon=\u0026#34;fas.faBreadSlice\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.allergy == Allergy.Seafood\u0026#34; :icon=\u0026#34;fas.faFish\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.allergy == Allergy.Shellfish\u0026#34; :icon=\u0026#34;fas.faShrimp\u0026#34; /\u0026gt; \u0026lt;span v-else-if=\u0026#34;$props.allergy == Allergy.Soy\u0026#34;\u0026gt;🫘\u0026lt;/span\u0026gt; \u0026lt;span v-else-if=\u0026#34;$props.allergy == Allergy.Peanut\u0026#34;\u0026gt;🥜\u0026lt;/span\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.allergy == Allergy.Wheat\u0026#34; :icon=\u0026#34;fas.faWheatAwn\u0026#34; /\u0026gt; \u0026lt;/span\u0026gt; In the end, it looks like this:\nStoring the state was not too hard. Local storage does only permit you to store basic JavaScript primitives and not arrays, meaning that I had to concatenate all elements into a string and seperate them with a separator. Originally I picked ;, but I didn\u0026rsquo;t account for how the API requires ,, meaning that I had to do a find and replace operation later on.\nIt was as simple as\nconst addAllergy = (allergy: Allergy) =\u0026gt; { selectedAllergies.value.push(allergy) window.localStorage.setItem(\u0026#39;allergies\u0026#39;, selectedAllergies.value.join(\u0026#39;;\u0026#39;)) } to concatenate all elements into a string and store it.\nI also wrote the onBeforeMount hook to do some work before a widget is mounted onto the DOM to load in the settings, which looked like this:\nonBeforeMount(() =\u0026gt; { let diet = window.localStorage.getItem(\u0026#39;diet\u0026#39;) let allergies = window.localStorage.getItem(\u0026#39;allergies\u0026#39;) if (allergies === null) { allergies = \u0026#39;\u0026#39; } const allergies_arr = allergies.split(\u0026#39;;\u0026#39;) console.log(\u0026#39;loaded\u0026#39;) selectedDiet.value = diet !== null ? (diet as Diet) : Diet.Vegetarian selectedAllergies.value = allergies !== null ? (allergies_arr as Array\u0026lt;Allergy\u0026gt;) : [] }) All in all, this gives us a working settings page, with proper storage in local storage.\nWoohoo!\nThe Pantry Again, the pantry bubble was also trivial. I didn\u0026rsquo;t even need to store an icon (as implementing icons through basic string matching would take FAR TOO LONG), which results in a simple SFC:\n\u0026lt;script lang=\u0026#34;ts\u0026#34; setup\u0026gt; import { far } from \u0026#39;@fortawesome/free-regular-svg-icons\u0026#39; import { FontAwesomeIcon } from \u0026#39;@fortawesome/vue-fontawesome\u0026#39; interface Props { itemName: string } defineProps\u0026lt;Props\u0026gt;() \u0026lt;/script\u0026gt; \u0026lt;template\u0026gt; \u0026lt;div class=\u0026#34;pantry-item-container\u0026#34;\u0026gt; \u0026lt;span class=\u0026#34;pantry-item-container-item-name\u0026#34;\u0026gt;{{ $props.itemName }}\u0026lt;/span\u0026gt; \u0026lt;FontAwesomeIcon :icon=\u0026#34;far.faCircleXmark\u0026#34; class=\u0026#34;pantry-item-container-x-icon\u0026#34; style=\u0026#34;color: var(--vt-c-white-soft)\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/template\u0026gt; \u0026lt;style scoped\u0026gt; .pantry-item-container { display: flex; border-radius: 8px; padding: 0.3em; margin: 0.3em; background-color: var(--vt-c-blue); } .pantry-item-container-item-name { font-weight: 700; color: var(--vt-c-white-soft); } .pantry-item-container-icon FontAwesomeIcon { margin-top: 0.3em; } .pantry-item-container .pantry-item-container-x-icon { display: none; margin-top: 0.3em; margin-left: 0.5em; color: var(--vt-c-red); } .pantry-item-container:hover .pantry-item-container-x-icon { display: inline-block; } \u0026lt;/style\u0026gt; For the user input box, I went with a simple HTML \u0026lt;input\u0026gt; tag. Like every other clickable \u0026ldquo;bubble\u0026rdquo;, I went with the wrap-it-in-a-null-button technique. The template is trivial:\n\u0026lt;button class=\u0026#34;null-button\u0026#34; @click=\u0026#34;addPantryItem(inputBoxModel)\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;pantry-add-item-container\u0026#34;\u0026gt; \u0026lt;input type=\u0026#34;text\u0026#34; name=\u0026#34;textInput\u0026#34; class=\u0026#34;pantry-view-input-box\u0026#34; v-model=\u0026#34;inputBoxModel\u0026#34; @keyup.enter=\u0026#34;addPantryItem(inputBoxModel)\u0026#34; /\u0026gt;\u0026lt;!-- Add a pantry item when the enter key is pressed (and therefore released) --\u0026gt; \u0026lt;span class=\u0026#34;pantry-add-item-container-plus-icon\u0026#34; \u0026gt;\u0026lt;FontAwesomeIcon :icon=\u0026#34;far.faSquarePlus\u0026#34; style=\u0026#34;color: var(--vt-c-white-soft)\u0026#34; /\u0026gt;\u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/button\u0026gt; Notice the v-model directive. That allows me to set a piece of reactive state in TS:\nconst inputBoxModel: Ref\u0026lt;string\u0026gt; = ref(\u0026#39;\u0026#39;) and sync the contents of the Input Box to the variable. I also use a @keyup.enter event handler (I don\u0026rsquo;t know the name, its the @ thing) to add a pantry item to a reactive list when enter is pressed. Of course, I had to make a hoverable div with rounded corners to tie it all together.\nI keep a reactive list pantry around like so:\nconst pantry: Ref\u0026lt;Array\u0026lt;string\u0026gt;\u0026gt; = ref([]) and I also set a few callbacks for this page:\nonBeforeMount(() =\u0026gt; { let pantry_s = window.localStorage.getItem(\u0026#39;pantry\u0026#39;) if (pantry_s === null) { pantry_s = \u0026#39;\u0026#39; } const pantry_arr = pantry_s.split(\u0026#39;;\u0026#39;) pantry.value = pantry_arr }) const addPantryItem = (item: string) =\u0026gt; { if (!pantry.value.includes(item)) { pantry.value.push(item.toLowerCase()) } inputBoxModel.value = \u0026#39;\u0026#39; window.localStorage.setItem(\u0026#39;pantry\u0026#39;, pantry.value.join(\u0026#39;;\u0026#39;)) } const removePantryItem = (item: string) =\u0026gt; { pantry.value = pantry.value.filter((v) =\u0026gt; v != item) window.localStorage.setItem(\u0026#39;pantry\u0026#39;, pantry.value.join(\u0026#39;;\u0026#39;)) } which also deal with concatenating all pantry items and mounting stuff, which yields one this:\nAfter that, I promptly went to sleep, dreaming about all the things that would go wrong the next day\u0026hellip;\nDay 2 I took a ride on this wonderful Singaporean creation again (rubber tires on concrete disguised as a train with dogshit acceleration) to come to Day 2. It was mostly as expected, I got there at 8:45 AM and got straight to the library to lock in for the day. The previous night I also fiddled with swapping out components based on JS state while keeping state across those components, and that worked.\nThe reason why I tested it is becuase when I fetch the data from the spoonacular API, I will only display a few recipe cards. However, when one clicks on a recipe card, data from the clicked card should transfer over to another component and be displayed as a full article. That actually worked, meaning that I could get strated.\nCoding session 1 NOTE: I am not sponsored by anyone, and I don\u0026rsquo;t really like this API either. I used it because it was the first one I found. Oh well.\nGetting the API key It was as simple as creating a spoonacular account and getting it from the dashboard.\nAfter that, I used curl to grab some JSON from https://api.spoonacular.com/recipes/complexSearch?apiKey=\u0026lt;THE API KEY WAS HERE\u0026gt;\nI then saved the JSON to a file. This is so that I don\u0026rsquo;t rate-limit myself (foreshadowing) when I have to submit my code.\nI hardcoded the JSON to a file for testing in the frontend and I used node\u0026rsquo;s fs module\u0026rsquo;s readFileSync to test the class constructor.\nI made a simple TypeScript class like so:\nexport class Recipe { vegetarian: boolean vegan: boolean glutenFree: boolean dairyFree: boolean timeToCook: number title: string summary: string sourceURL: string imageURL: string ingredients: Array\u0026lt;string\u0026gt; equipment: Array\u0026lt;string\u0026gt; instructions: Array\u0026lt;string\u0026gt; /* more code here */ } The constructor should take an object where the key is a String. However, tsserver decided it was cool that I used a string to query the parsed JSON object, so I had to write an interface:\nexport interface AnyObject { [key: string]: any } with funky syntax that I definitely did not copy from a certain LLM called ChatGPT. I then made the constructor take this in (the object happily coerced, unlike in other languages where types are real and are not imaginary constructs created by a transpiler to make developers feel better about using a toy dynamic language) ANYWAYS.\nThe overall idea was:\nGet the applicable diets (Veg, Vegan, Non-veg etc) from boolean values given Save all needed string values without change Loop over all the steps and save the string values and required ingredients Store all the ingredients in a set (ideally, I used an array because I thought the response would have no duplicates). This is what the constructor looks like:\nconstructor(recipeObj: AnyObject) { // type annotating the whole JSON response would be too tedious this.vegetarian = recipeObj[\u0026#39;vegetarian\u0026#39;] this.vegan = recipeObj[\u0026#39;vegan\u0026#39;] this.glutenFree = recipeObj[\u0026#39;glutenFree\u0026#39;] this.dairyFree = recipeObj[\u0026#39;dairyFree\u0026#39;] this.timeToCook = (recipeObj[\u0026#39;preparationMinutes\u0026#39;] as number) + (recipeObj[\u0026#39;cookingMinutes\u0026#39;] as number) this.title = recipeObj[\u0026#39;title\u0026#39;] this.summary = recipeObj[\u0026#39;summary\u0026#39;] this.sourceURL = recipeObj[\u0026#39;sourceUrl\u0026#39;] this.imageURL = recipeObj[\u0026#39;image\u0026#39;] if (this.timeToCook == 0) { this.timeToCook = recipeObj[\u0026#39;readyInMinutes\u0026#39;] as number } let ingredients: Array\u0026lt;string\u0026gt; = [] let equipment: Array\u0026lt;string\u0026gt; = [] const instructions: Array\u0026lt;string\u0026gt; = [] const steps: Array\u0026lt;AnyObject\u0026gt; = recipeObj[\u0026#39;analyzedInstructions\u0026#39;][0][\u0026#39;steps\u0026#39;] steps.forEach((obj: AnyObject) =\u0026gt; { // create a list of all new ingredients to add const ingredientNames = (obj[\u0026#39;ingredients\u0026#39;] as Array\u0026lt;AnyObject\u0026gt;).map( (o: AnyObject) =\u0026gt; o[\u0026#39;name\u0026#39;] as string ) const equipmentNames = (obj[\u0026#39;equipment\u0026#39;] as Array\u0026lt;AnyObject\u0026gt;).map( (o: AnyObject) =\u0026gt; o[\u0026#39;name\u0026#39;] as string ) ingredients = ingredients.concat(ingredientNames) equipment = equipment.concat(equipmentNames) instructions.push(obj[\u0026#39;step\u0026#39;]) }) this.ingredients = ingredients this.equipment = equipment this.instructions = instructions } Making the recipe card itself was trivial. The template itself is quite simple:\n\u0026lt;div class=\u0026#34;recipe-card-container\u0026#34;\u0026gt; \u0026lt;img :src=\u0026#34;props.recipeInfo.imageURL\u0026#34; class=\u0026#34;recipe-card-image\u0026#34; /\u0026gt; \u0026lt;div class=\u0026#34;recipe-card-info\u0026#34;\u0026gt; \u0026lt;h1 class=\u0026#34;recipe-card-title\u0026#34;\u0026gt;{{ title }}\u0026lt;/h1\u0026gt; \u0026lt;RecipeInfoDisplay :recipe-info=\u0026#34;$props.recipeInfo\u0026#34; /\u0026gt; \u0026lt;p v-html=\u0026#34;$props.recipeInfo.summary\u0026#34; class=\u0026#34;recipe-card-description\u0026#34;\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; (Notice the interpolation syntax with {{ title }}, that is to interpolate JS state into a template.)\nThe CSS was not so easy, I had to display the image and the recipe card inline, and then everything else as block.\nThe Recipe Info Display detailed the information about the recipe. It kinda looked like this:\n\u0026lt;template\u0026gt; \u0026lt;div class=\u0026#34;recipe-info-display-container recipe-info-display-container-green\u0026#34; v-if=\u0026#34;$props.recipeInfo.vegetarian\u0026#34; \u0026gt; \u0026lt;span\u0026gt; \u0026lt;FontAwesomeIcon :icon=\u0026#34;fas.faLeaf\u0026#34; /\u0026gt; \u0026lt;span class=\u0026#34;recipe-info-display-span\u0026#34;\u0026gt;Vegetarian\u0026lt;/span\u0026gt; \u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;recipe-info-display-container recipe-info-display-container-green\u0026#34; v-if=\u0026#34;$props.recipeInfo.vegan\u0026#34; \u0026gt; \u0026lt;span\u0026gt; \u0026lt;FontAwesomeIcon :icon=\u0026#34;fas.faSeedling\u0026#34; /\u0026gt; \u0026lt;span class=\u0026#34;recipe-info-display-span\u0026#34;\u0026gt;Vegan\u0026lt;/span\u0026gt; \u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;recipe-info-display-container recipe-info-display-container-green\u0026#34; v-if=\u0026#34;$props.recipeInfo.glutenFree\u0026#34; \u0026gt; \u0026lt;span\u0026gt; \u0026lt;FontAwesomeIcon :icon=\u0026#34;fas.faBreadSlice\u0026#34; /\u0026gt; \u0026lt;span class=\u0026#34;recipe-info-display-span\u0026#34;\u0026gt;Gluten Free\u0026lt;/span\u0026gt; \u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;recipe-info-display-container recipe-info-display-container-green\u0026#34; v-if=\u0026#34;$props.recipeInfo.dairyFree\u0026#34; \u0026gt; \u0026lt;span\u0026gt; \u0026lt;FontAwesomeIcon :icon=\u0026#34;fas.faCow\u0026#34; /\u0026gt; \u0026lt;span class=\u0026#34;recipe-info-display-span\u0026#34;\u0026gt;Dairy Free\u0026lt;/span\u0026gt; \u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;recipe-info-display-container recipe-info-display-container-blue\u0026#34;\u0026gt; \u0026lt;span\u0026gt; \u0026lt;FontAwesomeIcon :icon=\u0026#34;far.faClock\u0026#34; /\u0026gt; \u0026lt;span class=\u0026#34;recipe-info-display-span\u0026#34;\u0026gt;{{ $props.recipeInfo.timeToCook }}min\u0026lt;/span\u0026gt; \u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/template\u0026gt; Yes, it most definitely looks long, but it really is just a bunch of v-if directives.\nIn the end, you get a recipe card:\nSimple. The CSS is bog-standard:\n.recipe-card-container { display: flex; padding: 1rem; margin: 0.5rem; margin-bottom: 1em; border-radius: 12px; transition: 300ms; max-height: 12.5rem; background-color: var(--vt-c-divider-dark-2); } .recipe-card-description { max-height: 4.5rem; overflow: hidden; } .recipe-card-title { font-weight: 600; } .recipe-card-image { /* scaled 70%, all images from spoonacular are of equal dimension */ width: 218px; height: 162px; margin-right: 1em; } I also really wanted a hover effect, which is as simple as adding a box shadow:\n.recipe-card-container:hover { box-shadow: 0 4px 20px var(--vt-c-indigo); } Snack #1 It really was not too interesting. There was a free donut, but it was miniscule and I put it all in my mouth in one go. That wasn\u0026rsquo;t so good.\nI then decided to go downstairs to the café once again, to get a Vadai and Samosa. I thought about how well my idea developed into my final program while eating my food.\nIf you don\u0026rsquo;t know what a vadai is, it\u0026rsquo;s basically a salty fermented donut. It isn\u0026rsquo;t really made from a dough but from something more similar to a batter, and it is a lot more aerated. It also tastes Indian, unlike a Donut.\nI really had 0 time to waste, though. I spent basically no time eating my food and I immediately went back up to work on the article display.\nCoding session II By this point, my whole body was freezing cold from the Air Conditioning unit constantly blowing on me, but I really couldn\u0026rsquo;t do much about it at this point. I really just had to push through.\nAt that point, I only had one object with the recipe data, meaning that it was really easy to test the description view.\nThe overall layout was to be:\nThe navbar (stays intact) The title (heading 1, centered) A divider The image (centered) Recipe Info The ingredients The Equipment The summary The steps A go back button A diagram may help:\nPutting everything together was quite simple. I had just made a component that contains a label that you specify and a separator which looked like this:\n\u0026lt;template\u0026gt; \u0026lt;p class=\u0026#34;divider-item-label\u0026#34;\u0026gt;\u0026lt;slot\u0026gt;\u0026lt;/slot\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;hr style=\u0026#34;margin-bottom: 0.3em\u0026#34; /\u0026gt; \u0026lt;/template\u0026gt; \u0026lt;style scoped\u0026gt; .divider-item-label { margin-bottom: 0.3em; display: flex; justify-content: center; } \u0026lt;/style\u0026gt; An interlude At this point, I was really, really, really cold (my hands were about to freeze), so I decided to go downstairs to the area right below the 2nd to 3rd floor escalator.\nThat is where I finished the article display page.\nI pass through the array of recipes from the home page to the widget via a prop, and the index of the recipe. The component then only needs to do a simple array index.\nHere I render the list of recipes in a for loop and keep the index:\n\u0026lt;div v-if=\u0026#34;recipes.length \u0026gt; 0\u0026#34;\u0026gt; \u0026lt;div v-for=\u0026#34;(recipe, index) in recipes\u0026#34; :key=\u0026#34;index\u0026#34;\u0026gt; \u0026lt;button class=\u0026#34;null-button\u0026#34; @click=\u0026#34;openRecipe(index)\u0026#34;\u0026gt; \u0026lt;RecipeCard :recipe-info=\u0026#34;recipe\u0026#34;\u0026gt;\u0026lt;/RecipeCard\u0026gt; \u0026lt;/button\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; openRecipe then swaps a conditional value which then controls which page is active, and sets the index:\nconst showMain = ref(true) /* later */ const openRecipe = (index: number) =\u0026gt; { selectedRecipeIndex.value = index showMain.value = !showMain.value } The component only takes in 2 props:\ninterface Props { recipeList: Array\u0026lt;Recipe\u0026gt; index: number } const props = defineProps\u0026lt;Props\u0026gt;() const recipe = props.recipeList[props.index] the recipe list and then the index, and it is rendered like so:\n\u0026lt;div v-else\u0026gt; \u0026lt;RecipeView :recipe-list=\u0026#34;recipes\u0026#34; :index=\u0026#34;selectedRecipeIndex\u0026#34;\u0026gt;\u0026lt;/RecipeView\u0026gt; \u0026lt;button class=\u0026#34;back-home-button\u0026#34; @click=\u0026#34;showMain = !showMain\u0026#34;\u0026gt; \u0026lt;FontAwesomeIcon :icon=\u0026#34;fas.faCircleArrowLeft\u0026#34; /\u0026gt; \u0026lt;span\u0026gt;GO BACK\u0026lt;/span\u0026gt; \u0026lt;/button\u0026gt; \u0026lt;/div\u0026gt; The template is (again) quite simple:\n\u0026lt;template\u0026gt; \u0026lt;main\u0026gt; \u0026lt;h1 class=\u0026#34;title\u0026#34; style=\u0026#34;text-align: center; font-size: 2.5rem\u0026#34;\u0026gt;{{ recipe.title }}\u0026lt;/h1\u0026gt; \u0026lt;br /\u0026gt; \u0026lt;hr /\u0026gt; \u0026lt;br /\u0026gt; \u0026lt;div style=\u0026#34;display: flex; justify-content: center\u0026#34;\u0026gt; \u0026lt;img :src=\u0026#34;recipe.imageURL\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;br /\u0026gt; \u0026lt;div style=\u0026#34;display: flex; justify-content: center\u0026#34;\u0026gt; \u0026lt;RecipeInfoDisplay :recipe-info=\u0026#34;recipe\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;h2 class=\u0026#34;subtitle\u0026#34;\u0026gt;INGREDIENTS\u0026lt;/h2\u0026gt; \u0026lt;BubbleListView :items=\u0026#34;recipe.ingredients\u0026#34; /\u0026gt; \u0026lt;h2 class=\u0026#34;subtitle\u0026#34;\u0026gt;EQUIPMENT\u0026lt;/h2\u0026gt; \u0026lt;BubbleListView :items=\u0026#34;recipe.equipment\u0026#34; /\u0026gt; \u0026lt;h2 class=\u0026#34;subtitle\u0026#34;\u0026gt;SUMMARY\u0026lt;/h2\u0026gt; \u0026lt;div class=\u0026#34;recipe-body-container\u0026#34;\u0026gt; \u0026lt;p v-html=\u0026#34;recipe.summary\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;br /\u0026gt; \u0026lt;h2 class=\u0026#34;subtitle\u0026#34;\u0026gt;INSTRUCTIONS\u0026lt;/h2\u0026gt; \u0026lt;ol\u0026gt; \u0026lt;li v-for=\u0026#34;(instruction, index) in recipe.instructions\u0026#34; :key=\u0026#34;index\u0026#34;\u0026gt; {{ instruction }} \u0026lt;/li\u0026gt; \u0026lt;/ol\u0026gt; \u0026lt;br /\u0026gt; \u0026lt;/main\u0026gt; \u0026lt;/template\u0026gt; After going back up and finishing all the code I showed you, here\u0026rsquo;s what the display looks like.\nSince this article is getting too long once again, I will post a fourth and final part, which details my troubles connecting the API to my app and some final remarks. So until then, cheers!\n","permalink":"http://ezntek.com/posts/the-giis-hackathon-x-a-review-part-3-20240801t1539/","summary":"\u003ch2 id=\"intro--recap\"\u003eIntro \u0026amp; Recap\u003c/h2\u003e\n\u003cp\u003eAs of August 1st, I have been quite busy over the past few days. I went out\nwith friends, and a lot of new hardware parts arrived, such as SOIC-8 clips\n(that I had to assemble), my T440p keyboard (finally!!), and other such things.\nThis explains why I haven\u0026rsquo;t uploaded part 3 yet, but here it finally is!\u003c/p\u003e\n\u003cp\u003eSome source code examples might deviate from the actual source code at\n\u003ca href=\"https://github.com/ezntek/foodscroller\"\u003ehttps://github.com/ezntek/foodscroller\u003c/a\u003e for clarity sake.\u003c/p\u003e","title":"The GIIS Hackathon X - My Experience (part 3)"},{"content":"Recap If you haven\u0026rsquo;t checked the first article out, please do here.\nThis article will cover mainly the events on day one, along other appropriate stories fit for this article. Source code shown is in the state that it is in right now (i.e. the complete app). I only set up git later on in the development process due to time reasons. Some components may not be explained, that is to be expected.\nIn summary, I thought the campus that the event was held in was pretty cool in all, and gave off some heavy hospital vibes. Despite the very late start and multiple delays given without much explanation, initial impressions were very good.\nStructure for the first day It was very simple, we would have 2 coding sessions that\u0026rsquo;d last for 1h30m and 2h respectively, however due to the delay before prior to the opeing ceremony, the times were shifted a bit. We were to have our coding session 1 end at 5:00PM, and and coding session 2 to begin at 5:30. That means that we would get 1h30mins for the last coding session. Oh well.\nCoding session #1 As addressed in my first article, I went to the library to get work done.\n(That\u0026rsquo;s actually a custom BIOS, my own Coreboot GRUB+SeaBIOS payload! Article coming soon).\nI ultimately decided against using GTK+Rust+Libadwaita due to additional complications that I did not want to deal with later. I also really didn\u0026rsquo;t want to deal with the whole async rust shebang, which is a pure pain in the arse.\nI did find a few tablemates, however. A man by the name of Jiwoo was sitting at a table and I decided to join him. We talked for a bit, and I found out that he went to Saint John\u0026rsquo;s International in Singapore, and that he\u0026rsquo;s actually a pretty good Python developer. I was still brainstorming when I sat next to him because I was still so clueless on the theme \u0026ldquo;Life on all elements\u0026rdquo; (I still don\u0026rsquo;t know what that means exactly).\nI met a few of his friends who just had a Comp Sci exam, and had come late. We talked about project ideas and a possibility of a team merger. My idea was to use raylib to make a bug killing simulator in a living room, as bugs are elements along with other things in a room with life, and they really seemed to like the idea of raylib, but we all mutually agree that doing a team merger would be dumb. Our prior experiences are quite different (as I learnt C as my first language for some reason, and still mainly use it along with Rust). I also didn\u0026rsquo;t resonate with their idea of a chemical reaction simulator.\nThis is how I ultimately decided on using Vue.js and TS as described in the first article. But where did my idea come from?\nSnack time (an interlude) I really wanted a break from this stuff, so I decied to go to the second floor to get snack, as I saw a café there. It was actually a huge mistake, as I soon found out that all food at this vent, including the snack was completely complimentary. But it really was a blessing in disguise.\nI got a Samosa (like a true Indian food enjoyer [1]).\nBut while I enjoyed that piping hot samosa for 2 dollars (I think) (I almost burned myself) an idea popped in my head.\nSee, this samosa was made by following a set of instructions, a recipe. Written down or not, it was processed by somebody\u0026rsquo;s brain and those instructions were followed to make delicious food.\nYet, I thought, we aren\u0026rsquo;t cows or sheep. We must prepare our ingredients in such a way that we can taste it, such that we can enjoy it and use its nutrients effectively. We must cook food, and a recipe is crucial to that.\nTherefore the idea came up. Make a recipe scroller. One can scroll in an infinite and never-ending list of recipes, and continuously discover new ones. They should also be able to specify their dietary needs and have their recipes in their feed tailored to them.\nso basically I came up with my idea over a samosa.\nInstead of quickly running up like a cartoon innovator, however, I decided to get a bottle of water and a mystery orange chicken sandwich nuked in the microwave (which was nice too), and I waited till the end of the break to really get my idea baked into my mind so I wouldn\u0026rsquo;t contemplate when I\u0026rsquo;d be productive\nThe second coding session I told my rough (at the time) idea to my new-found friends Jiwoo and the other people (I don\u0026rsquo;t know their names, I should have asked LMAO), and they seemed to love it.\nThe overall architecture The idea was to use Vue.js, and TypeScript. I would make a single-page application (an SPA) and use Vue Router as a way to swap out components naturally to emulate a multipage application, but with absolutely no lag when switching between pages. I\u0026rsquo;d also have a navbar just like a proper web app.\nIn this session, I didn\u0026rsquo;t really do much. I brainstormed potential features I wanted more, and I also browsed on RapidAPI to see what my API options were. I decided on using spoonacular, which would actually be my downfall (foreshadowing), and I got right to work on the settings.\nThe settings page My idea was to use the browser local storage. In JS, you can simply access it with this simple expression:\nwindow.localStorage This is a basic key-value store. You can store JavaScript primitives in it by simply issuing .setItem(key, value). This way, I was able to cook up a basic way to save persistent application state without a server. With that, I was able to make a simple diet setting item, which would save if you were vegan, vegetarian, non-veg, pescetarian and the like.\n// types.ts export enum Diet { NonVegetarian = \u0026#39;Non-Vegetarian\u0026#39;, Vegetarian = \u0026#39;Vegetarian\u0026#39;, Vegan = \u0026#39;Vegan\u0026#39;, LactoVegetarian = \u0026#39;Lacto-Vegetarian\u0026#39;, OvoVegetarian = \u0026#39;Ovo-Vegetarian\u0026#39;, Pescetarian = \u0026#39;Pescetarian\u0026#39; } I used a simple TypeScript enum for this. Then I used some some reactive state to save the currently selected diet option.\nimport { Diet } from \u0026#39;@/types.ts\u0026#39; const selectedDiet = ref\u0026lt;Diet\u0026gt;(Diet.Vegetarian) I made a diet bubble component that would display a div and a font awesome icon. Oh Wait-\nFont Awesome my good friend. As I would soon find out, there are actually 3 ways that one can go about displaying FA icons.\nUse the JS \u0026lt;script /\u0026gt; tag method, Download a bunch of CSS and import that Use a Node.js package and Vue components The first one didn\u0026rsquo;t work. A typical Vue SPA looks like this (not a complete directory tree):\n| +- node_modules +- src | | | +- main.ts | +- App.vue | +- router | | | +- index.ts +- package.json +- tsconfig.json +- vite.config.ts +- index.html +- env.d.ts I decided to put the script tag in the index.html where all the Vue code is eventually injected. That didn\u0026rsquo;t really work.\nI also tried downloading a bundle including CSS and all necessary fonts and SVGs, but that also didn\u0026rsquo;t work.\nIn the end, I decided to use the third method. I followed this guide, and icons were displaying just fine.\n..and it only took me till around 6:45 to finish. What an unproductive first day.\nBy the end of session 2, I had finished what the bubble was supposed to look like, but only one (the one that says Vegetarian). Unfortunately I do not have screenshots or a commit from when I finished that. Sorry ._.\nMore Vue The component is very simple. It looks like this:\n\u0026lt;script lang=\u0026#34;ts\u0026#34; setup\u0026gt; import type { Diet as DietT } from \u0026#39;@/types\u0026#39; import { Diet } from \u0026#39;@/types\u0026#39; import { far } from \u0026#39;@fortawesome/free-regular-svg-icons\u0026#39; import { fas } from \u0026#39;@fortawesome/free-solid-svg-icons\u0026#39; import { FontAwesomeIcon } from \u0026#39;@fortawesome/vue-fontawesome\u0026#39; // Component properties: TS+Vue allows one to pass an iface in as a generic type argument to define props. interface Props { diet: DietT showTick: boolean } defineProps\u0026lt;Props\u0026gt;() // Reactive state \u0026lt;/script\u0026gt; \u0026lt;template\u0026gt; \u0026lt;div class=\u0026#34;diet-bubble-container\u0026#34; :class=\u0026#34;$props.showTick ? \u0026#39;diet-bubble-container-green\u0026#39; : \u0026#39;diet-bubble-container-blue\u0026#39;\u0026#34; \u0026gt; \u0026lt;span class=\u0026#34;diet-bubble-container-icon\u0026#34;\u0026gt; \u0026lt;!-- using Vue\u0026#39;s v-if/v-else-if/v-else directives to do conditional rendering --\u0026gt; \u0026lt;FontAwesomeIcon v-if=\u0026#34;$props.diet == Diet.Vegetarian\u0026#34; :icon=\u0026#34;fas.faLeaf\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.diet == Diet.LactoVegetarian\u0026#34; :icon=\u0026#34;fas.faCow\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.diet == Diet.OvoVegetarian\u0026#34; :icon=\u0026#34;fas.faEgg\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.diet == Diet.Vegan\u0026#34; :icon=\u0026#34;fas.faSeedling\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.diet == Diet.NonVegetarian\u0026#34; :icon=\u0026#34;fas.faBacon\u0026#34; /\u0026gt; \u0026lt;FontAwesomeIcon v-else-if=\u0026#34;$props.diet == Diet.Pescetarian\u0026#34; :icon=\u0026#34;fas.faFish\u0026#34; /\u0026gt; \u0026lt;/span\u0026gt; \u0026lt;span class=\u0026#34;diet-bubble-container-diet-name\u0026#34;\u0026gt;{{ $props.diet }}\u0026lt;/span\u0026gt; \u0026lt;FontAwesomeIcon v-if=\u0026#34;$props.showTick\u0026#34; :icon=\u0026#34;far.faSquarePlus\u0026#34; class=\u0026#34;diet-bubble-container-x-icon\u0026#34; style=\u0026#34;color: var(--vt-c-white-soft)\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/template\u0026gt; This is excluding the CSS, of course (covered in the netx article). It simply renders 2 span elements, one with a font awesome icon that is conditionally rendered based on the enum\u0026rsquo;s state, and the other is just the enum name. I also included an icon that would pop up on hover, if a property showTick is set.\n\u0026lt;DividerItem\u0026gt;Your diet is:\u0026lt;/DividerItem\u0026gt; \u0026lt;div class=\u0026#34;diet-container\u0026#34;\u0026gt; \u0026lt;DietBubble :diet=\u0026#34;selectedDiet\u0026#34; :showTick=\u0026#34;false\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;br /\u0026gt; \u0026lt;DividerItem\u0026gt;Or set your diet:\u0026lt;/DividerItem\u0026gt; \u0026lt;div class=\u0026#34;all-diets-container\u0026#34; v-for=\u0026#34;(diet, index) in diets\u0026#34; :key=\u0026#34;index\u0026#34;\u0026gt; \u0026lt;button class=\u0026#34;null-button\u0026#34; @click=\u0026#34;setCurrentDiet(diet)\u0026#34;\u0026gt; \u0026lt;DietBubble :diet=\u0026#34;diet\u0026#34; :showTick=\u0026#34;true\u0026#34; v-if=\u0026#34;diet != selectedDiet\u0026#34; /\u0026gt; \u0026lt;/button\u0026gt; \u0026lt;/div\u0026gt; I made a class null-button which is basically a button with all the properties unset so I could put a div in it AND use the @click event handler just fine.\nI would render every possible diet (which is preset in the diets array) with the v-for directive, and if the DietBubble is clicked I would call setCurrentDiet with the diet the button is displaying. It is a closure that looks like this:\nconst setCurrentDiet = (diet: Diet) =\u0026gt; { selectedDiet.value = diet window.localStorage.setItem(\u0026#39;diet\u0026#39;, diet) } I used an arrow function (a closure) because you can capture the surrounding values just fine. In the end, clicking a diet bubble saves its state in local storage and displays it (through the reactive variable selectedDiet) Easy!\nDinner We were called to dinner at 7. Again, it was served on level 4. This time, I actually cared to go up (because I knew that it was going to be served there), and I was greeted by a wonderfully long line that stretched all the way from the counter into the corridor; luckily they had 2 lines for crowd control.\n(unfortunately I dont have pics. whoops-)\nAfter I claimed my food, I was actually not surprised that served us\u0026hellip;\nPizza Hut. Cheaper than catering I guess\u0026hellip;and it\u0026rsquo;s free! Can\u0026rsquo;t complain too much I guess-\nAs you probably already figured, this school does have 2 canteens, the level 3 and the level 4 one. Here\u0026rsquo;s the latter:\nVideo compressed to save space\nI\u0026rsquo;m quite surprised that GIIS has 2 canteens with proper seating and real tables. As an individual from places far and wide who must live with generic gray plastic chairs without armrests and perpetually stained glossy plastic tables, this was a real breath of fresh air. Don\u0026rsquo;t take your tables and chairs for granted!\nMiscellaneous I forgot to talk about the event\u0026rsquo;s design. Designer Ashwath and his team really put a lot of effort designing everything within the event!\nAt the registration, everybody was given merchandise. A band, lanyard and T-shirt. Not only that, every room had cool designs stuck on outside that almost aggressively shoves the fact that you\u0026rsquo;re at Hackathon X and not any other event but almost in a kind way. Even the slides were really carefully designed; there was quite a bit of attention to detail.\nHeres how the merch looks:\n(I lost my bracelet :skull:)\nUnfortunately, I don\u0026rsquo;t have any photos of the rooms, or any of the other designs; It really was in my subconscious until now. I do still think it still deserves a mention.\nI\u0026rsquo;m also ending this article early because there\u0026rsquo;s still a lot to talk about. However, I have already gotten to \u0026gt;1900 words (according to neovim at least), so I\u0026rsquo;ll discuss the second day and other such things in the next and most likely last article.\nStay tuned.\nUPDATE: Here\u0026rsquo;s the next part.\nfootnotes I really like Indian food. I really dont care if its north or south, because I\u0026rsquo;ve tried it all. And I love it. Millions must consume Indian food. ","permalink":"http://ezntek.com/posts/the-giis-hackathon-x-a-review-part-2-20240729t1317/","summary":"\u003ch2 id=\"recap\"\u003eRecap\u003c/h2\u003e\n\u003cp\u003eIf you haven\u0026rsquo;t checked the first article out, please do \u003ca href=\"https://ezntek.com/posts/the-giis-hackathon-x-a-review-part-1-20240726t1322/\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThis article will cover mainly the events on day one, along other appropriate\nstories fit for this article. Source code shown is in the state that it is\nin right now (i.e. the complete app). I only set up git later on in the\ndevelopment process due to time reasons. Some components may not be explained,\nthat is to be expected.\u003c/p\u003e","title":"The GIIS Hackathon X - My Experience (part 2)"},{"content":"Why? In the student homebase representative group chat, there arrived a message. A certain message leading people to visit a certain site.\nThat would be this.\nThis would be a hackathon. An event where programmers (or non programmers) (foreshadowing) would come together and code in teams while competing with other teams to win prizes and recognition from other programmers in the event. Usually, one would have to pay for these kinds of events, but this one was actually free. And held close to my home. So I decided, why not? I\u0026rsquo;d just have to go to the Global International Indian School that my peers who came from that school had said great things about. Could anyting go wrong?\nFirst impressions Upon arrival, there was nobody at the front door to greet anybody. Nobody, just security guards and and two large buildings in front of me (One world international school was also right next door).\nI actually had to look in the distance to what looked like the atrium area, to see some dudes changing into their hackathon X jerseys. Naturally, I entered through the side gate to find out that the aforementioned \u0026ldquo;MPH\u0026rdquo; area was actually just the entrance area.\nEntering the building, it felt more like a hospital than anything. An oddly geometric wooden panel greeted me with a softly lit set of hexagonal ceiling lights, angular edges on the walls, the shebang. It was clear to me that some sort of big corporation built this campus (which is correct, this school actually has various campuses scattered all across the globe) and the designers obviously paid A LOT of attention to designing this place well.\nRegistration This is where I hit the first pothole. There was actually a lot of people \u0026ldquo;lining\u0026rdquo; up, surprisingly. I expected much fewer participants but obviously I was wrong.\nI wouldn\u0026rsquo;t really call this a line, but I\u0026rsquo;d actually call this a crowd.\nA really packed one. Nobody seemed to know what line up meant (I mean, they were all small children, but that\u0026rsquo;s besides the point). The workers and even some adult had to yell at the crowd collectively and tell them to get into 3 lines. What formed were three distinct enough crowds, loosely bunched up. Everybody seemed to cut the queue, and nothing was done. Finally, some organizer decided to ask a bunch of people if they had registered yet, and directed them to counters and helped the line move along. I was one of those people and I was told to go to the leftmost counter, with a group already doing their registration.\nAnnoyingly, at the counter, they actually couldn\u0026rsquo;t find my name in their wonderfully structured spreadsheet. I had to show them my whole inbox for them to see the two acceptance letters (those who were rejected got one acceptance and one rejection letter due to some system error), and they somehow didn\u0026rsquo;t have me on the list.\nOkay, I thought, so I told them all my details, but as they were filling out my full name, my name autocompleted. That means that my name was already on the system. I was index 3, and they somehow seemed to miss that :p\nThe opening ceremony Oh dear this did not go well.\nAccording to the itinerary given to us on our tags and on the slack group, it was supposed to begin at 2:00 PM sharp. Everything seemed to be on track, until it hit 2PM. When we first all did our registration, we were told to go back to the first floor to do the opening ceremony, but instead, people were in chaos. The organizers and/or volunteers had told us to go to the third floor canteen area, but the volunteers on the third floor told us to go to the first floor. After two laps, we were told to go to the third floor and stay there. Instead, only a small group of people went there to get cotton candy, and they all seemed to just go back to the second floor lounging area, where everybody seemed to be.\nAs I am writing this paragraph, it is already 2:21PM, and no ceremony was announced yet. It has been an hour and twenty minutes, with absolutely no progress done to the event. What a bummer.\nLater It got delayed again. We were all allowed in at around 14:32PM; but turns out, all the \u0026ldquo;internal\u0026rdquo; students from the campus that the hackathon was hosted at didnt know how to sit properly, and they all sat too high up in the booths. Everyone was told to move as far down as possible, which took a while. There was also an organizer yelling at all the students on the microphone. How fun.\nIt took until around 14:46 until the event really got around to strating. It took multiple people, including all the execs of the school coming to get the crowd to quiet down. Surprisingly took very very long.\nAnnouncements (note: this section is unpolished as fuck because I wrote while they were speaking)\nBefore he (the announcer, \u0026ldquo;Karthik\u0026rdquo;) got around to the actual announcement, He decided to talk about his experience in 2018, where his brand new laptop was destroyed because some teammate of his tripped over the charging cable :skull:\nSpeaker 1 One Nishant Patil came onto the stage, and\u0026hellip;No theme for a while. He shared his experiences after he got elected as the VP of the tech club, including how he witnessed the prices going up. Apparently, he found hack club, a 501(c)(3) nonprofit organization which oversees multiple hackathons globally. The VP and his friends also apparently began crying when they found out that DBS (the bank) ended up being able to ssponsor them in the event.\nNo theme, though.\nSpeaker 2 Aditya Bairy, the president of the Tech club came up to the stage, and annouced the theme is\u0026hellip;\nNot yet. He talked about how he was happy about how multiple student groups came from multiple countries even (oh), came to GIIS participate in the hackathon. He also talked about how the sacrifices he had to make of rejecting young programmers hurted him and made him \u0026ldquo;sad\u0026rdquo;. He also told us more talented and older programmers to form our own events, if it suited us ;)\nThe Theme Life on all elements. More on my brainstorming later.\nThe Rubric criteria marks description Creativity 25% How innovative it is, and Technical complexity 25% The complexity, with comments and documentation Functionality and usability 25% User-friedliness and real-life applications Pitching 15% Being able to answer questions regading the code Software-dependent marks 10% AI would be data representation, Game development would be game design, app development would be the UI, and web dev would be the layout. The event is declared open! At 15:12:50 (ish), the pricipal declared the event open. yay.\nHow it works Contestants are split into two major categories, seniors and juniors. Juniors are in grades 6 through 8, and seniors 9 through 12. The main difference are the skill levels between the two major categories, and due to the Juniors most likely having less exeprience with programming in general, they are be allowed to use tools like Scratch and Thunkable. The seniors would have more skill in general, so they weren\u0026rsquo;t allowed scratch, but by the end, nobody actually used it (which is a good thing.)\nI was placed into the senior team. I saw my fellow students from places far and wide there, which were also placed into the senior team. I genuinely believed that they, or the older kids would do better than me, as my self-confidence wasn\u0026rsquo;t too high at the time of me joining. I did not know any sort of toolkit or framework that I could use to create a product, so I kinda had to raw-dog it.\nFirst steps We were made to go to the Third floor coding rooms. After 2 flights worth of escalator, we would have to make a U turn from the canteen into an auto-opening door, which would lead us to the coding rooms.\nAt first, I went into S3-07 (keep this one in mind), which was actually supposed to be a Junior coding room, as I\u0026rsquo;d soon find out. I had already placed my bag down on an empty space on a table mounted to a pillar, and have already grabbed a chair. Oh well, I guess this would be the last time I\u0026rsquo;d be in a room like this.\nI went to the library instead, where we were told to go. At this point, I had absolutely no idea as to what I would build. I wanted to use Rust+GTK+Libadwaita at first, but due to the theme being so incredibly vague, it would be completely useless to build something with it. Additionally, this framework is considerably harder than doing web development, because it uses completely foreign concepts. GTK usually recommends you to write XML to describe your components, and include it in your Rust project as a resource. However, styling and positioning would also be difficult due to GTK CSS being limited and components (widgets) being a pain in general. One could also not subclass a GObject and therefore a gtk::Widget easily without 2 modules per subclass and about 30,000 macros, so I ultimately decided against it.\nI was back to square one. At this point, I really didn\u0026rsquo;t know what I wanted to do. I could make a game in C and raylib, but game development would be my downfall because I\u0026rsquo;d have to make art. A graphics library would also be a pain overall, and if I wanted any chance of winning, I would have to learn and therefore master a game engine.\nThere was only really one option left for me, which is web development. I had actually feared this before the event, so I did some practice beforehand with Vue.js, but not nearly enough for a full app. That means that if I didn\u0026rsquo;t want to be a disappointment, I would have to basically master the basics of Vue while in the Hackathon.\nI\u0026rsquo;ll address my experience with Vue and my overall experience in this 2 day event, along with all the other fun things offered alongside it in the next article. At around 1,900 words, this is already a really long article. I promise, the next one will be just as good if not miles ahead of this one.\nUPDATE: here is the next post.\nRandom things I heard Some adult: Oh, you joined the hackathon as a participant?\nSome child: yes! I did! this would be a great chance for me to demonstrate and develop my technical skills-\nThat same adult: Why didn\u0026rsquo;t you join as an organizer?\nSome random tall guy who obviously is an outsider to the school: WOW THIS CAMPUS IS AMAZING\nThe guest speaker mentioned the AI buzzword. ha ha ha ha ha-\nSome random things I saw why are there students from places far and wide™ [1] the canteen is actually high tech lmao why can\u0026rsquo;t our school not force a monopoly on us and force us to pay absurd prices for food? this school has different stalls with different food options. oh wow. the slide authors coldn\u0026rsquo;t spell \u0026ldquo;principal\u0026rdquo; (they spelt it \u0026ldquo;principle\u0026rdquo;). footnotes Our school song begins with \u0026ldquo;From places far and wide, we come to make friends and live here side by side\u0026rdquo;. You may see references later throughout the post, I am not sure. ","permalink":"http://ezntek.com/posts/the-giis-hackathon-x-a-review-part-1-20240726t1322/","summary":"\u003ch2 id=\"why\"\u003eWhy?\u003c/h2\u003e\n\u003cp\u003eIn the student homebase representative group chat, there arrived a message. A\ncertain message leading people to visit a certain site.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Announcement message\" loading=\"lazy\" src=\"/img/hackathon/announcement.png\"\u003e\u003c/p\u003e\n\u003cp\u003eThat would be \u003ca href=\"https://hackathonx.net\"\u003ethis\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThis would be a hackathon. An event where programmers (or non programmers)\n(foreshadowing) would come together and code in teams while competing with other\nteams to win prizes and recognition from other programmers in the event.\nUsually, one would have to pay for these kinds of events, but this one was\nactually free. And held close to my home. So I decided, why not? I\u0026rsquo;d just have\nto go to the \u003cem\u003eGlobal International Indian School\u003c/em\u003e that my peers who came from\nthat school had said \u003cem\u003egreat things\u003c/em\u003e about. Could anyting go wrong?\u003c/p\u003e","title":"The GIIS Hackathon X - My Experience (part 1)"},{"content":"Economics revision guide NOTE: This guide was NOT WRITTEN BY ME, but by Markus Clausen. I do not take the economics course.\nyou can find the PDF here.\n","permalink":"http://ezntek.com/posts/econs-revision-20240509t110029/","summary":"\u003ch2 id=\"economics-revision-guide\"\u003eEconomics revision guide\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003eNOTE:\u003c/strong\u003e\u003c/em\u003e This guide was NOT WRITTEN BY ME, but by Markus Clausen. I do not take the economics course.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://ezntek.com/revision/econs_g1_s2.pdf\"\u003eyou can find the PDF here.\u003c/a\u003e\u003c/p\u003e\n\u003cscript src=\"https://utteranc.es/client.js\"\n        repo=\"ezntek/ezntek.github.io\"\n        issue-term=\"title\"\n        label=\"comments\"\n        theme=\"github-dark\"\n        crossorigin=\"anonymous\"\n        async\u003e\n\u003c/script\u003e","title":"Econs Revision (20240509T110029)"},{"content":"Da link here\nFor the uneducated: Our school provides the IGCSE Comp Sci 0478 course (instead of ICT now), but the school\u0026rsquo;s selection of teachers are suboptimal. Despite their best efforts to teach us as much as they can, computer science is a hard subject for many and they may need a revision guide to help them.\nTested topics From the homework post,\nChapter 2 Data transmission structure of data packets \u0026amp; contents packet switching methods of transmission (serial, parallel, HD \u0026amp; FD) USB error detection - parity check, checksum, echocheck check digits - ISBN 13 and Modulo 11 (know how GENERATE and RECALCULATE) NO CALCULATOR ALLOWED ARQ Encryption Chapter 3 Hardware CPU Dual core \u0026amp; quad core processors Von neumann architecture control bus, address bus, data bus fetch-decode-execute cycle instruction sets embedded systems qr codes RAM, ROM, DRAM, SRAM virtual memory MAC addresses router Chapter 9 Databases structure of flat file - fields, records, validation data types use of primary keys SQL scripts to query data ","permalink":"http://ezntek.com/posts/comp-sci-revision-20240509t0944/","summary":"\u003ch2 id=\"da-link\"\u003eDa link\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://ezntek.com/revision/comp_sci_g1_s2.html\"\u003ehere\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"for-the-uneducated\"\u003eFor the uneducated:\u003c/h2\u003e\n\u003cp\u003eOur school provides the IGCSE Comp Sci 0478 course (instead of ICT now), but the school\u0026rsquo;s selection of\nteachers are \u003cem\u003esuboptimal\u003c/em\u003e. Despite their best efforts to teach us as much as they can, computer science\nis a hard subject for many and they may need a revision guide to help them.\u003c/p\u003e\n\u003ch2 id=\"tested-topics\"\u003eTested topics\u003c/h2\u003e\n\u003cp\u003eFrom the homework post,\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch3 id=\"chapter-2-data-transmission\"\u003eChapter 2 Data transmission\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003estructure of data packets \u0026amp; contents\u003c/li\u003e\n\u003cli\u003epacket switching\u003c/li\u003e\n\u003cli\u003emethods of transmission (serial, parallel, HD \u0026amp; FD)\u003c/li\u003e\n\u003cli\u003eUSB\u003c/li\u003e\n\u003cli\u003eerror detection - parity check, checksum, echocheck\u003c/li\u003e\n\u003cli\u003echeck digits - ISBN 13 and Modulo 11 (know how GENERATE and RECALCULATE) NO CALCULATOR ALLOWED\u003c/li\u003e\n\u003cli\u003eARQ\u003c/li\u003e\n\u003cli\u003eEncryption\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"chapter-3-hardware\"\u003eChapter 3 Hardware\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eCPU Dual core \u0026amp; quad core processors\u003c/li\u003e\n\u003cli\u003eVon neumann architecture\u003c/li\u003e\n\u003cli\u003econtrol bus, address bus, data bus\u003c/li\u003e\n\u003cli\u003efetch-decode-execute cycle\u003c/li\u003e\n\u003cli\u003einstruction sets\u003c/li\u003e\n\u003cli\u003eembedded systems\u003c/li\u003e\n\u003cli\u003eqr codes\u003c/li\u003e\n\u003cli\u003eRAM, ROM, DRAM, SRAM\u003c/li\u003e\n\u003cli\u003evirtual memory\u003c/li\u003e\n\u003cli\u003eMAC addresses\u003c/li\u003e\n\u003cli\u003erouter\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"chapter-9-databases\"\u003eChapter 9 Databases\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003estructure of flat file - fields, records, validation\u003c/li\u003e\n\u003cli\u003edata types\u003c/li\u003e\n\u003cli\u003euse of primary keys\u003c/li\u003e\n\u003cli\u003eSQL scripts to query data\u003c/li\u003e\n\u003c/ul\u003e\u003c/blockquote\u003e\n\u003cscript src=\"https://utteranc.es/client.js\"\n     repo=\"ezntek/ezntek.github.io\"\n     issue-term=\"title\"\n     label=\"comments\"\n     theme=\"github-dark\"\n     crossorigin=\"anonymous\"\n     async\u003e\n\u003c/script\u003e","title":"Computer Science G1 revision guide"},{"content":"About Me who Hey, I\u0026rsquo;m Eason, otherwise known as eggman or ezntek. I\u0026rsquo;m a 16-year-old programmer living in Singapore.\nNOTE: I barely update this page. If you want proper introductions, might as well e-mail me at eason@ezntek.com\ntechnologies/languages C Rust Python Vue.js and TypeScript (to an extent) C++ (to an extent) Java (to an extent) zig (to an extent) hobbies coding computer hardware/bios mods playing on sitaku (wiki) researching transport networks/transit nerd activities cooking (surprisingly) cycling why can\u0026rsquo;t i code a lot? I\u0026rsquo;m a student. No inspiration No project ideas No motivation what do i use I use (ranked in order of preference/usage frequency):\ncomputer operating system ThinkPad T420 (i7-3632QM) Arch Linux+niri (libreboot) ThinkPad T480 (i7-8650U) Arch Linux+GONME Workstation (ASUS Z790-p+i7-14700KF+RX5600XT) Artix Linux (dinit) ThinkPad X230 (i7-3520M) Arch Linux+XFCE (coreboot tianocore) ThinKPad L460 (i5-6200U) No OS currently ThinkPad T440p (i7-4712MQ) Arch Linux+KDE Plasma (libreboot) ThinkPad X200/X201 FrankenPad (i5-560M) Arch Linux+niri (coreboot) ThinkPad X230 (i5-3320M) Linux Mint (lent to others) (coreboot) ","permalink":"http://ezntek.com/about/","summary":"\u003ch1 id=\"about-me\"\u003eAbout Me\u003c/h1\u003e\n\u003ch2 id=\"who\"\u003ewho\u003c/h2\u003e\n\u003cp\u003eHey, I\u0026rsquo;m Eason, otherwise known as eggman or ezntek. I\u0026rsquo;m a 16-year-old programmer living in Singapore.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003eNOTE: I barely update this page. If you want proper introductions, might as well e-mail me at \u003ca href=\"mailto:eason@ezntek.com\"\u003eeason@ezntek.com\u003c/a\u003e\u003c/strong\u003e\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"technologieslanguages\"\u003etechnologies/languages\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eC\u003c/li\u003e\n\u003cli\u003eRust\u003c/li\u003e\n\u003cli\u003ePython\u003c/li\u003e\n\u003cli\u003eVue.js and TypeScript (to an extent)\u003c/li\u003e\n\u003cli\u003eC++ (to an extent)\u003c/li\u003e\n\u003cli\u003eJava (to an extent)\u003c/li\u003e\n\u003cli\u003ezig (to an extent)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"hobbies\"\u003ehobbies\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ecoding\u003c/li\u003e\n\u003cli\u003ecomputer hardware/bios mods\u003c/li\u003e\n\u003cli\u003eplaying on \u003ca href=\"https://ezntek.com/sitaku\"\u003esitaku\u003c/a\u003e \u003ca href=\"https://sitaku.miraheze.org\"\u003e(wiki)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eresearching transport networks/transit nerd activities\u003c/li\u003e\n\u003cli\u003ecooking (surprisingly)\u003c/li\u003e\n\u003cli\u003ecycling\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"why-cant-i-code-a-lot\"\u003ewhy can\u0026rsquo;t i code a lot?\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eI\u0026rsquo;m a student.\u003c/li\u003e\n\u003cli\u003eNo inspiration\u003c/li\u003e\n\u003cli\u003eNo project ideas\u003c/li\u003e\n\u003cli\u003eNo motivation\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"what-do-i-use\"\u003ewhat do i use\u003c/h2\u003e\n\u003cp\u003eI use (ranked in order of preference/usage frequency):\u003c/p\u003e","title":""},{"content":"Revision Resources (mostly for OFS) The IGCSE Computer Science (Theory) Revision Guide (Full), Revision 5 IGCSE Computer Science: Arrays and Iteration Workbook(booklet?) The OFS IGCSE Computer Science G2 Exam Revision Reference Guide (2025-2027), Revision Three The OFS IGCSE Computer Science G1 Guide to Programming and Logic Gates (2026-2028), Revision Four The IGCSE Pseudocode to Python Reference Guide, Revision Seven ","permalink":"http://ezntek.com/revision/","summary":"\u003ch1 id=\"revision-resources-mostly-for-ofs\"\u003eRevision Resources (mostly for OFS)\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/doc/CSRG_Full_Rev5.pdf\"\u003eThe IGCSE Computer Science (Theory) Revision Guide (Full), Revision 5\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://ezntek.com/doc/igcse_cs_arrays_iteration_workbook.pdf\"\u003eIGCSE Computer Science: Arrays and Iteration Workbook(booklet?)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://ezntek.com/doc/CSRG_G2_Rev4.pdf\"\u003eThe OFS IGCSE Computer Science G2 Exam Revision Reference Guide (2025-2027), Revision Three\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://ezntek.com/doc/CSRG_G1_Rev4.pdf\"\u003eThe OFS IGCSE Computer Science G1 Guide to Programming and Logic Gates (2026-2028), Revision Four\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://ezntek.com/doc/pseudocodereference_rev7.pdf\"\u003eThe IGCSE Pseudocode to Python Reference Guide, Revision Seven\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":""},{"content":"Sitaku Sitaku is a minecraft server I play on (a lot).\nAbove: A render of Dechora-dera, Distaye on 2C.\n\u0026hellip;It is not really a minecraft server in the classic sense. Instead, it is more like a collection of minecraft worlds with a community overlaid on top of it. Sitaku always will have a survival and creative world active, and map resets are done whenever they are necessary.\nThe current maps that we play on (active) are 9s (the ninth survival) and 2c (the second creative). I am most active on 2c (because it is objectively better).\nWhat do I do? Rails.\nAbove: The comprehensive (planning) map of the Republic of Sitaku\nA lot of this is under construction, especially the heavy rail. But that is my job. I drew the map and planned the rail network, and it is my job, along with my friend Kasreti to build.\nThe capital region railway (the Sitaku City metro) is the dense area with station bubbles, and station distances ar anywhere from 500 to 800 blocks.\nAnything without station bubbles are out-of-capital, meaning that those are heavy rail stations. This means that they can span much longer distances, the shortest distance between stations on the network being about 1750 blocks (I think).\nI also do graphic design; I draw all the maps and station art for the subway stations, with the exemption of heavy rail, which Kasreti does.\n","permalink":"http://ezntek.com/sitaku/","summary":"\u003ch1 id=\"sitaku\"\u003eSitaku\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://sitaku.miraheze.org\"\u003eSitaku\u003c/a\u003e is a minecraft server I play on (a lot).\u003c/p\u003e\n\u003cimg src=\"/img/japan2c.png\" alt=\"A render of Dechora-dera, Distaye on 2C\" width=\"100%\" /\u003e\n\u003cp\u003e\u003cem\u003eAbove: A render of Dechora-dera, Distaye on 2C.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u0026hellip;It is not really a minecraft server in the classic sense. Instead, it is more like a\ncollection of minecraft worlds with a community overlaid on top of it. Sitaku always will have a\nsurvival and creative world active, and map resets are done whenever they are necessary.\u003c/p\u003e","title":""},{"content":"What I\u0026rsquo;ve Built NOTE: this is extremely out of date! might as well check out my GitHub.\nbrickout (wip ig) beancode (wip) tpfanspeed (will rewrite in C) dictionaryparser (will write web app) whowlang (will definitely rewrite and rename) beanbattery (stale) youareanidiot (stale) mathparser (unfinished) cursython (bullshit) n64romconvert dotfiles my dotfiles SITAKU!! Not mine, technically, but I\u0026rsquo;ll put it here for now.\n","permalink":"http://ezntek.com/stuff/","summary":"\u003ch1 id=\"what-ive-built\"\u003eWhat I\u0026rsquo;ve Built\u003c/h1\u003e\n\u003cp\u003e\u003cem\u003e\u003cstrong\u003eNOTE: this is extremely out of date! might as well check out my \u003ca href=\"https://github.com/ezntek\"\u003eGitHub.\u003c/a\u003e\u003c/strong\u003e\u003c/em\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/brickout\"\u003ebrickout\u003c/a\u003e (wip ig)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/beancode\"\u003ebeancode\u003c/a\u003e (wip)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/tpfanspeed\"\u003etpfanspeed\u003c/a\u003e (will rewrite in C)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/dictionaryparser\"\u003edictionaryparser\u003c/a\u003e (will write web app)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/whowlang\"\u003ewhowlang\u003c/a\u003e (will definitely rewrite and rename)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/BeanwareHQ/beanbattery\"\u003ebeanbattery\u003c/a\u003e (stale)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/youareanidiot\"\u003eyouareanidiot\u003c/a\u003e (stale)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/mathparser\"\u003emathparser\u003c/a\u003e (unfinished)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/cursython\"\u003ecursython\u003c/a\u003e (bullshit)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/n64romconvert\"\u003en64romconvert\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ezntek/dotfiles\"\u003edotfiles\u003c/a\u003e my dotfiles\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sitaku\"\u003eSITAKU!!\u003c/h2\u003e\n\u003cp\u003eNot mine, technically, but I\u0026rsquo;ll put it \u003ca href=\"/sitaku/\"\u003ehere\u003c/a\u003e for now.\u003c/p\u003e","title":""},{"content":"lol you found it Here are some tools for my conlang, Tuluwasa, that I speak with friends.\nKaithifier ","permalink":"http://ezntek.com/tuluwasa/","summary":"\u003ch1 id=\"lol-you-found-it\"\u003elol you found it\u003c/h1\u003e\n\u003cp\u003eHere are some tools for my conlang, Tuluwasa, that I speak with friends.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/tuluwasa/kaithifier.html\"\u003eKaithifier\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":""}]